Blender V4.5
MOD_grease_pencil_dash.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 "BLI_array_utils.hh"
10#include "BLI_index_range.hh"
11#include "BLI_span.hh"
12#include "BLI_string.h"
13#include "BLI_string_utf8.h"
14
15#include "DNA_defaults.h"
16#include "DNA_modifier_types.h"
17
18#include "BKE_curves.hh"
19#include "BKE_geometry_set.hh"
20#include "BKE_grease_pencil.hh"
21#include "BKE_instances.hh"
22#include "BKE_modifier.hh"
23#include "BKE_screen.hh"
24
25#include "BLO_read_write.hh"
26
27#include "UI_interface.hh"
28#include "UI_resources.hh"
29
30#include "BLT_translation.hh"
31
32#include "WM_api.hh"
33#include "WM_types.hh"
34
35#include "RNA_access.hh"
36#include "RNA_prototypes.hh"
37
39#include "MOD_ui_common.hh"
40
42
43namespace blender {
44
45static void init_data(ModifierData *md)
46{
47 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
48
50
52 modifier::greasepencil::init_influence_data(&dmd->influence, false);
53
55 STRNCPY_UTF8(ds->name, DATA_("Segment"));
56 dmd->segments_array = ds;
57 dmd->segments_num = 1;
58}
59
60static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
61{
62 const auto *dmd = reinterpret_cast<const GreasePencilDashModifierData *>(md);
63 auto *tmmd = reinterpret_cast<GreasePencilDashModifierData *>(target);
64
66
68 modifier::greasepencil::copy_influence_data(&dmd->influence, &tmmd->influence, flag);
69
70 tmmd->segments_array = static_cast<GreasePencilDashModifierSegment *>(
71 MEM_dupallocN(dmd->segments_array));
72}
73
74static void free_data(ModifierData *md)
75{
76 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
78
79 MEM_SAFE_FREE(dmd->segments_array);
80}
81
82static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
83{
84 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
85 modifier::greasepencil::foreach_influence_ID_link(&dmd->influence, ob, walk, user_data);
86}
87
88static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
89{
90 const auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
91 /* Enable if at least one segment has non-zero length. */
92 for (const GreasePencilDashModifierSegment &dash_segment : dmd->segments()) {
93 if (dash_segment.dash + dash_segment.gap - 1 > 0) {
94 return false;
95 }
96 }
97 return true;
98}
99
100static int floored_modulo(const int a, const int b)
101{
102 return a - math::floor(float(a) / float(b)) * b;
103}
104
105/* Combined segment info used by all strokes. */
115
117{
118 PatternInfo info;
119 for (const GreasePencilDashModifierSegment &dash_segment : dmd.segments()) {
120 info.length += dash_segment.dash + dash_segment.gap;
121 }
122
123 info.segments.reinitialize(dmd.segments().size());
124 info.cyclic.reinitialize(dmd.segments().size());
125 info.material.reinitialize(dmd.segments().size());
126 info.radius.reinitialize(dmd.segments().size());
127 info.opacity.reinitialize(dmd.segments().size());
128 info.offset = floored_modulo(dmd.dash_offset, info.length);
129
130 /* Store segments as ranges. */
131 IndexRange dash_range(0);
132 IndexRange gap_range(0);
133 for (const int i : dmd.segments().index_range()) {
134 const GreasePencilDashModifierSegment &dash_segment = dmd.segments()[i];
135 dash_range = gap_range.after(dash_segment.dash);
136 gap_range = dash_range.after(dash_segment.gap);
137 info.segments[i] = dash_range;
138 info.cyclic[i] = dash_segment.flag & MOD_GREASE_PENCIL_DASH_USE_CYCLIC;
139 info.material[i] = dash_segment.mat_nr;
140 info.radius[i] = dash_segment.radius;
141 info.opacity[i] = dash_segment.opacity;
142 }
143 return info;
144}
145
146/* Returns the segment covering the given index, including repetitions. */
147static int find_dash_segment(const PatternInfo &pattern_info, const int index)
148{
149 const int repeat = index / pattern_info.length;
150 const int segments_num = pattern_info.segments.size();
151
152 const int local_index = index - repeat * pattern_info.length;
153 for (const int i : pattern_info.segments.index_range().drop_back(1)) {
154 const IndexRange segment = pattern_info.segments[i];
155 const IndexRange next_segment = pattern_info.segments[i + 1];
156 if (local_index >= segment.start() && local_index < next_segment.start()) {
157 return i + repeat * segments_num;
158 }
159 }
160 return segments_num - 1 + repeat * segments_num;
161}
162
168static void foreach_dash(const PatternInfo &pattern_info,
169 const IndexRange src_points,
170 const bool cyclic,
171 FunctionRef<void(IndexRange, bool, int, float, float)> fn)
172{
173 const int points_num = src_points.size();
174 const int segments_num = pattern_info.segments.size();
175
176 const int first_segment = find_dash_segment(pattern_info, pattern_info.offset);
177 const int last_segment = find_dash_segment(pattern_info, pattern_info.offset + points_num - 1);
178 BLI_assert(first_segment < segments_num);
179 BLI_assert(last_segment >= first_segment);
180
181 const IndexRange all_segments = IndexRange(first_segment, last_segment - first_segment + 1);
182 for (const int i : all_segments) {
183 const int repeat = i / segments_num;
184 const int segment_index = i - repeat * segments_num;
185 const IndexRange range = pattern_info.segments[segment_index].shift(repeat *
186 pattern_info.length);
187
188 const int64_t point_shift = src_points.start() - pattern_info.offset;
189 const int64_t min_point = src_points.start();
190 const int64_t max_point = cyclic ? src_points.one_after_last() : src_points.last();
191 const int64_t start = std::clamp(range.start() + point_shift, min_point, max_point);
192 const int64_t end = std::clamp(range.one_after_last() + point_shift, min_point, max_point + 1);
193
194 IndexRange points(start, end - start);
195 if (!points.is_empty()) {
196 fn(points,
197 pattern_info.cyclic[segment_index],
198 pattern_info.material[segment_index],
199 pattern_info.radius[segment_index],
200 pattern_info.opacity[segment_index]);
201 }
202 }
203}
204
206 const bke::CurvesGeometry &src_curves,
207 const IndexMask &curves_mask)
208{
209 const bke::AttributeAccessor src_attributes = src_curves.attributes();
210 const VArray<bool> src_cyclic = src_curves.cyclic();
211 const VArray<int> src_material = *src_attributes.lookup_or_default(
212 "material_index", bke::AttrDomain::Curve, 0);
213 const VArray<float> src_radius = *src_attributes.lookup_or_default<float>(
214 "radius", bke::AttrDomain::Point, 0.01f);
215 const VArray<float> src_opacity = *src_attributes.lookup_or_default<float>(
216 "opacity", bke::AttrDomain::Point, 1.0f);
217
218 /* Count new curves and points. */
219 int dst_point_num = 0;
220 int dst_curve_num = 0;
221 curves_mask.foreach_index([&](const int64_t src_curve_i) {
222 const IndexRange src_points = src_curves.points_by_curve()[src_curve_i];
223
224 foreach_dash(pattern_info,
225 src_points,
226 src_cyclic[src_curve_i],
227 [&](const IndexRange copy_points,
228 bool /*cyclic*/,
229 int /*material*/,
230 float /*radius*/,
231 float /*opacity*/) {
232 dst_point_num += copy_points.size();
233 dst_curve_num += 1;
234 });
235 });
236
237 bke::CurvesGeometry dst_curves(dst_point_num, dst_curve_num);
238 bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
239 bke::SpanAttributeWriter<bool> dst_cyclic = dst_attributes.lookup_or_add_for_write_span<bool>(
240 "cyclic", bke::AttrDomain::Curve);
241 bke::SpanAttributeWriter<int> dst_material = dst_attributes.lookup_or_add_for_write_span<int>(
242 "material_index", bke::AttrDomain::Curve);
243 bke::SpanAttributeWriter<float> dst_radius = dst_attributes.lookup_or_add_for_write_span<float>(
244 "radius", bke::AttrDomain::Point);
245 bke::SpanAttributeWriter<float> dst_opacity = dst_attributes.lookup_or_add_for_write_span<float>(
246 "opacity", bke::AttrDomain::Point);
247 /* Map each destination point and curve to its source. */
248 Array<int> src_point_indices(dst_point_num);
249 Array<int> src_curve_indices(dst_curve_num);
250
251 {
252 /* Start at curve offset and add points for each dash. */
253 IndexRange dst_point_range(0);
254 int dst_curve_i = 0;
255 auto add_dash_curve = [&](const int src_curve,
256 const IndexRange src_points,
257 const IndexRange copy_points,
258 bool cyclic,
259 int material,
260 float radius,
261 float opacity) {
262 dst_point_range = dst_point_range.after(copy_points.size());
263 dst_curves.offsets_for_write()[dst_curve_i] = dst_point_range.start();
264
265 if (src_points.contains(copy_points.last())) {
266 array_utils::fill_index_range(src_point_indices.as_mutable_span().slice(dst_point_range),
267 int(copy_points.start()));
268 }
269 else {
270 /* Cyclic curve. */
272 src_point_indices.as_mutable_span().slice(dst_point_range.drop_back(1)),
273 int(copy_points.start()));
274 src_point_indices[dst_point_range.last()] = src_points.first();
275 }
276 src_curve_indices[dst_curve_i] = src_curve;
277 dst_cyclic.span[dst_curve_i] = cyclic;
278 dst_material.span[dst_curve_i] = material >= 0 ? material : src_material[src_curve];
279 for (const int i : dst_point_range) {
280 dst_radius.span[i] = src_radius[src_point_indices[i]] * radius;
281 }
282 if (dst_opacity) {
283 for (const int i : dst_point_range) {
284 dst_opacity.span[i] = src_opacity[src_point_indices[i]] * opacity;
285 }
286 }
287
288 ++dst_curve_i;
289 };
290
291 curves_mask.foreach_index([&](const int64_t src_curve_i) {
292 const IndexRange src_points = src_curves.points_by_curve()[src_curve_i];
293 foreach_dash(pattern_info,
294 src_points,
295 src_cyclic[src_curve_i],
296 [&](const IndexRange copy_points,
297 bool cyclic,
298 int material,
299 float radius,
300 float opacity) {
301 add_dash_curve(
302 src_curve_i, src_points, copy_points, cyclic, material, radius, opacity);
303 });
304 });
305 if (dst_curve_i > 0) {
306 /* Last offset entry is total point count. */
307 dst_curves.offsets_for_write()[dst_curve_i] = dst_point_range.one_after_last();
308 }
309 }
310
311 bke::gather_attributes(src_attributes,
314 bke::attribute_filter_from_skip_ref({"radius", "opacity"}),
315 src_point_indices,
316 dst_attributes);
317 bke::gather_attributes(src_attributes,
320 bke::attribute_filter_from_skip_ref({"cyclic", "material_index"}),
321 src_curve_indices,
322 dst_attributes);
323
324 dst_cyclic.finish();
325 dst_material.finish();
326 dst_radius.finish();
327 dst_opacity.finish();
328 dst_curves.update_curve_types();
329
330 return dst_curves;
331}
332
334 const ModifierEvalContext &ctx,
335 const PatternInfo &pattern_info,
337{
339 const bke::CurvesGeometry &src_curves = drawing.strokes();
340 if (src_curves.curve_num == 0) {
341 return;
342 }
343 /* Selected source curves. */
344 IndexMaskMemory curve_mask_memory;
346 ctx.object, src_curves, dmd.influence, curve_mask_memory);
347 const IndexMask unselected_mask = curves_mask.complement(src_curves.curves_range(),
348 curve_mask_memory);
350 src_curves, unselected_mask, {});
351
352 bke::CurvesGeometry dashed_curves = create_dashes(pattern_info, src_curves, curves_mask);
353
354 Curves *masked_curves_id = bke::curves_new_nomain(dashed_curves);
355 Curves *unselected_curves_id = bke::curves_new_nomain(unselected_curves);
356 bke::GeometrySet masked_geo = bke::GeometrySet::from_curves(masked_curves_id);
357 bke::GeometrySet unselected_geo = bke::GeometrySet::from_curves(unselected_curves_id);
358 bke::GeometrySet joined_geo = geometry::join_geometries({unselected_geo, masked_geo}, {});
359
360 if (!joined_geo.has_curves()) {
361 drawing.strokes_for_write() = {};
362 }
363 else {
364 drawing.strokes_for_write() = std::move(joined_geo.get_curves_for_write()->geometry.wrap());
365 }
366 drawing.tag_topology_changed();
367}
368
370 const ModifierEvalContext *ctx,
371 bke::GeometrySet *geometry_set)
372{
374
375 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
376
377 if (!geometry_set->has_grease_pencil()) {
378 return;
379 }
380 GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write();
381 const int frame = grease_pencil.runtime->eval_frame;
382
383 const PatternInfo pattern_info = get_pattern_info(*dmd);
384
385 IndexMaskMemory mask_memory;
387 grease_pencil, dmd->influence, mask_memory);
388
390 grease_pencil, layer_mask, frame);
392 drawings, [&](Drawing *drawing) { modify_drawing(*dmd, *ctx, pattern_info, *drawing); });
393}
394
395static void panel_draw(const bContext *C, Panel *panel)
396{
397 uiLayout *layout = panel->layout;
398
399 PointerRNA ob_ptr;
401 auto *dmd = static_cast<GreasePencilDashModifierData *>(ptr->data);
402
403 uiLayoutSetPropSep(layout, true);
404
405 layout->prop(ptr, "dash_offset", UI_ITEM_NONE, std::nullopt, ICON_NONE);
406
407 uiLayout *row = &layout->row(false);
408 uiLayoutSetPropSep(row, false);
409
410 uiTemplateList(row,
411 (bContext *)C,
412 "MOD_UL_grease_pencil_dash_modifier_segments",
413 "",
414 ptr,
415 "segments",
416 ptr,
417 "segment_active_index",
418 nullptr,
419 3,
420 10,
421 0,
422 1,
424
425 uiLayout *col = &row->column(false);
426 uiLayout *sub = &col->column(true);
427 sub->op("OBJECT_OT_grease_pencil_dash_modifier_segment_add", "", ICON_ADD);
428 sub->op("OBJECT_OT_grease_pencil_dash_modifier_segment_remove", "", ICON_REMOVE);
429 col->separator();
430 sub = &col->column(true);
432 sub, "", ICON_TRIA_UP, "OBJECT_OT_grease_pencil_dash_modifier_segment_move", "type", "UP");
434 "",
435 ICON_TRIA_DOWN,
436 "OBJECT_OT_grease_pencil_dash_modifier_segment_move",
437 "type",
438 "DOWN");
439
440 if (dmd->segment_active_index >= 0 && dmd->segment_active_index < dmd->segments_num) {
441 PointerRNA ds_ptr = RNA_pointer_create_discrete(ptr->owner_id,
442 &RNA_GreasePencilDashModifierSegment,
443 &dmd->segments()[dmd->segment_active_index]);
444
445 sub = &layout->column(true);
446 sub->prop(&ds_ptr, "dash", UI_ITEM_NONE, std::nullopt, ICON_NONE);
447 sub->prop(&ds_ptr, "gap", UI_ITEM_NONE, std::nullopt, ICON_NONE);
448
449 sub = &layout->column(false);
450 sub->prop(&ds_ptr, "radius", UI_ITEM_NONE, std::nullopt, ICON_NONE);
451 sub->prop(&ds_ptr, "opacity", UI_ITEM_NONE, std::nullopt, ICON_NONE);
452 sub->prop(&ds_ptr, "material_index", UI_ITEM_NONE, std::nullopt, ICON_NONE);
453 sub->prop(&ds_ptr, "use_cyclic", UI_ITEM_NONE, std::nullopt, ICON_NONE);
454 }
455
456 if (uiLayout *influence_panel = layout->panel_prop(
457 C, ptr, "open_influence_panel", IFACE_("Influence")))
458 {
461 }
462
464}
465
466static void segment_list_item_draw(uiList * /*ui_list*/,
467 const bContext * /*C*/,
468 uiLayout *layout,
469 PointerRNA * /*idataptr*/,
470 PointerRNA *itemptr,
471 int /*icon*/,
472 PointerRNA * /*active_dataptr*/,
473 const char * /*active_propname*/,
474 int /*index*/,
475 int /*flt_flag*/)
476{
477 uiLayout *row = &layout->row(true);
478 row->prop(itemptr, "name", UI_ITEM_R_NO_BG, "", ICON_NONE);
479}
480
481static void panel_register(ARegionType *region_type)
482{
484
485 uiListType *list_type = MEM_callocN<uiListType>("Grease Pencil Dash modifier segments");
486 STRNCPY(list_type->idname, "MOD_UL_grease_pencil_dash_modifier_segments");
488 WM_uilisttype_add(list_type);
489}
490
491static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
492{
493 const auto *dmd = reinterpret_cast<const GreasePencilDashModifierData *>(md);
494
496 modifier::greasepencil::write_influence_data(writer, &dmd->influence);
497
499 writer, GreasePencilDashModifierSegment, dmd->segments_num, dmd->segments_array);
500}
501
502static void blend_read(BlendDataReader *reader, ModifierData *md)
503{
504 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
505
506 modifier::greasepencil::read_influence_data(reader, &dmd->influence);
507
509 reader, GreasePencilDashModifierSegment, dmd->segments_num, &dmd->segments_array);
510}
511
512} // namespace blender
513
515 /*idname*/ "GreasePencilDash",
516 /*name*/ N_("Dot Dash"),
517 /*struct_name*/ "GreasePencilDashModifierData",
518 /*struct_size*/ sizeof(GreasePencilDashModifierData),
519 /*srna*/ &RNA_GreasePencilDashModifierData,
523 /*icon*/ ICON_MOD_DASH,
524
525 /*copy_data*/ blender::copy_data,
526
527 /*deform_verts*/ nullptr,
528 /*deform_matrices*/ nullptr,
529 /*deform_verts_EM*/ nullptr,
530 /*deform_matrices_EM*/ nullptr,
531 /*modify_mesh*/ nullptr,
532 /*modify_geometry_set*/ blender::modify_geometry_set,
533
534 /*init_data*/ blender::init_data,
535 /*required_data_mask*/ nullptr,
536 /*free_data*/ blender::free_data,
537 /*is_disabled*/ blender::is_disabled,
538 /*update_depsgraph*/ nullptr,
539 /*depends_on_time*/ nullptr,
540 /*depends_on_normals*/ nullptr,
541 /*foreach_ID_link*/ blender::foreach_ID_link,
542 /*foreach_tex_link*/ nullptr,
543 /*free_runtime_data*/ nullptr,
544 /*panel_register*/ blender::panel_register,
545 /*blend_write*/ blender::blend_write,
546 /*blend_read*/ blender::blend_read,
547};
548
549blender::Span<GreasePencilDashModifierSegment> GreasePencilDashModifierData::segments() const
550{
551 return {this->segments_array, this->segments_num};
552}
553
554blender::MutableSpan<GreasePencilDashModifierSegment> GreasePencilDashModifierData::segments()
555{
556 return {this->segments_array, this->segments_num};
557}
Low-level operations for curves.
Low-level operations for grease pencil.
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_AcceptsGreasePencil
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
#define BLI_assert(a)
Definition BLI_assert.h:46
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define STRNCPY_UTF8(dst, src)
#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 BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define IFACE_(msgid)
#define DATA_(msgid)
#define DNA_struct_default_get(struct_name)
#define DNA_struct_default_alloc(struct_name)
@ MOD_GREASE_PENCIL_DASH_USE_CYCLIC
@ eModifierType_GreasePencilDash
static bool is_disabled
ModifierTypeInfo modifierType_GreasePencilDash
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
#define C
Definition RandGen.cpp:29
void uiTemplateList(uiLayout *layout, const bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, blender::StringRefNull propname, PointerRNA *active_dataptr, const char *active_propname, const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns, enum uiTemplateListFlags flags)
@ UI_TEMPLATE_LIST_FLAG_NONE
@ UI_ITEM_R_NO_BG
void uiItemEnumO_string(uiLayout *layout, blender::StringRef name, int icon, blender::StringRefNull opname, blender::StringRefNull propname, const char *value_str)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
long long int int64_t
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:398
constexpr int64_t one_after_last() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr IndexRange after(int64_t n) const
constexpr int64_t start() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
VArray< bool > cyclic() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
uint col
#define MEM_SAFE_FREE(v)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void fill_index_range(MutableSpan< T > span, const T start=0)
CurvesGeometry curves_copy_curve_selection(const CurvesGeometry &curves, const IndexMask &curves_to_copy, const AttributeFilter &attribute_filter)
auto attribute_filter_from_skip_ref(const Span< StringRef > skip)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
Curves * curves_new_nomain(int points_num, int curves_num)
bke::GeometrySet join_geometries(Span< bke::GeometrySet > geometries, const bke::AttributeFilter &attribute_filter, const std::optional< Span< bke::GeometryComponent::Type > > &component_types_to_join=std::nullopt)
T floor(const T &a)
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_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)
static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil, const std::optional< StringRef > tree_node_name_filter, const std::optional< int > layer_pass_filter, const bool layer_filter_invert, const bool layer_pass_filter_invert, IndexMaskMemory &memory)
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 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)
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:56
static int floored_modulo(const int a, const int b)
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 segment_list_item_draw(uiList *, const bContext *, uiLayout *layout, PointerRNA *, PointerRNA *itemptr, int, PointerRNA *, const char *, int, int)
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 free_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void foreach_dash(const PatternInfo &pattern_info, const IndexRange src_points, const bool cyclic, FunctionRef< void(IndexRange, bool, int, float, float)> fn)
static bke::CurvesGeometry create_dashes(const PatternInfo &pattern_info, const bke::CurvesGeometry &src_curves, const IndexMask &curves_mask)
static void modify_drawing(const GreasePencilArrayModifierData &mmd, const ModifierEvalContext &ctx, bke::greasepencil::Drawing &drawing)
static int find_dash_segment(const PatternInfo &pattern_info, const int index)
static PatternInfo get_pattern_info(const GreasePencilDashModifierData &dmd)
static bool is_disabled(const Scene *, ModifierData *md, bool)
static void blend_read(BlendDataReader *reader, ModifierData *md)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
CurvesGeometry geometry
GreasePencilModifierInfluenceData influence
GreasePencilDashModifierSegment * segments_array
GreasePencilRuntimeHandle * runtime
Definition DNA_ID.h:404
struct uiLayout * layout
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GreasePencil * get_grease_pencil_for_write()
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
PanelLayout panel_prop(const bContext *C, PointerRNA *open_prop_owner, blender::StringRefNull open_prop_name)
uiLayout & column(bool align)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
char idname[BKE_ST_MAXNAME]
uiListDrawItemFunc draw_item
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4227
bool WM_uilisttype_add(uiListType *ult)
uint8_t flag
Definition wm_window.cc:139