Blender V5.0
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"
29#include "UI_resources.hh"
30
31#include "BLT_translation.hh"
32
33#include "WM_api.hh"
34#include "WM_types.hh"
35
36#include "RNA_access.hh"
37#include "RNA_prototypes.hh"
38
40#include "MOD_ui_common.hh"
41
43
44namespace blender {
45
46static void init_data(ModifierData *md)
47{
48 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
49
51
53 modifier::greasepencil::init_influence_data(&dmd->influence, false);
54
56 STRNCPY_UTF8(ds->name, DATA_("Segment"));
57 dmd->segments_array = ds;
58 dmd->segments_num = 1;
59}
60
61static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
62{
63 const auto *dmd = reinterpret_cast<const GreasePencilDashModifierData *>(md);
64 auto *tmmd = reinterpret_cast<GreasePencilDashModifierData *>(target);
65
67
69 modifier::greasepencil::copy_influence_data(&dmd->influence, &tmmd->influence, flag);
70
71 tmmd->segments_array = static_cast<GreasePencilDashModifierSegment *>(
72 MEM_dupallocN(dmd->segments_array));
73}
74
75static void free_data(ModifierData *md)
76{
77 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
79
80 MEM_SAFE_FREE(dmd->segments_array);
81}
82
83static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
84{
85 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
86 modifier::greasepencil::foreach_influence_ID_link(&dmd->influence, ob, walk, user_data);
87}
88
89static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
90{
91 const auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
92 /* Enable if at least one segment has non-zero length. */
93 for (const GreasePencilDashModifierSegment &dash_segment : dmd->segments()) {
94 if (dash_segment.dash + dash_segment.gap - 1 > 0) {
95 return false;
96 }
97 }
98 return true;
99}
100
101static int floored_modulo(const int a, const int b)
102{
103 return a - math::floor(float(a) / float(b)) * b;
104}
105
106/* Combined segment info used by all strokes. */
116
118{
119 PatternInfo info;
120 for (const GreasePencilDashModifierSegment &dash_segment : dmd.segments()) {
121 info.length += dash_segment.dash + dash_segment.gap;
122 }
123
124 info.segments.reinitialize(dmd.segments().size());
125 info.cyclic.reinitialize(dmd.segments().size());
126 info.material.reinitialize(dmd.segments().size());
127 info.radius.reinitialize(dmd.segments().size());
128 info.opacity.reinitialize(dmd.segments().size());
129 info.offset = floored_modulo(dmd.dash_offset, info.length);
130
131 /* Store segments as ranges. */
132 IndexRange dash_range(0);
133 IndexRange gap_range(0);
134 for (const int i : dmd.segments().index_range()) {
135 const GreasePencilDashModifierSegment &dash_segment = dmd.segments()[i];
136 dash_range = gap_range.after(dash_segment.dash);
137 gap_range = dash_range.after(dash_segment.gap);
138 info.segments[i] = dash_range;
139 info.cyclic[i] = dash_segment.flag & MOD_GREASE_PENCIL_DASH_USE_CYCLIC;
140 info.material[i] = dash_segment.mat_nr;
141 info.radius[i] = dash_segment.radius;
142 info.opacity[i] = dash_segment.opacity;
143 }
144 return info;
145}
146
147/* Returns the segment covering the given index, including repetitions. */
148static int find_dash_segment(const PatternInfo &pattern_info, const int index)
149{
150 const int repeat = index / pattern_info.length;
151 const int segments_num = pattern_info.segments.size();
152
153 const int local_index = index - repeat * pattern_info.length;
154 for (const int i : pattern_info.segments.index_range().drop_back(1)) {
155 const IndexRange segment = pattern_info.segments[i];
156 const IndexRange next_segment = pattern_info.segments[i + 1];
157 if (local_index >= segment.start() && local_index < next_segment.start()) {
158 return i + repeat * segments_num;
159 }
160 }
161 return segments_num - 1 + repeat * segments_num;
162}
163
169static void foreach_dash(const PatternInfo &pattern_info,
170 const IndexRange src_points,
171 const bool cyclic,
172 FunctionRef<void(IndexRange, bool, int, float, float)> fn)
173{
174 const int points_num = src_points.size();
175 const int segments_num = pattern_info.segments.size();
176
177 const int first_segment = find_dash_segment(pattern_info, pattern_info.offset);
178 const int last_segment = find_dash_segment(pattern_info, pattern_info.offset + points_num - 1);
179 BLI_assert(first_segment < segments_num);
180 BLI_assert(last_segment >= first_segment);
181
182 const IndexRange all_segments = IndexRange(first_segment, last_segment - first_segment + 1);
183 for (const int i : all_segments) {
184 const int repeat = i / segments_num;
185 const int segment_index = i - repeat * segments_num;
186 const IndexRange range = pattern_info.segments[segment_index].shift(repeat *
187 pattern_info.length);
188
189 const int64_t point_shift = src_points.start() - pattern_info.offset;
190 const int64_t min_point = src_points.start();
191 const int64_t max_point = cyclic ? src_points.one_after_last() : src_points.last();
192 const int64_t start = std::clamp(range.start() + point_shift, min_point, max_point);
193 const int64_t end = std::clamp(range.one_after_last() + point_shift, min_point, max_point + 1);
194
195 IndexRange points(start, end - start);
196 if (!points.is_empty()) {
197 fn(points,
198 pattern_info.cyclic[segment_index],
199 pattern_info.material[segment_index],
200 pattern_info.radius[segment_index],
201 pattern_info.opacity[segment_index]);
202 }
203 }
204}
205
207 const bke::CurvesGeometry &src_curves,
208 const IndexMask &curves_mask)
209{
210 const bke::AttributeAccessor src_attributes = src_curves.attributes();
211 const VArray<bool> src_cyclic = src_curves.cyclic();
212 const VArray<int> src_material = *src_attributes.lookup_or_default(
213 "material_index", bke::AttrDomain::Curve, 0);
214 const VArray<float> src_radius = *src_attributes.lookup_or_default<float>(
215 "radius", bke::AttrDomain::Point, 0.01f);
216 const VArray<float> src_opacity = *src_attributes.lookup_or_default<float>(
217 "opacity", bke::AttrDomain::Point, 1.0f);
218
219 /* Count new curves and points. */
220 int dst_point_num = 0;
221 int dst_curve_num = 0;
222 curves_mask.foreach_index([&](const int64_t src_curve_i) {
223 const IndexRange src_points = src_curves.points_by_curve()[src_curve_i];
224
225 foreach_dash(pattern_info,
226 src_points,
227 src_cyclic[src_curve_i],
228 [&](const IndexRange copy_points,
229 bool /*cyclic*/,
230 int /*material*/,
231 float /*radius*/,
232 float /*opacity*/) {
233 dst_point_num += copy_points.size();
234 dst_curve_num += 1;
235 });
236 });
237
238 bke::CurvesGeometry dst_curves(dst_point_num, dst_curve_num);
239 bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
240 bke::SpanAttributeWriter<bool> dst_cyclic = dst_attributes.lookup_or_add_for_write_span<bool>(
241 "cyclic", bke::AttrDomain::Curve);
242 bke::SpanAttributeWriter<int> dst_material = dst_attributes.lookup_or_add_for_write_span<int>(
243 "material_index", bke::AttrDomain::Curve);
244 bke::SpanAttributeWriter<float> dst_radius = dst_attributes.lookup_or_add_for_write_span<float>(
245 "radius", bke::AttrDomain::Point);
246 bke::SpanAttributeWriter<float> dst_opacity = dst_attributes.lookup_or_add_for_write_span<float>(
247 "opacity", bke::AttrDomain::Point);
248 /* Map each destination point and curve to its source. */
249 Array<int> src_point_indices(dst_point_num);
250 Array<int> src_curve_indices(dst_curve_num);
251
252 {
253 /* Start at curve offset and add points for each dash. */
254 IndexRange dst_point_range(0);
255 int dst_curve_i = 0;
256 auto add_dash_curve = [&](const int src_curve,
257 const IndexRange src_points,
258 const IndexRange copy_points,
259 bool cyclic,
260 int material,
261 float radius,
262 float opacity) {
263 dst_point_range = dst_point_range.after(copy_points.size());
264 dst_curves.offsets_for_write()[dst_curve_i] = dst_point_range.start();
265
266 if (src_points.contains(copy_points.last())) {
267 array_utils::fill_index_range(src_point_indices.as_mutable_span().slice(dst_point_range),
268 int(copy_points.start()));
269 }
270 else {
271 /* Cyclic curve. */
273 src_point_indices.as_mutable_span().slice(dst_point_range.drop_back(1)),
274 int(copy_points.start()));
275 src_point_indices[dst_point_range.last()] = src_points.first();
276 }
277 src_curve_indices[dst_curve_i] = src_curve;
278 dst_cyclic.span[dst_curve_i] = cyclic;
279 dst_material.span[dst_curve_i] = material >= 0 ? material : src_material[src_curve];
280 for (const int i : dst_point_range) {
281 dst_radius.span[i] = src_radius[src_point_indices[i]] * radius;
282 }
283 if (dst_opacity) {
284 for (const int i : dst_point_range) {
285 dst_opacity.span[i] = src_opacity[src_point_indices[i]] * opacity;
286 }
287 }
288
289 ++dst_curve_i;
290 };
291
292 curves_mask.foreach_index([&](const int64_t src_curve_i) {
293 const IndexRange src_points = src_curves.points_by_curve()[src_curve_i];
294 foreach_dash(pattern_info,
295 src_points,
296 src_cyclic[src_curve_i],
297 [&](const IndexRange copy_points,
298 bool cyclic,
299 int material,
300 float radius,
301 float opacity) {
302 add_dash_curve(
303 src_curve_i, src_points, copy_points, cyclic, material, radius, opacity);
304 });
305 });
306 if (dst_curve_i > 0) {
307 /* Last offset entry is total point count. */
308 dst_curves.offsets_for_write()[dst_curve_i] = dst_point_range.one_after_last();
309 }
310 }
311
312 bke::gather_attributes(src_attributes,
315 bke::attribute_filter_from_skip_ref({"radius", "opacity"}),
316 src_point_indices,
317 dst_attributes);
318 bke::gather_attributes(src_attributes,
321 bke::attribute_filter_from_skip_ref({"cyclic", "material_index"}),
322 src_curve_indices,
323 dst_attributes);
324
325 dst_cyclic.finish();
326 dst_material.finish();
327 dst_radius.finish();
328 dst_opacity.finish();
329 dst_curves.update_curve_types();
330
331 return dst_curves;
332}
333
335 const ModifierEvalContext &ctx,
336 const PatternInfo &pattern_info,
338{
340 const bke::CurvesGeometry &src_curves = drawing.strokes();
341 if (src_curves.curve_num == 0) {
342 return;
343 }
344 /* Selected source curves. */
345 IndexMaskMemory curve_mask_memory;
347 ctx.object, src_curves, dmd.influence, curve_mask_memory);
348 const IndexMask unselected_mask = curves_mask.complement(src_curves.curves_range(),
349 curve_mask_memory);
351 src_curves, unselected_mask, {});
352
353 bke::CurvesGeometry dashed_curves = create_dashes(pattern_info, src_curves, curves_mask);
354
355 Curves *masked_curves_id = bke::curves_new_nomain(dashed_curves);
356 Curves *unselected_curves_id = bke::curves_new_nomain(unselected_curves);
357 bke::GeometrySet masked_geo = bke::GeometrySet::from_curves(masked_curves_id);
358 bke::GeometrySet unselected_geo = bke::GeometrySet::from_curves(unselected_curves_id);
359 bke::GeometrySet joined_geo = geometry::join_geometries({unselected_geo, masked_geo}, {});
360
361 if (!joined_geo.has_curves()) {
362 drawing.strokes_for_write() = {};
363 }
364 else {
365 drawing.strokes_for_write() = std::move(joined_geo.get_curves_for_write()->geometry.wrap());
366 }
367 drawing.tag_topology_changed();
368}
369
371 const ModifierEvalContext *ctx,
372 bke::GeometrySet *geometry_set)
373{
375
376 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
377
378 if (!geometry_set->has_grease_pencil()) {
379 return;
380 }
381 GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write();
382 const int frame = grease_pencil.runtime->eval_frame;
383
384 const PatternInfo pattern_info = get_pattern_info(*dmd);
385
386 IndexMaskMemory mask_memory;
388 grease_pencil, dmd->influence, mask_memory);
389
391 grease_pencil, layer_mask, frame);
393 drawings, [&](Drawing *drawing) { modify_drawing(*dmd, *ctx, pattern_info, *drawing); });
394}
395
396static void panel_draw(const bContext *C, Panel *panel)
397{
398 uiLayout *layout = panel->layout;
399
400 PointerRNA ob_ptr;
402 auto *dmd = static_cast<GreasePencilDashModifierData *>(ptr->data);
403
404 layout->use_property_split_set(true);
405
406 layout->prop(ptr, "dash_offset", UI_ITEM_NONE, std::nullopt, ICON_NONE);
407
408 uiLayout *row = &layout->row(false);
409 row->use_property_split_set(false);
410
411 uiTemplateList(row,
412 (bContext *)C,
413 "MOD_UL_grease_pencil_dash_modifier_segments",
414 "",
415 ptr,
416 "segments",
417 ptr,
418 "segment_active_index",
419 nullptr,
420 3,
421 10,
422 0,
423 1,
425
426 uiLayout *col = &row->column(false);
427 uiLayout *sub = &col->column(true);
428 sub->op("OBJECT_OT_grease_pencil_dash_modifier_segment_add", "", ICON_ADD);
429 sub->op("OBJECT_OT_grease_pencil_dash_modifier_segment_remove", "", ICON_REMOVE);
430 col->separator();
431 sub = &col->column(true);
432 PointerRNA op_ptr = sub->op(
433 "OBJECT_OT_grease_pencil_dash_modifier_segment_move", "", ICON_TRIA_UP);
434 RNA_enum_set(&op_ptr, "type", /* blender::ed::object::DashSegmentMoveDirection::Up */ -1);
435 op_ptr = sub->op("OBJECT_OT_grease_pencil_dash_modifier_segment_move", "", ICON_TRIA_DOWN);
436 RNA_enum_set(&op_ptr, "type", /* blender::ed::object::DashSegmentMoveDirection::Down */ 1);
437
438 if (dmd->segment_active_index >= 0 && dmd->segment_active_index < dmd->segments_num) {
439 PointerRNA ds_ptr = RNA_pointer_create_discrete(ptr->owner_id,
440 &RNA_GreasePencilDashModifierSegment,
441 &dmd->segments()[dmd->segment_active_index]);
442
443 sub = &layout->column(true);
444 sub->prop(&ds_ptr, "dash", UI_ITEM_NONE, std::nullopt, ICON_NONE);
445 sub->prop(&ds_ptr, "gap", UI_ITEM_NONE, std::nullopt, ICON_NONE);
446
447 sub = &layout->column(false);
448 sub->prop(&ds_ptr, "radius", UI_ITEM_NONE, std::nullopt, ICON_NONE);
449 sub->prop(&ds_ptr, "opacity", UI_ITEM_NONE, std::nullopt, ICON_NONE);
450 sub->prop(&ds_ptr, "material_index", UI_ITEM_NONE, std::nullopt, ICON_NONE);
451 sub->prop(&ds_ptr, "use_cyclic", UI_ITEM_NONE, std::nullopt, ICON_NONE);
452 }
453
454 if (uiLayout *influence_panel = layout->panel_prop(
455 C, ptr, "open_influence_panel", IFACE_("Influence")))
456 {
459 }
460
462}
463
464static void segment_list_item_draw(uiList * /*ui_list*/,
465 const bContext * /*C*/,
466 uiLayout *layout,
467 PointerRNA * /*idataptr*/,
468 PointerRNA *itemptr,
469 int /*icon*/,
470 PointerRNA * /*active_dataptr*/,
471 const char * /*active_propname*/,
472 int /*index*/,
473 int /*flt_flag*/)
474{
475 uiLayout *row = &layout->row(true);
476 row->prop(itemptr, "name", UI_ITEM_R_NO_BG, "", ICON_NONE);
477}
478
479static void panel_register(ARegionType *region_type)
480{
482
483 uiListType *list_type = MEM_callocN<uiListType>("Grease Pencil Dash modifier segments");
484 STRNCPY(list_type->idname, "MOD_UL_grease_pencil_dash_modifier_segments");
486 WM_uilisttype_add(list_type);
487}
488
489static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
490{
491 const auto *dmd = reinterpret_cast<const GreasePencilDashModifierData *>(md);
492
494 modifier::greasepencil::write_influence_data(writer, &dmd->influence);
495
497 writer, GreasePencilDashModifierSegment, dmd->segments_num, dmd->segments_array);
498}
499
500static void blend_read(BlendDataReader *reader, ModifierData *md)
501{
502 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(md);
503
504 modifier::greasepencil::read_influence_data(reader, &dmd->influence);
505
507 reader, GreasePencilDashModifierSegment, dmd->segments_num, &dmd->segments_array);
508}
509
510} // namespace blender
511
513 /*idname*/ "GreasePencilDash",
514 /*name*/ N_("Dot Dash"),
515 /*struct_name*/ "GreasePencilDashModifierData",
516 /*struct_size*/ sizeof(GreasePencilDashModifierData),
517 /*srna*/ &RNA_GreasePencilDashModifierData,
521 /*icon*/ ICON_MOD_DASH,
522
523 /*copy_data*/ blender::copy_data,
524
525 /*deform_verts*/ nullptr,
526 /*deform_matrices*/ nullptr,
527 /*deform_verts_EM*/ nullptr,
528 /*deform_matrices_EM*/ nullptr,
529 /*modify_mesh*/ nullptr,
530 /*modify_geometry_set*/ blender::modify_geometry_set,
531
532 /*init_data*/ blender::init_data,
533 /*required_data_mask*/ nullptr,
534 /*free_data*/ blender::free_data,
535 /*is_disabled*/ blender::is_disabled,
536 /*update_depsgraph*/ nullptr,
537 /*depends_on_time*/ nullptr,
538 /*depends_on_normals*/ nullptr,
539 /*foreach_ID_link*/ blender::foreach_ID_link,
540 /*foreach_tex_link*/ nullptr,
541 /*free_runtime_data*/ nullptr,
542 /*panel_register*/ blender::panel_register,
543 /*blend_write*/ blender::blend_write,
544 /*blend_read*/ blender::blend_read,
545};
546
547blender::Span<GreasePencilDashModifierSegment> GreasePencilDashModifierData::segments() const
548{
549 return {this->segments_array, this->segments_num};
550}
551
552blender::MutableSpan<GreasePencilDashModifierSegment> GreasePencilDashModifierData::segments()
553{
554 return {this->segments_array, this->segments_num};
555}
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:693
#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
#define MEM_SAFE_FREE(v)
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
#define UI_ITEM_NONE
long long int int64_t
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
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, AttrType 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, AttrType 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
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, bool allow_merging_instance_references=true)
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)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
CurvesGeometry geometry
GreasePencilModifierInfluenceData influence
GreasePencilDashModifierSegment * segments_array
GreasePencilRuntimeHandle * runtime
Definition DNA_ID.h:414
struct uiLayout * layout
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GreasePencil * get_grease_pencil_for_write()
PanelLayout panel_prop(const bContext *C, PointerRNA *open_prop_owner, blender::StringRefNull open_prop_name)
uiLayout & column(bool align)
uiLayout & row(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void use_property_split_set(bool value)
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:4238
bool WM_uilisttype_add(uiListType *ult)
uint8_t flag
Definition wm_window.cc:145