diff options
author | Richard Antalik <richardantalik@gmail.com> | 2022-06-29 13:45:59 +0300 |
---|---|---|
committer | Richard Antalik <richardantalik@gmail.com> | 2022-06-29 13:48:34 +0300 |
commit | 302b04a5a3fc0e767ac784424f78ce2edf5d2844 (patch) | |
tree | def4de621fbb0a194b350da781f054c6aefbab35 /source/blender/editors/space_sequencer/sequencer_select.c | |
parent | c51b8ec86364585c4088837c603b39752065bc34 (diff) |
VSE: Improved Retiming system
Patch implements better way to control playback speed than it is
possible to do with speed effect. Speed factor property can be set in
Time panel.
There are 2 layers of control:
Option to retime movie to match scene FPS rate.
Custom speed factor to control playback rate.
Since playback rate is strip property, it is now possible to manipulate
strip as normal one even if it is retimed.
To facilitate manipulation, some functions need to consider speed factor
and apply necessary corrections to strip offset or strip start. These
corrections may need to be float numbers, so start and offsets must be
float as well.
Sound strips now use speed factor instead of pitch. This means, that
strips will change length to match usable length. In addition, it is
possible to group movie and sound strip and change speed of meta strip.
Diffstat (limited to 'source/blender/editors/space_sequencer/sequencer_select.c')
-rw-r--r-- | source/blender/editors/space_sequencer/sequencer_select.c | 139 |
1 files changed, 79 insertions, 60 deletions
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index f237fbc0a12..cfdbeaf0658 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -59,7 +59,7 @@ SeqCollection *all_strips_from_context(bContext *C) const bool is_preview = sequencer_view_has_preview_poll(C); if (is_preview) { - return SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + return SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); } return SEQ_query_all_strips(seqbase); @@ -74,7 +74,7 @@ SeqCollection *selected_strips_from_context(bContext *C) const bool is_preview = sequencer_view_has_preview_poll(C); if (is_preview) { - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); return strips; } @@ -108,7 +108,8 @@ static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRIN } /* Used for mouse selection in SEQUENCER_OT_select. */ -static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame) +static void select_active_side( + const Scene *scene, ListBase *seqbase, int sel_side, int channel, int frame) { Sequence *seq; @@ -116,13 +117,13 @@ static void select_active_side(ListBase *seqbase, int sel_side, int channel, int if (channel == seq->machine) { switch (sel_side) { case SEQ_SIDE_LEFT: - if (frame > (SEQ_time_left_handle_frame_get(seq))) { + if (frame > (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } break; case SEQ_SIDE_RIGHT: - if (frame < (SEQ_time_left_handle_frame_get(seq))) { + if (frame < (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } @@ -137,7 +138,8 @@ static void select_active_side(ListBase *seqbase, int sel_side, int channel, int } /* Used for mouse selection in SEQUENCER_OT_select_side. */ -static void select_active_side_range(ListBase *seqbase, +static void select_active_side_range(const Scene *scene, + ListBase *seqbase, const int sel_side, const int frame_ranges[MAXSEQ], const int frame_ignore) @@ -152,13 +154,13 @@ static void select_active_side_range(ListBase *seqbase, } switch (sel_side) { case SEQ_SIDE_LEFT: - if (frame > (SEQ_time_left_handle_frame_get(seq))) { + if (frame > (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } break; case SEQ_SIDE_RIGHT: - if (frame < (SEQ_time_left_handle_frame_get(seq))) { + if (frame < (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } @@ -173,14 +175,14 @@ static void select_active_side_range(ListBase *seqbase, } /* Used for mouse selection in SEQUENCER_OT_select */ -static void select_linked_time(ListBase *seqbase, Sequence *seq_link) +static void select_linked_time(const Scene *scene, ListBase *seqbase, Sequence *seq_link) { Sequence *seq; for (seq = seqbase->first; seq; seq = seq->next) { if (seq_link->machine != seq->machine) { - int left_match = (SEQ_time_left_handle_frame_get(seq) == seq_link->startdisp) ? 1 : 0; - int right_match = (SEQ_time_right_handle_frame_get(seq) == seq_link->enddisp) ? 1 : 0; + int left_match = (SEQ_time_left_handle_frame_get(scene, seq) == seq_link->startdisp) ? 1 : 0; + int right_match = (SEQ_time_right_handle_frame_get(scene, seq) == seq_link->enddisp) ? 1 : 0; if (left_match && right_match) { /* Direct match, copy the selection settings. */ @@ -245,10 +247,10 @@ void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool desel recurs_sel_seq(seq); } -void seq_rectf(Sequence *seq, rctf *rect) +void seq_rectf(const Scene *scene, Sequence *seq, rctf *rect) { - rect->xmin = SEQ_time_left_handle_frame_get(seq); - rect->xmax = SEQ_time_right_handle_frame_get(seq); + rect->xmin = SEQ_time_left_handle_frame_get(scene, seq); + rect->xmax = SEQ_time_right_handle_frame_get(scene, seq); rect->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM; rect->ymax = seq->machine + SEQ_STRIP_OFSTOP; } @@ -273,12 +275,14 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se (sel == 0 && (seq->flag & SELECT) == 0))) { switch (lr) { case SEQ_SIDE_LEFT: - if (SEQ_time_left_handle_frame_get(test) == (SEQ_time_right_handle_frame_get(seq))) { + if (SEQ_time_left_handle_frame_get(scene, test) == + (SEQ_time_right_handle_frame_get(scene, seq))) { return seq; } break; case SEQ_SIDE_RIGHT: - if (SEQ_time_right_handle_frame_get(test) == (SEQ_time_left_handle_frame_get(seq))) { + if (SEQ_time_right_handle_frame_get(scene, test) == + (SEQ_time_left_handle_frame_get(scene, seq))) { return seq; } break; @@ -311,18 +315,20 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ while (seq) { if (seq->machine == (int)y) { /* Check for both normal strips, and strips that have been flipped horizontally. */ - if (((SEQ_time_left_handle_frame_get(seq) < SEQ_time_right_handle_frame_get(seq)) && - (SEQ_time_left_handle_frame_get(seq) <= x && - SEQ_time_right_handle_frame_get(seq) >= x)) || - ((SEQ_time_left_handle_frame_get(seq) > SEQ_time_right_handle_frame_get(seq)) && - (SEQ_time_left_handle_frame_get(seq) >= x && - SEQ_time_right_handle_frame_get(seq) <= x))) { + if (((SEQ_time_left_handle_frame_get(scene, seq) < + SEQ_time_right_handle_frame_get(scene, seq)) && + (SEQ_time_left_handle_frame_get(scene, seq) <= x && + SEQ_time_right_handle_frame_get(scene, seq) >= x)) || + ((SEQ_time_left_handle_frame_get(scene, seq) > + SEQ_time_right_handle_frame_get(scene, seq)) && + (SEQ_time_left_handle_frame_get(scene, seq) >= x && + SEQ_time_right_handle_frame_get(scene, seq) <= x))) { if (SEQ_transform_sequence_can_be_translated(seq)) { /* Clamp handles to defined size in pixel space. */ - handsize = 2.0f * sequence_handle_size_get_clamped(seq, pixelx); - displen = (float)abs(SEQ_time_left_handle_frame_get(seq) - - SEQ_time_right_handle_frame_get(seq)); + handsize = 2.0f * sequence_handle_size_get_clamped(scene, seq, pixelx); + displen = (float)abs(SEQ_time_left_handle_frame_get(scene, seq) - + SEQ_time_right_handle_frame_get(scene, seq)); /* Don't even try to grab the handles of small strips. */ if (displen / pixelx > 16) { @@ -337,10 +343,10 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ CLAMP(handsize, 7 * pixelx, 30 * pixelx); } - if (handsize + SEQ_time_left_handle_frame_get(seq) >= x) { + if (handsize + SEQ_time_left_handle_frame_get(scene, seq) >= x) { *hand = SEQ_SIDE_LEFT; } - else if (-handsize + SEQ_time_right_handle_frame_get(seq) <= x) { + else if (-handsize + SEQ_time_right_handle_frame_get(scene, seq) <= x) { *hand = SEQ_SIDE_RIGHT; } } @@ -583,8 +589,8 @@ static void sequencer_select_side_of_frame(const bContext *C, const float x = UI_view2d_region_to_view_x(v2d, mval[0]); LISTBASE_FOREACH (Sequence *, seq_iter, SEQ_active_seqbase_get(ed)) { - if (((x < CFRA) && (SEQ_time_right_handle_frame_get(seq_iter) <= CFRA)) || - ((x >= CFRA) && (SEQ_time_left_handle_frame_get(seq_iter) >= CFRA))) { + if (((x < CFRA) && (SEQ_time_right_handle_frame_get(scene, seq_iter) <= CFRA)) || + ((x >= CFRA) && (SEQ_time_left_handle_frame_get(scene, seq_iter) >= CFRA))) { /* Select left or right. */ seq_iter->flag |= SELECT; recurs_sel_seq(seq_iter); @@ -639,8 +645,11 @@ static void sequencer_select_linked_handle(const bContext *C, case SEQ_SIDE_LEFT: if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) { seq->flag |= SELECT; - select_active_side( - ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, SEQ_time_left_handle_frame_get(seq)); + select_active_side(scene, + ed->seqbasep, + SEQ_SIDE_LEFT, + seq->machine, + SEQ_time_left_handle_frame_get(scene, seq)); } else { seq->flag |= SELECT; @@ -653,8 +662,11 @@ static void sequencer_select_linked_handle(const bContext *C, case SEQ_SIDE_RIGHT: if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) { seq->flag |= SELECT; - select_active_side( - ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, SEQ_time_left_handle_frame_get(seq)); + select_active_side(scene, + ed->seqbasep, + SEQ_SIDE_RIGHT, + seq->machine, + SEQ_time_left_handle_frame_get(scene, seq)); } else { seq->flag |= SELECT; @@ -669,7 +681,7 @@ static void sequencer_select_linked_handle(const bContext *C, else { select_active_side( - ed->seqbasep, sel_side, seq->machine, SEQ_time_left_handle_frame_get(seq)); + scene, ed->seqbasep, sel_side, seq->machine, SEQ_time_left_handle_frame_get(scene, seq)); } } } @@ -734,7 +746,7 @@ static Sequence *seq_select_seq_from_preview( const bool use_cycle = (!WM_cursor_test_motion_and_update(mval) || extend || toggle); SeqCollection *strips = SEQ_query_rendered_strips( - channels, seqbase, scene->r.cfra, sseq->chanshown); + scene, channels, seqbase, scene->r.cfra, sseq->chanshown); /* Allow strips this far from the closest center to be included. * This allows cycling over center points which are near enough @@ -921,7 +933,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) ED_sequencer_deselect_all(scene); } sequencer_select_strip_impl(ed, seq, handle_clicked, extend, deselect, toggle); - select_linked_time(ed->seqbasep, seq); + select_linked_time(scene, ed->seqbasep, seq); sequencer_select_do_updates(C, scene); sequencer_select_set_active(scene, seq); return OPERATOR_FINISHED; @@ -1436,13 +1448,13 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op) bool test = false; switch (side) { case -1: - test = (timeline_frame >= SEQ_time_right_handle_frame_get(seq)); + test = (timeline_frame >= SEQ_time_right_handle_frame_get(scene, seq)); break; case 1: - test = (timeline_frame <= SEQ_time_left_handle_frame_get(seq)); + test = (timeline_frame <= SEQ_time_left_handle_frame_get(scene, seq)); break; case 2: - test = SEQ_time_strip_intersects_frame(seq, timeline_frame); + test = SEQ_time_strip_intersects_frame(scene, seq, timeline_frame); break; } @@ -1513,10 +1525,10 @@ static int sequencer_select_side_exec(bContext *C, wmOperator *op) if (seq->flag & SELECT) { selected = true; if (sel_side == SEQ_SIDE_LEFT) { - *frame_limit_p = max_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(seq)); + *frame_limit_p = max_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(scene, seq)); } else { - *frame_limit_p = min_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(seq)); + *frame_limit_p = min_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(scene, seq)); } } } @@ -1525,7 +1537,7 @@ static int sequencer_select_side_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - select_active_side_range(ed->seqbasep, sel_side, frame_ranges, frame_init); + select_active_side_range(scene, ed->seqbasep, sel_side, frame_ranges, frame_init); ED_outliner_select_sync_from_sequence_tag(C); @@ -1595,7 +1607,7 @@ static void seq_box_select_seq_from_preview(const bContext *C, rctf *rect, const SpaceSeq *sseq = CTX_wm_space_seq(C); SeqCollection *strips = SEQ_query_rendered_strips( - channels, seqbase, scene->r.cfra, sseq->chanshown); + scene, channels, seqbase, scene->r.cfra, sseq->chanshown); Sequence *seq; SEQ_ITERATOR_FOREACH (seq, strips) { if (!seq_box_select_rect_image_isect(scene, seq, rect)) { @@ -1648,15 +1660,15 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) { rctf rq; - seq_rectf(seq, &rq); + seq_rectf(scene, seq, &rq); if (BLI_rctf_isect(&rq, &rectf, NULL)) { if (handles) { /* Get the handles draw size. */ float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); - float handsize = sequence_handle_size_get_clamped(seq, pixelx); + float handsize = sequence_handle_size_get_clamped(scene, seq, pixelx); /* Right handle. */ - if (rectf.xmax > (SEQ_time_right_handle_frame_get(seq) - handsize)) { + if (rectf.xmax > (SEQ_time_right_handle_frame_get(scene, seq) - handsize)) { if (select) { seq->flag |= SELECT | SEQ_RIGHTSEL; } @@ -1669,7 +1681,7 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op) } } /* Left handle. */ - if (rectf.xmin < (SEQ_time_left_handle_frame_get(seq) + handsize)) { + if (rectf.xmin < (SEQ_time_left_handle_frame_get(scene, seq) + handsize)) { if (select) { seq->flag |= SELECT | SEQ_LEFTSEL; } @@ -1953,7 +1965,8 @@ static bool select_grouped_effect(SeqCollection *strips, return changed; } -static bool select_grouped_time_overlap(SeqCollection *strips, +static bool select_grouped_time_overlap(const Scene *scene, + SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq) { @@ -1961,8 +1974,10 @@ static bool select_grouped_time_overlap(SeqCollection *strips, Sequence *seq; SEQ_ITERATOR_FOREACH (seq, strips) { - if (SEQ_time_left_handle_frame_get(seq) < SEQ_time_right_handle_frame_get(actseq) && - SEQ_time_right_handle_frame_get(seq) > SEQ_time_left_handle_frame_get(actseq)) { + if (SEQ_time_left_handle_frame_get(scene, seq) < + SEQ_time_right_handle_frame_get(scene, actseq) && + SEQ_time_right_handle_frame_get(scene, seq) > + SEQ_time_left_handle_frame_get(scene, actseq)) { seq->flag |= SELECT; changed = true; } @@ -1972,7 +1987,8 @@ static bool select_grouped_time_overlap(SeqCollection *strips, } /* Query strips that are in lower channel and intersect in time with seq_reference. */ -static void query_lower_channel_strips(Sequence *seq_reference, +static void query_lower_channel_strips(const Scene *scene, + Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection) { @@ -1980,10 +1996,10 @@ static void query_lower_channel_strips(Sequence *seq_reference, if (seq_test->machine > seq_reference->machine) { continue; /* Not lower channel. */ } - if (SEQ_time_right_handle_frame_get(seq_test) <= - SEQ_time_left_handle_frame_get(seq_reference) || - SEQ_time_left_handle_frame_get(seq_test) >= - SEQ_time_right_handle_frame_get(seq_reference)) { + if (SEQ_time_right_handle_frame_get(scene, seq_test) <= + SEQ_time_left_handle_frame_get(scene, seq_reference) || + SEQ_time_left_handle_frame_get(scene, seq_test) >= + SEQ_time_right_handle_frame_get(scene, seq_reference)) { continue; /* Not intersecting in time. */ } SEQ_collection_append_strip(seq_test, collection); @@ -1992,7 +2008,8 @@ static void query_lower_channel_strips(Sequence *seq_reference, /* Select all strips within time range and with lower channel of initial selection. Then select * effect chains of these strips. */ -static bool select_grouped_effect_link(SeqCollection *strips, +static bool select_grouped_effect_link(const Scene *scene, + SeqCollection *strips, ListBase *seqbase, Sequence *UNUSED(actseq), const int UNUSED(channel)) @@ -2000,8 +2017,10 @@ static bool select_grouped_effect_link(SeqCollection *strips, /* Get collection of strips. */ SEQ_filter_selected_strips(strips); const int selected_strip_count = SEQ_collection_len(strips); - SEQ_collection_expand(seqbase, strips, query_lower_channel_strips); - SEQ_collection_expand(seqbase, strips, SEQ_query_strip_effect_chain); + // XXX this uses scene as arg, so it does not work with iterator :( I had thought about this, but + // expand function is just so useful... I can just add scene and inject it I guess..... + SEQ_collection_expand(scene, seqbase, strips, query_lower_channel_strips); + SEQ_collection_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain); /* Check if other strips will be affected. */ const bool changed = SEQ_collection_len(strips) > selected_strip_count; @@ -2067,10 +2086,10 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op) changed |= select_grouped_effect(strips, seqbase, actseq, channel); break; case SEQ_SELECT_GROUP_EFFECT_LINK: - changed |= select_grouped_effect_link(strips, seqbase, actseq, channel); + changed |= select_grouped_effect_link(scene, strips, seqbase, actseq, channel); break; case SEQ_SELECT_GROUP_OVERLAP: - changed |= select_grouped_time_overlap(strips, seqbase, actseq); + changed |= select_grouped_time_overlap(scene, strips, seqbase, actseq); break; default: BLI_assert(0); |