36#include "RNA_prototypes.hh"
79 if (mmd->object !=
nullptr) {
102 const int time_alignment,
103 const int transition,
105 const bool clamp_points,
114 float max_length = 0;
116 const bool stroke_cyclic = cyclic[stroke];
124 r_curves_num = r_points_num = 0;
125 factor_to_keep = std::clamp(factor_to_keep, 0.0f, 1.0f);
128 auto get_stroke_factor = [&](
const float factor,
const int index) {
129 const bool stroke_cyclic = cyclic[index];
131 if (total_length == 0) {
132 return factor > 0.5f ? 1.0f : 0.0f;
134 const float max_factor = max_length / total_length;
137 return std::clamp(factor * max_factor, 0.0f, 1.0f);
139 return factor * max_factor;
142 const float min_factor = max_factor - 1.0f;
143 const float use_factor = factor * max_factor;
145 return std::clamp(use_factor - min_factor, 0.0f, 1.0f);
147 return use_factor - min_factor;
156 const float local_factor =
select[curve] ? get_stroke_factor(factor_to_keep, curve) : 1.0f;
157 const int num_points = points_by_curve[curve].
size() * local_factor;
158 result[curve] = num_points;
160 r_points_num += num_points;
161 if (num_points > 0) {
172 const int time_alignment,
173 const int transition,
175 const float factor_start,
176 const float factor_opacity,
177 const float factor_radii,
180 int dst_curves_num, dst_points_num;
181 const bool has_fade = factor_start != factor;
183 curves, selection, time_alignment, transition, factor,
true, dst_curves_num, dst_points_num);
184 if (dst_curves_num == 0) {
223 if (!point_counts_to_keep[curve]) {
226 const IndexRange points = points_by_curve[curve];
227 dst_offsets[next_curve] = point_counts_to_keep[curve];
228 const int curve_size = points.
size();
230 auto get_fade_weight = [&](
const int local_index) {
231 const float fade_range = std::abs(ends_per_curve[curve] - starts_per_curve[curve]);
233 const float factor_from_start = local_index - curve_size + ends_per_curve[curve];
234 return 1.0f - std::clamp(factor_from_start / fade_range, 0.0f, 1.0f);
236 const float factor_from_start = local_index - starts_per_curve[curve];
237 return std::clamp(factor_from_start / fade_range, 0.0f, 1.0f);
240 const int extra_offset = is_vanishing ? points.
size() - point_counts_to_keep[curve] : 0;
241 for (
const int stroke_point :
IndexRange(point_counts_to_keep[curve])) {
242 const int src_point_index = points.
first() + extra_offset + stroke_point;
244 const float fade_weight = get_fade_weight(extra_offset + stroke_point);
245 opacities[src_point_index] = opacities[src_point_index] *
246 (1.0f - fade_weight * factor_opacity);
247 radii[src_point_index] = radii[src_point_index] * (1.0f - fade_weight * factor_radii);
248 if (!weights.
span.is_empty()) {
249 weights.
span[src_point_index] = fade_weight;
252 dst_to_src_point[next_point] = src_point_index;
255 dst_to_src_curve[next_curve] = curve;
265 gather_attributes(src_attributes,
271 gather_attributes(src_attributes,
285 const int transition,
287 const bool clamp_points,
297 factor_to_keep = std::clamp(factor_to_keep, 0.0f, 1.0f);
304 const int untouched_points_num = points_by_curve.
total_size() - effective_points_num;
305 effective_points_num *= factor_to_keep;
306 effective_points_num += untouched_points_num;
308 r_points_num = effective_points_num;
314 int counted_points_num = 0;
316 const int stroke = is_vanishing ? stroke_count -
i - 1 :
i;
317 if (
select[stroke] && counted_points_num >= effective_points_num) {
320 counted_points_num += points_by_curve[stroke].
size();
328 const int transition,
330 const float factor_start,
331 const float factor_opacity,
332 const float factor_radii,
335 const bool has_fade = factor_start != factor;
336 int dst_curves_num, dst_points_num;
337 int start_points_num, end_points_num, dummy_curves_num;
339 curves, selection, transition, factor,
true, dst_curves_num, dst_points_num);
341 if (dst_curves_num == 0) {
346 curves, selection, transition, factor_start,
false, dummy_curves_num, start_points_num);
348 curves, selection, transition, factor,
false, dummy_curves_num, end_points_num);
365 int next_curve = 1, next_point = 0;
368 for (
const int point : points_by_curve[stroke]) {
369 dst_to_src_point[next_point] = point;
372 dst_to_src_curve[next_curve - 1] = stroke;
373 dst_offsets[next_curve] = next_point;
378 bool done_scanning =
false;
380 const int stroke = is_vanishing ? stroke_count -
i - 1 :
i;
381 if (done_scanning || next_point >= dst_points_num) {
382 done_scanning =
true;
386 auto get_fade_weight = [&](
const int next_point_count) {
387 return std::clamp(
float(next_point_count - start_points_num) /
388 float(
abs(end_points_num - start_points_num)),
393 const IndexRange points = points_by_curve[stroke];
394 for (
const int point : points) {
395 const int local_index = point - points.
first();
396 const int src_point_index = is_vanishing ? points.
last() - local_index : point;
397 dst_to_src_point[next_point] = src_point_index;
400 const float fade_weight = get_fade_weight(next_point);
401 opacities[src_point_index] = opacities[src_point_index] *
402 (1.0f - fade_weight * factor_opacity);
403 radii[src_point_index] = radii[src_point_index] * (1.0f - fade_weight * factor_radii);
404 if (!weights.
span.is_empty()) {
405 weights.
span[src_point_index] = fade_weight;
410 if (next_point >= dst_points_num) {
411 done_scanning =
true;
415 dst_offsets[next_curve] = next_point;
416 dst_to_src_curve[next_curve - 1] =
i;
421 BLI_assert(next_curve == (dst_curves_num + 1));
427 gather_attributes(src_attributes,
433 gather_attributes(src_attributes,
452 const float3 center =
object.object_to_world().location();
462 const IndexRange points = points_by_curve[stroke];
466 distances[stroke].index = stroke;
467 distances[stroke].selected =
select[stroke];
471 distances.
begin(), distances.
end(), [](Pair &a, Pair &
b) { return a.value < b.value; });
475 new_order[
i] = distances[
i].index;
476 r_selection[
i] = distances[
i].selected;
483 const float time_elapsed,
484 const float speed_fac,
486 const float frame_duration)
497 float accumulated_shift_delta_time = init_times[0];
499 const float previous_start_time = start_times[curve - 1];
500 const float previous_delta_time = delta_times[points_by_curve[curve - 1].last()];
501 const float previous_end_time = previous_start_time + previous_delta_time;
503 const float shifted_start_time = init_times[curve] - accumulated_shift_delta_time;
504 const float gap_delta_time =
math::min(
math::abs(shifted_start_time - previous_end_time),
507 start_times[curve] = previous_end_time + gap_delta_time;
508 accumulated_shift_delta_time +=
math::max(shifted_start_time - start_times[curve], 0.0f);
515 const float max_time = start_times.
last() + delta_times.last();
520 const float time_compress_factor =
math::max(max_time / speed_fac / frame_duration, 1.0f);
523 const float limit = time_elapsed * speed_fac * time_compress_factor;
526 const float start_time = start_times[curve];
527 for (
const int point : points_by_curve[curve]) {
528 if (start_time + delta_times[point] >= limit) {
538 const int current_frame,
539 const int start_frame,
540 const int frame_duration,
542 const float percentage,
544 const float scene_fps,
545 const float speed_fac,
552 float(use_time - start_frame) /
length, 0.0f, 1.0f) *
556 return build_factor_frames;
558 return percentage * (1.0f +
fade);
563 return build_factor_frames;
566 float(current_frame) / scene_fps,
569 float(frame_duration) / scene_fps) *
580 const int current_time,
581 const int frame_duration,
582 const float scene_fps)
598 const int prev_strokes = prev_curves.
curves_num();
599 const int added_strokes = curves.
curves_num() - prev_strokes;
600 if (added_strokes > 0) {
630 float factor_start = factor - fade_factor;
632 std::swap(factor, factor_start);
690 const int eval_frame = grease_pencil.
runtime->eval_frame;
694 grease_pencil, mmd->influence, mask_memory);
699 if (eval_frame < mmd->start_frame || eval_frame > mmd->end_frame) {
718 layer, start_frame - 1);
720 const int relative_start_frame = eval_frame - start_frame;
725 int frame_duration = INT_MAX;
726 if (frame_index != layer.
sorted_keys().index_range().last()) {
727 const int next_frame = layer.
sorted_keys()[frame_index + 1];
735 relative_start_frame,
796 "open_frame_range_panel",
798 "use_restrict_frame_range",
799 IFACE_(
"Effective Range"));
800 if (
uiLayout *panel = restrict_frame_range_layout.
body) {
808 C,
ptr,
"open_fading_panel",
ptr,
"use_fading",
IFACE_(
"Fading"));
822 "target_vertex_group",
830 C,
ptr,
"open_influence_panel",
IFACE_(
"Influence")))
847 "GreasePencilBuildModifier",
849 "GreasePencilBuildModifierData",
851 &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)
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *searchptr, blender::StringRefNull searchpropname, std::optional< blender::StringRefNull > name, int icon)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
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 drop_front(int64_t n) const
T last(const int64_t n=0) const
bool contains(StringRef attribute_id) 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
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
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)
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_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::StringRefNull > label)
PanelLayout panel_prop(const bContext *C, PointerRNA *open_prop_owner, blender::StringRefNull open_prop_name)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
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)