37#include "RNA_prototypes.hh"
83 if (mmd->object !=
nullptr) {
106 const int time_alignment,
107 const int transition,
109 const bool clamp_points,
118 float max_length = 0;
120 const bool stroke_cyclic = cyclic[stroke];
128 r_curves_num = r_points_num = 0;
129 factor_to_keep = std::clamp(factor_to_keep, 0.0f, 1.0f);
132 auto get_stroke_factor = [&](
const float factor,
const int index) {
133 const bool stroke_cyclic = cyclic[index];
135 if (total_length == 0) {
136 return factor > 0.5f ? 1.0f : 0.0f;
138 const float max_factor = max_length / total_length;
141 return std::clamp(factor * max_factor, 0.0f, 1.0f);
143 return factor * max_factor;
146 const float min_factor = max_factor - 1.0f;
147 const float use_factor = factor * max_factor;
149 return std::clamp(use_factor - min_factor, 0.0f, 1.0f);
151 return use_factor - min_factor;
160 const float local_factor =
select[curve] ? get_stroke_factor(factor_to_keep, curve) : 1.0f;
161 const int num_points = points_by_curve[curve].
size() * local_factor;
162 result[curve] = num_points;
164 r_points_num += num_points;
165 if (num_points > 0) {
176 const int time_alignment,
177 const int transition,
179 const float factor_start,
180 const float factor_opacity,
181 const float factor_radii,
184 int dst_curves_num, dst_points_num;
185 const bool has_fade = factor_start != factor;
187 curves, selection, time_alignment, transition, factor,
true, dst_curves_num, dst_points_num);
188 if (dst_curves_num == 0) {
227 if (!point_counts_to_keep[curve]) {
230 const IndexRange points = points_by_curve[curve];
231 dst_offsets[next_curve] = point_counts_to_keep[curve];
232 const int curve_size = points.
size();
234 auto get_fade_weight = [&](
const int local_index) {
235 const float fade_range = std::abs(ends_per_curve[curve] - starts_per_curve[curve]);
237 const float factor_from_start = local_index - curve_size + ends_per_curve[curve];
238 return 1.0f - std::clamp(factor_from_start / fade_range, 0.0f, 1.0f);
240 const float factor_from_start = local_index - starts_per_curve[curve];
241 return std::clamp(factor_from_start / fade_range, 0.0f, 1.0f);
244 const int extra_offset = is_vanishing ? points.
size() - point_counts_to_keep[curve] : 0;
245 for (
const int stroke_point :
IndexRange(point_counts_to_keep[curve])) {
246 const int src_point_index = points.
first() + extra_offset + stroke_point;
248 const float fade_weight = get_fade_weight(extra_offset + stroke_point);
249 opacities[src_point_index] = opacities[src_point_index] *
250 (1.0f - fade_weight * factor_opacity);
251 radii[src_point_index] = radii[src_point_index] * (1.0f - fade_weight * factor_radii);
252 if (!weights.
span.is_empty()) {
253 weights.
span[src_point_index] = fade_weight;
256 dst_to_src_point[next_point] = src_point_index;
259 dst_to_src_curve[next_curve] = curve;
269 gather_attributes(src_attributes,
275 gather_attributes(src_attributes,
289 const int transition,
291 const bool clamp_points,
301 factor_to_keep = std::clamp(factor_to_keep, 0.0f, 1.0f);
308 const int untouched_points_num = points_by_curve.
total_size() - effective_points_num;
309 effective_points_num *= factor_to_keep;
310 effective_points_num += untouched_points_num;
312 r_points_num = effective_points_num;
318 int counted_points_num = 0;
320 const int stroke = is_vanishing ? stroke_count -
i - 1 :
i;
321 if (
select[stroke] && counted_points_num >= effective_points_num) {
324 counted_points_num += points_by_curve[stroke].
size();
332 const int transition,
334 const float factor_start,
335 const float factor_opacity,
336 const float factor_radii,
339 const bool has_fade = factor_start != factor;
340 int dst_curves_num, dst_points_num;
341 int start_points_num, end_points_num, dummy_curves_num;
343 curves, selection, transition, factor,
true, dst_curves_num, dst_points_num);
345 if (dst_curves_num == 0) {
350 curves, selection, transition, factor_start,
false, dummy_curves_num, start_points_num);
352 curves, selection, transition, factor,
false, dummy_curves_num, end_points_num);
369 int next_curve = 1, next_point = 0;
372 for (
const int point : points_by_curve[stroke]) {
373 dst_to_src_point[next_point] = point;
376 dst_to_src_curve[next_curve - 1] = stroke;
377 dst_offsets[next_curve] = next_point;
382 bool done_scanning =
false;
384 const int stroke = is_vanishing ? stroke_count -
i - 1 :
i;
385 if (done_scanning || next_point >= dst_points_num) {
386 done_scanning =
true;
390 auto get_fade_weight = [&](
const int next_point_count) {
391 return std::clamp(
float(next_point_count - start_points_num) /
392 float(
abs(end_points_num - start_points_num)),
397 const IndexRange points = points_by_curve[stroke];
398 for (
const int point : points) {
399 const int local_index = point - points.
first();
400 const int src_point_index = is_vanishing ? points.
last() - local_index : point;
401 dst_to_src_point[next_point] = src_point_index;
404 const float fade_weight = get_fade_weight(next_point);
405 opacities[src_point_index] = opacities[src_point_index] *
406 (1.0f - fade_weight * factor_opacity);
407 radii[src_point_index] = radii[src_point_index] * (1.0f - fade_weight * factor_radii);
408 if (!weights.
span.is_empty()) {
409 weights.
span[src_point_index] = fade_weight;
414 if (next_point >= dst_points_num) {
415 done_scanning =
true;
419 dst_offsets[next_curve] = next_point;
420 dst_to_src_curve[next_curve - 1] =
i;
425 BLI_assert(next_curve == (dst_curves_num + 1));
431 gather_attributes(src_attributes,
437 gather_attributes(src_attributes,
456 const float3 center =
object.object_to_world().location();
466 const IndexRange points = points_by_curve[stroke];
470 distances[stroke].index = stroke;
471 distances[stroke].selected =
select[stroke];
475 distances.
begin(), distances.
end(), [](Pair &a, Pair &
b) { return a.value < b.value; });
479 new_order[
i] = distances[
i].index;
480 r_selection[
i] = distances[
i].selected;
487 const float time_elapsed,
488 const float speed_fac,
490 const float frame_duration)
501 if (
const std::optional<float> src_delta_time = src_delta_times.get_if_single()) {
502 delta_times.fill(*src_delta_time);
513 const IndexRange points = points_by_curve[curve];
514 if (delta_times[points.
last()] == 0.0f && points.
size() != 1) {
516 const int point_i = points[point_id];
525 float accumulated_shift_delta_time = init_times[0];
527 const float previous_start_time = start_times[curve - 1];
528 const float init_time = init_times[curve];
529 const float previous_delta_time = delta_times[points_by_curve[curve - 1].last()];
530 const float previous_end_time = previous_start_time + previous_delta_time;
531 float shifted_start_time = init_time - accumulated_shift_delta_time;
534 if (init_time == 0.0f) {
535 shifted_start_time = previous_end_time;
538 const float gap_delta_time =
math::min(
math::abs(shifted_start_time - previous_end_time),
541 start_times[curve] = previous_end_time + gap_delta_time;
542 accumulated_shift_delta_time +=
math::max(shifted_start_time - start_times[curve], 0.0f);
549 const float max_time = start_times.
last() + delta_times.last();
554 const float time_compress_factor =
math::max(max_time / speed_fac / frame_duration, 1.0f);
557 const float limit = time_elapsed * speed_fac * time_compress_factor;
560 const float start_time = start_times[curve];
561 for (
const int point : points_by_curve[curve]) {
562 if (start_time + delta_times[point] >= limit) {
572 const int current_frame,
573 const int start_frame,
574 const int frame_duration,
576 const float percentage,
578 const float scene_fps,
579 const float speed_fac,
586 float(use_time - start_frame) /
length, 0.0f, 1.0f) *
590 return build_factor_frames;
592 return percentage * (1.0f +
fade);
595 float(current_frame) / scene_fps,
598 float(frame_duration) / scene_fps) *
609 const int current_time,
610 const int frame_duration,
611 const float scene_fps)
627 const int prev_strokes = prev_curves.
curves_num();
628 const int added_strokes = curves.
curves_num() - prev_strokes;
629 if (added_strokes > 0) {
659 float factor_start = factor - fade_factor;
661 std::swap(factor, factor_start);
719 const int eval_frame = grease_pencil.
runtime->eval_frame;
723 grease_pencil, mmd->influence, mask_memory);
728 if (eval_frame < mmd->start_frame || eval_frame > mmd->end_frame) {
747 layer, start_frame - 1);
749 const int relative_start_frame = eval_frame - start_frame;
754 int frame_duration = INT_MAX;
755 if (frame_index != layer.
sorted_keys().index_range().last()) {
756 const int next_frame = layer.
sorted_keys()[frame_index + 1];
764 relative_start_frame,
825 "open_frame_range_panel",
827 "use_restrict_frame_range",
828 IFACE_(
"Effective Range"));
829 if (
uiLayout *panel = restrict_frame_range_layout.
body) {
837 C,
ptr,
"open_fading_panel",
ptr,
"use_fading",
IFACE_(
"Fading"));
850 ptr,
"target_vertex_group", &ob_ptr,
"vertex_groups",
IFACE_(
"Weight Output"), ICON_NONE);
854 C,
ptr,
"open_influence_panel",
IFACE_(
"Influence")))
871 "GreasePencilBuildModifier",
873 "GreasePencilBuildModifierData",
875 &RNA_GreasePencilBuildModifier,
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_AcceptsGreasePencil
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
#define BLI_assert_unreachable()
#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)
void DEG_add_object_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
#define DNA_struct_default_get(struct_name)
GreasePencilBuildTimeMode
@ MOD_GREASE_PENCIL_BUILD_TIMEMODE_PERCENTAGE
@ MOD_GREASE_PENCIL_BUILD_TIMEMODE_DRAWSPEED
@ MOD_GREASE_PENCIL_BUILD_TIMEMODE_FRAMES
@ MOD_GREASE_PENCIL_BUILD_TIMEALIGN_START
@ MOD_GREASE_PENCIL_BUILD_TIMEALIGN_END
@ MOD_GREASE_PENCIL_BUILD_MODE_SEQUENTIAL
@ MOD_GREASE_PENCIL_BUILD_MODE_ADDITIVE
@ MOD_GREASE_PENCIL_BUILD_MODE_CONCURRENT
@ MOD_GREASE_PENCIL_BUILD_RESTRICT_TIME
@ MOD_GREASE_PENCIL_BUILD_USE_FADING
@ eModifierType_GreasePencilBuild
@ MOD_GREASE_PENCIL_BUILD_TRANSITION_VANISH
@ MOD_GREASE_PENCIL_BUILD_TRANSITION_GROW
Object is a sort of wrapper for general info.
ModifierTypeInfo modifierType_GreasePencilBuild
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)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
const T & last(const int64_t n=0) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr IndexRange drop_front(int64_t n) 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
void update_curve_types()
MutableAttributeAccessor attributes_for_write()
Span< float3 > positions() const
AttributeAccessor attributes() const
float evaluated_length_total_for_curve(int curve_index, bool cyclic) const
MutableSpan< int > offsets_for_write()
void ensure_evaluated_lengths() const
VArray< bool > cyclic() const
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
MutableSpan< float > opacities_for_write()
MutableSpan< float > radii_for_write()
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_topology_changed()
int sorted_keys_index_at(int frame_number) const
std::optional< int > start_frame_at(int frame_number) const
Span< FramesMapKeyT > sorted_keys() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void to_bools(MutableSpan< bool > r_bools) const
void foreach_index(Fn &&fn) const
float length(VecOp< float, D >) RET
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
bke::CurvesGeometry reorder_curves_geometry(const bke::CurvesGeometry &src_curves, Span< int > old_by_new_map, const bke::AttributeFilter &attribute_filter)
T clamp(const T &a, const T &min, const T &max)
T distance(const T &a, const T &b)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
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)
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)
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)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
int sum_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask)
void parallel_for_each(Range &&range, const Function &function)
constexpr float GP_BUILD_TIME_DEFAULT_STROKES
static Array< int > point_counts_to_keep_concurrent(const bke::CurvesGeometry &curves, const IndexMask &selection, const int time_alignment, const int transition, const float factor, const bool clamp_points, int &r_curves_num, int &r_points_num)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void blend_write(BlendWriter *writer, const ID *, const ModifierData *md)
static bke::CurvesGeometry build_sequential(bke::greasepencil::Drawing &drawing, bke::CurvesGeometry &curves, const IndexMask &selection, const int transition, const float factor, const float factor_start, const float factor_opacity, const float factor_radii, StringRefNull target_vgname)
static void init_data(ModifierData *md)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void points_info_sequential(const bke::CurvesGeometry &curves, const IndexMask &selection, const int transition, const float factor, const bool clamp_points, int &r_curves_num, int &r_points_num)
static void panel_draw(const bContext *C, Panel *panel)
static float get_factor_from_draw_speed(const bke::CurvesGeometry &curves, const float time_elapsed, const float speed_fac, const float max_gap, const float frame_duration)
static float get_build_factor(const GreasePencilBuildTimeMode time_mode, const int current_frame, const int start_frame, const int frame_duration, const int length, const float percentage, const bke::CurvesGeometry &curves, const float scene_fps, const float speed_fac, const float max_gap, const float fade)
static void modify_geometry_set(ModifierData *md, const ModifierEvalContext *ctx, bke::GeometrySet *geometry_set)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
static bke::CurvesGeometry reorder_strokes(const bke::CurvesGeometry &curves, const Span< bool > select, const Object &object, MutableSpan< bool > r_selection)
static void free_data(ModifierData *md)
static void build_drawing(const GreasePencilBuildModifierData &mmd, const Object &ob, bke::greasepencil::Drawing &drawing, const bke::greasepencil::Drawing *previous_drawing, const int current_time, const int frame_duration, const float scene_fps)
static void panel_register(ARegionType *region_type)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
VecBase< float, 3 > float3
static void blend_read(BlendDataReader *reader, ModifierData *md)
static bke::CurvesGeometry build_concurrent(bke::greasepencil::Drawing &drawing, bke::CurvesGeometry &curves, const IndexMask &selection, const int time_alignment, const int transition, const float factor, const float factor_start, const float factor_opacity, const float factor_radii, StringRefNull target_vgname)
CCL_NAMESPACE_BEGIN ccl_device float fade(const float t)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
GreasePencilModifierInfluenceData influence
float fade_opacity_strength
float fade_thickness_strength
GreasePencilRuntimeHandle * runtime
bool has_grease_pencil() const
GreasePencil * get_grease_pencil_for_write()
MutableVArraySpan< T > span
bke::greasepencil::Drawing * drawing
PanelLayout panel_prop(const bContext *C, PointerRNA *open_prop_owner, blender::StringRefNull open_prop_name)
PanelLayout panel_prop_with_bool_header(const bContext *C, PointerRNA *open_prop_owner, blender::StringRefNull open_prop_name, PointerRNA *bool_prop_owner, blender::StringRefNull bool_prop_name, std::optional< blender::StringRef > label)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
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)