mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-14 19:26:59 -04:00
Timeline: scrolling the video tracks up leaves room to drop a new track (fixes #1522)
This commit is contained in:
1 parent
71438c627b
commit
fe7efdaffc
1 file changed
+53
-7
@@ -233,6 +233,19 @@ fn new_track_at(seq: &Sequence, layout: &Layout, y: f32, vh: f32, ah: f32) -> Op
|
||||
}
|
||||
}
|
||||
|
||||
/// The top of each of `n` video rows `vh` high, V1 first: V1 sits at the bottom of `area` and the
|
||||
/// tracks stack upward; `v_scroll` (clamped here) shifts them up. Also gives the largest `v_scroll`.
|
||||
/// The scroll range includes one empty track's height above the top track: without it, tracks that
|
||||
/// fill the area leave no space where a drop adds a new one (#1522).
|
||||
fn video_row_tops(area: Rect, n: usize, vh: f32, v_scroll: &mut f32) -> (Vec<f32>, f32) {
|
||||
let total = (n + 1) as f32 * vh;
|
||||
let v_off = (area.height() - total).max(0.0);
|
||||
let max_vs = (total - area.height()).max(0.0);
|
||||
*v_scroll = v_scroll.clamp(0.0, max_vs);
|
||||
let tops = (0..n).map(|i| area.min.y + v_off + (n - i) as f32 * vh - (max_vs - *v_scroll)).collect();
|
||||
(tops, max_vs)
|
||||
}
|
||||
|
||||
/// How far the Timeline reaches, in seconds: ten minutes past the end of the sequence. Premiere
|
||||
/// Pro's Timeline does the same (on a 6 s sequence its view stops with 00:10:06 at the right
|
||||
/// edge). The view cannot be scrolled past it and the scroll bar spans it.
|
||||
@@ -412,14 +425,9 @@ pub fn show(app: &mut FilmcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
let vh = app.ui.timeline.video_track_h;
|
||||
let ah = app.ui.timeline.audio_track_h;
|
||||
let mut rows = Vec::new();
|
||||
// Video: V1 at the bottom of the video area, stacking upward; v_scroll shifts up.
|
||||
let nv = seq.video_tracks.len();
|
||||
let video_total = nv as f32 * vh;
|
||||
let v_off = (video_area.height() - video_total).max(0.0);
|
||||
let max_vs = (video_total - video_area.height()).max(0.0);
|
||||
app.ui.timeline.v_scroll = app.ui.timeline.v_scroll.clamp(0.0, max_vs);
|
||||
for (i, tr) in seq.video_tracks.iter().enumerate() {
|
||||
let top = video_area.min.y + v_off + (nv - 1 - i) as f32 * vh - (max_vs - app.ui.timeline.v_scroll);
|
||||
let (video_tops, max_vs) = video_row_tops(video_area, nv, vh, &mut app.ui.timeline.v_scroll);
|
||||
for ((i, tr), top) in seq.video_tracks.iter().enumerate().zip(video_tops) {
|
||||
let rect = Rect::from_min_max(pos2(content.min.x, top), pos2(content.max.x, top + vh));
|
||||
rows.push(Row { track: tr.id, kind: TrackKind::Video, index: i, rect, lane: false });
|
||||
}
|
||||
@@ -3201,4 +3209,42 @@ mod new_track_tests {
|
||||
assert_eq!(at(y), None, "y = {y}");
|
||||
}
|
||||
}
|
||||
|
||||
/// #1522: when the video tracks fill the video area, scrolling all the way up still leaves a
|
||||
/// track's height of empty space above the top one, so a drop there can add a fourth track.
|
||||
#[test]
|
||||
fn a_full_video_area_scrolls_to_space_for_a_new_track() {
|
||||
let mut p = Project::new("t");
|
||||
let id = p.new_sequence("s", SequenceSettings::default(), 3, 1, None);
|
||||
let seq = p.sequence(id).cloned().expect("sequence");
|
||||
// video area 0..150 holds V1..V3 exactly; scrolled up as far as it goes
|
||||
let area = Rect::from_min_max(pos2(0.0, 0.0), pos2(800.0, 150.0));
|
||||
let mut v_scroll = f32::MAX;
|
||||
let (tops, _) = video_row_tops(area, 3, 50.0, &mut v_scroll);
|
||||
let rows = seq
|
||||
.video_tracks
|
||||
.iter()
|
||||
.zip(&tops)
|
||||
.enumerate()
|
||||
.map(|(index, (t, &y0))| Row {
|
||||
track: t.id,
|
||||
kind: TrackKind::Video,
|
||||
index,
|
||||
rect: Rect::from_min_max(pos2(0.0, y0), pos2(800.0, y0 + 50.0)),
|
||||
lane: false,
|
||||
})
|
||||
.collect();
|
||||
let layout = Layout {
|
||||
content: Rect::from_min_max(pos2(0.0, 0.0), pos2(800.0, 500.0)),
|
||||
ruler: Rect::from_min_max(pos2(0.0, -20.0), pos2(800.0, 0.0)),
|
||||
rows,
|
||||
pps: 100.0,
|
||||
scroll: 0.0,
|
||||
split_y: 150.0,
|
||||
};
|
||||
assert_eq!(new_track_at(&seq, &layout, 10.0, 50.0, 50.0), Some((TrackKind::Video, Rect::from_min_max(pos2(0.0, 0.0), pos2(800.0, 50.0)))));
|
||||
// scrolled to the bottom, V1..V3 fill the area as before
|
||||
let mut v_scroll = 0.0;
|
||||
assert_eq!(video_row_tops(area, 3, 50.0, &mut v_scroll).0, vec![100.0, 50.0, 0.0]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user