From 2419605cc4740845e514bdcda3642f0da493cf6f Mon Sep 17 00:00:00 2001 From: bflatastic Date: Thu, 8 Oct 2026 23:11:04 +0700 Subject: [PATCH] Timeline: a press in the time ruler moves the current time (#284) The ruler moved the current-time indicator only once the pointer had dragged past egui's drag threshold, or on release for a click. As in After Effects, the time now jumps to the pointer as soon as the button goes down in the ruler, then follows the drag. Test: a_press_in_the_ruler_moves_the_current_time (ui_timeline_zoom). Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/panels/timeline.rs | 5 +++-- crates/ui-egui/tests/ui_timeline_zoom.rs | 28 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/ui-egui/src/panels/timeline.rs b/crates/ui-egui/src/panels/timeline.rs index 44d340b7..3ed530c1 100644 --- a/crates/ui-egui/src/panels/timeline.rs +++ b/crates/ui-egui/src/panels/timeline.rs @@ -1320,9 +1320,10 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { } s += secs_per_label; } - // Scrub in the ruler. + // Scrub in the ruler: the current time jumps to the pointer as soon as the button goes down + // (After Effects), then follows it. let rresp = ui.interact(Rect::from_min_max(pos2(graph_x0, ruler.min.y + 12.0), ruler.max), egui::Id::new("tl-ruler"), Sense::click_and_drag()); - if (rresp.dragged() || rresp.clicked()) + if ((rresp.is_pointer_button_down_on() && ui.input(|i| i.pointer.primary_down())) || rresp.clicked()) && let Some(pt) = rresp.interact_pointer_pos() { let mut secs = tm.t(pt.x).max(0.0); diff --git a/crates/ui-egui/tests/ui_timeline_zoom.rs b/crates/ui-egui/tests/ui_timeline_zoom.rs index 29f26b08..2a9c2ba9 100644 --- a/crates/ui-egui/tests/ui_timeline_zoom.rs +++ b/crates/ui-egui/tests/ui_timeline_zoom.rs @@ -213,3 +213,31 @@ fn shift_dragging_the_work_area_snaps_to_the_current_time() { drag_with(&mut h, mid, to, Modifiers::SHIFT); assert!(near(work_area(&h), (3.0, 6.0)), "the bar snaps its end to the CTI: {:?}", work_area(&h)); } + +/// #284: pressing in the time ruler moves the current time there at once, before the pointer +/// moves or the button comes up (After Effects); dragging on then scrubs. +#[test] +fn a_press_in_the_ruler_moves_the_current_time() { + let (mut h, _) = harness(); + // (Opening the comp showed all of it.) + h.state_mut().ui.timeline.pps = Some(200.0); + h.state_mut().ui.timeline.start = 10.0; + h.run_steps(2); + let ruler = rect(&h, "timeline.ruler"); + let (start, _) = visible(&h); + // 2 s into the visible span at 200 px/s (the ruler maps time from 6 px in). + let at = pos2(ruler.min.x + 6.0 + 400.0, ruler.min.y + 17.0); + h.event(Event::PointerMoved(at)); + h.step(); + h.event(Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed: true, modifiers: Modifiers::NONE }); + h.step(); + let now = h.state().session.time().seconds(); + assert!((now - (start + 2.0)).abs() < 0.05, "the press moved the CTI to {}: {now}", start + 2.0); + // Still held: dragging scrubs on. + h.event(Event::PointerMoved(at + vec2(100.0, 0.0))); + h.step(); + let now = h.state().session.time().seconds(); + assert!((now - (start + 2.5)).abs() < 0.05, "{now}"); + h.event(Event::PointerButton { pos: at + vec2(100.0, 0.0), button: egui::PointerButton::Primary, pressed: false, modifiers: Modifiers::NONE }); + h.step(); +}