diff options
Diffstat (limited to 'source/blender/sequencer/intern/strip_time.c')
-rw-r--r-- | source/blender/sequencer/intern/strip_time.c | 193 |
1 files changed, 127 insertions, 66 deletions
diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index 4d6efb1639b..d4357fe28b6 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -31,14 +31,32 @@ #include "strip_time.h" #include "utils.h" -float seq_give_frame_index(Sequence *seq, float timeline_frame) +static float seq_time_media_playback_rate_factor_get(const Scene *scene, const Sequence *seq) +{ + if ((seq->flag & SEQ_AUTO_PLAYBACK_RATE) == 0) { + return 1.0f; + } + if (seq->media_playback_rate == 0.0f) { + return 1.0f; + } + + float scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base; + return seq->media_playback_rate / scene_playback_rate; +} + +static float seq_time_playback_rate_factor_get(const Scene *scene, const Sequence *seq) +{ + return seq_time_media_playback_rate_factor_get(scene, seq) * seq->speed_factor; +} + +float seq_give_frame_index(const Scene *scene, Sequence *seq, float timeline_frame) { float frame_index; - int sta = seq->start; - int end = seq->start + seq->len - 1; + float sta = SEQ_time_start_frame_get(seq); + float end = SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq) - 1; if (seq->type & SEQ_TYPE_EFFECT) { - end = SEQ_time_right_handle_frame_get(seq); + end = SEQ_time_right_handle_frame_get(scene, seq); } if (end < sta) { @@ -46,29 +64,16 @@ float seq_give_frame_index(Sequence *seq, float timeline_frame) } if (seq->flag & SEQ_REVERSE_FRAMES) { - /* Reverse frame in this sequence. */ - if (timeline_frame <= sta) { - frame_index = end - sta; - } - else if (timeline_frame >= end) { - frame_index = 0; - } - else { - frame_index = end - timeline_frame; - } + frame_index = end - timeline_frame; } else { - if (timeline_frame <= sta) { - frame_index = 0; - } - else if (timeline_frame >= end) { - frame_index = end - sta; - } - else { - frame_index = timeline_frame - sta; - } + frame_index = timeline_frame - sta; } + /* Clamp frame index to strip frame range. */ + frame_index = clamp_f(frame_index, 0, end - sta); + frame_index *= seq_time_playback_rate_factor_get(scene, seq); + if (seq->strobe < 1.0f) { seq->strobe = 1.0f; } @@ -149,14 +154,14 @@ void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta) return; } - const int strip_start = SEQ_time_left_handle_frame_get(seq_meta); - const int strip_end = SEQ_time_right_handle_frame_get(seq_meta); + const int strip_start = SEQ_time_left_handle_frame_get(scene, seq_meta); + const int strip_end = SEQ_time_right_handle_frame_get(scene, seq_meta); int min = MAXFRAME * 2; int max = -MAXFRAME * 2; LISTBASE_FOREACH (Sequence *, seq, &seq_meta->seqbase) { - min = min_ii(SEQ_time_left_handle_frame_get(seq), min); - max = max_ii(SEQ_time_right_handle_frame_get(seq), max); + min = min_ii(SEQ_time_left_handle_frame_get(scene, seq), min); + max = max_ii(SEQ_time_right_handle_frame_get(scene, seq), max); } seq_meta->start = min + seq_meta->anim_startofs; @@ -171,25 +176,25 @@ void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta) SEQ_time_right_handle_frame_set(scene, seq_meta, strip_end); } -void seq_time_effect_range_set(Sequence *seq) +void seq_time_effect_range_set(const Scene *scene, Sequence *seq) { if (seq->seq1 == NULL && seq->seq2 == NULL) { return; } if (seq->seq1 && seq->seq2) { /* 2 - input effect. */ - seq->startdisp = max_ii(SEQ_time_left_handle_frame_get(seq->seq1), - SEQ_time_left_handle_frame_get(seq->seq2)); - seq->enddisp = min_ii(SEQ_time_right_handle_frame_get(seq->seq1), - SEQ_time_right_handle_frame_get(seq->seq2)); + seq->startdisp = max_ii(SEQ_time_left_handle_frame_get(scene, seq->seq1), + SEQ_time_left_handle_frame_get(scene, seq->seq2)); + seq->enddisp = min_ii(SEQ_time_right_handle_frame_get(scene, seq->seq1), + SEQ_time_right_handle_frame_get(scene, seq->seq2)); } else if (seq->seq1) { /* Single input effect. */ - seq->startdisp = SEQ_time_right_handle_frame_get(seq->seq1); - seq->enddisp = SEQ_time_left_handle_frame_get(seq->seq1); + seq->startdisp = SEQ_time_right_handle_frame_get(scene, seq->seq1); + seq->enddisp = SEQ_time_left_handle_frame_get(scene, seq->seq1); } else if (seq->seq2) { /* Strip may be missing one of inputs. */ - seq->startdisp = SEQ_time_right_handle_frame_get(seq->seq2); - seq->enddisp = SEQ_time_left_handle_frame_get(seq->seq2); + seq->startdisp = SEQ_time_right_handle_frame_get(scene, seq->seq2); + seq->enddisp = SEQ_time_left_handle_frame_get(scene, seq->seq2); } if (seq->startdisp > seq->enddisp) { @@ -210,7 +215,7 @@ void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effe Sequence *seq; /* First pass: Update length of immediate effects. */ SEQ_ITERATOR_FOREACH (seq, effects) { - seq_time_effect_range_set(seq); + seq_time_effect_range_set(scene, seq); } /* Second pass: Recursive call to update effects in chain and in order, so they inherit length @@ -255,14 +260,14 @@ int SEQ_time_find_next_prev_edit(Scene *scene, } if (do_center) { - seq_frames[0] = (SEQ_time_left_handle_frame_get(seq) + - SEQ_time_right_handle_frame_get(seq)) / + seq_frames[0] = (SEQ_time_left_handle_frame_get(scene, seq) + + SEQ_time_right_handle_frame_get(scene, seq)) / 2; seq_frames_tot = 1; } else { - seq_frames[0] = SEQ_time_left_handle_frame_get(seq); - seq_frames[1] = SEQ_time_right_handle_frame_get(seq); + seq_frames[0] = SEQ_time_left_handle_frame_get(scene, seq); + seq_frames[1] = SEQ_time_right_handle_frame_get(scene, seq); seq_frames_tot = 2; } @@ -339,18 +344,18 @@ void SEQ_timeline_init_boundbox(const Scene *scene, rctf *rect) rect->ymax = 8.0f; } -void SEQ_timeline_expand_boundbox(const ListBase *seqbase, rctf *rect) +void SEQ_timeline_expand_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect) { if (seqbase == NULL) { return; } LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if (rect->xmin > SEQ_time_left_handle_frame_get(seq) - 1) { - rect->xmin = SEQ_time_left_handle_frame_get(seq) - 1; + if (rect->xmin > SEQ_time_left_handle_frame_get(scene, seq) - 1) { + rect->xmin = SEQ_time_left_handle_frame_get(scene, seq) - 1; } - if (rect->xmax < SEQ_time_right_handle_frame_get(seq) + 1) { - rect->xmax = SEQ_time_right_handle_frame_get(seq) + 1; + if (rect->xmax < SEQ_time_right_handle_frame_get(scene, seq) + 1) { + rect->xmax = SEQ_time_right_handle_frame_get(scene, seq) + 1; } if (rect->ymax < seq->machine) { rect->ymax = seq->machine; @@ -361,14 +366,16 @@ void SEQ_timeline_expand_boundbox(const ListBase *seqbase, rctf *rect) void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect) { SEQ_timeline_init_boundbox(scene, rect); - SEQ_timeline_expand_boundbox(seqbase, rect); + SEQ_timeline_expand_boundbox(scene, seqbase, rect); } -static bool strip_exists_at_frame(SeqCollection *all_strips, const int timeline_frame) +static bool strip_exists_at_frame(const Scene *scene, + SeqCollection *all_strips, + const int timeline_frame) { Sequence *seq; SEQ_ITERATOR_FOREACH (seq, all_strips) { - if (SEQ_time_strip_intersects_frame(seq, timeline_frame)) { + if (SEQ_time_strip_intersects_frame(scene, seq, timeline_frame)) { return true; } } @@ -390,10 +397,10 @@ void seq_time_gap_info_get(const Scene *scene, SeqCollection *collection = SEQ_query_all_strips(seqbase); - if (!strip_exists_at_frame(collection, initial_frame)) { + if (!strip_exists_at_frame(scene, collection, initial_frame)) { /* Search backward for gap_start_frame. */ for (; timeline_frame >= sfra; timeline_frame--) { - if (strip_exists_at_frame(collection, timeline_frame)) { + if (strip_exists_at_frame(scene, collection, timeline_frame)) { break; } } @@ -403,7 +410,7 @@ void seq_time_gap_info_get(const Scene *scene, else { /* Search forward for gap_start_frame. */ for (; timeline_frame <= efra; timeline_frame++) { - if (!strip_exists_at_frame(collection, timeline_frame)) { + if (!strip_exists_at_frame(scene, collection, timeline_frame)) { r_gap_info->gap_start_frame = timeline_frame; break; } @@ -411,7 +418,7 @@ void seq_time_gap_info_get(const Scene *scene, } /* Search forward for gap_end_frame. */ for (; timeline_frame <= efra; timeline_frame++) { - if (strip_exists_at_frame(collection, timeline_frame)) { + if (strip_exists_at_frame(scene, collection, timeline_frame)) { const int gap_end_frame = timeline_frame; r_gap_info->gap_length = gap_end_frame - r_gap_info->gap_start_frame; r_gap_info->gap_exists = true; @@ -420,28 +427,67 @@ void seq_time_gap_info_get(const Scene *scene, } } -bool SEQ_time_strip_intersects_frame(const Sequence *seq, const int timeline_frame) +bool SEQ_time_strip_intersects_frame(const Scene *scene, + const Sequence *seq, + const int timeline_frame) +{ + return (SEQ_time_left_handle_frame_get(scene, seq) <= timeline_frame) && + (SEQ_time_right_handle_frame_get(scene, seq) > timeline_frame); +} + +void SEQ_time_speed_factor_set(const Scene *scene, Sequence *seq, const float speed_factor) +{ + const float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq); + const float unity_start_offset = seq->startofs * seq->speed_factor; + const float unity_end_offset = seq->endofs * seq->speed_factor; + + /* Left handle is pivot point for content scaling - it must always show same frame. */ + seq->speed_factor = speed_factor; + seq->startofs = unity_start_offset / speed_factor; + seq->start = left_handle_frame - seq->startofs; + seq->endofs = unity_end_offset / speed_factor; + + SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq)); + seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq)); +} + +bool SEQ_time_has_left_still_frames(const Scene *scene, const Sequence *seq) +{ + return SEQ_time_left_handle_frame_get(scene, seq) < SEQ_time_start_frame_get(seq); +} + +bool SEQ_time_has_right_still_frames(const Scene *scene, const Sequence *seq) +{ + return SEQ_time_right_handle_frame_get(scene, seq) > + SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq); +} + +bool SEQ_time_has_still_frames(const Scene *scene, const Sequence *seq) { - return (SEQ_time_left_handle_frame_get(seq) <= timeline_frame) && - (SEQ_time_right_handle_frame_get(seq) > timeline_frame); + return SEQ_time_has_right_still_frames(scene, seq) || SEQ_time_has_left_still_frames(scene, seq); } -bool SEQ_time_has_left_still_frames(const Sequence *seq) +/* Length of strip content in frames. This is number of original frames adjusted by playback rate + * factor */ +int SEQ_time_strip_length_get(const Scene *scene, const Sequence *seq) { - return seq->startofs < 0; + return seq->len / seq_time_playback_rate_factor_get(scene, seq); } -bool SEQ_time_has_right_still_frames(const Sequence *seq) +/* Return timeline frame, where strip content starts. */ +float SEQ_time_start_frame_get(const Sequence *seq) { - return seq->endofs < 0; + return seq->start; } -bool SEQ_time_has_still_frames(const Sequence *seq) +void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_frame) { - return SEQ_time_has_right_still_frames(seq) || SEQ_time_has_left_still_frames(seq); + seq->start = timeline_frame; + SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq)); + seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq)); } -int SEQ_time_left_handle_frame_get(const Sequence *seq) +int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq) { if (seq->seq1 || seq->seq2) { return seq->startdisp; @@ -450,27 +496,42 @@ int SEQ_time_left_handle_frame_get(const Sequence *seq) return seq->start + seq->startofs; } -int SEQ_time_right_handle_frame_get(const Sequence *seq) +int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq) { if (seq->seq1 || seq->seq2) { return seq->enddisp; } - return seq->start + seq->len - seq->endofs; + return seq->start + SEQ_time_strip_length_get(scene, seq) - seq->endofs; } void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int val) { + const float right_handle_orig_frame = SEQ_time_right_handle_frame_get(scene, seq); + + if (val >= right_handle_orig_frame) { + val = right_handle_orig_frame - 1; + } + seq->startofs = val - seq->start; seq->startdisp = val; /* Only to make files usable in older versions. */ + SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq)); seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq)); } void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int val) { - seq->endofs = seq->start + seq->len - val; + const float strip_content_end_frame = seq->start + SEQ_time_strip_length_get(scene, seq); + const float left_handle_orig_frame = SEQ_time_left_handle_frame_get(scene, seq); + + if (val <= left_handle_orig_frame) { + val = left_handle_orig_frame + 1; + } + + seq->endofs = strip_content_end_frame - val; seq->enddisp = val; /* Only to make files usable in older versions. */ + SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq)); seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq)); } |