Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix lagging time cursor when panning a time series plot #4972

Merged
merged 5 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions crates/re_space_view_time_series/src/space_view_class.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use egui::ahash::HashSet;
use egui_plot::{Legend, Line, Plot, Points};
use egui_plot::{Legend, Line, Plot, PlotPoint, Points};

use re_data_store::TimeType;
use re_format::next_grid_tick_magnitude_ns;
Expand Down Expand Up @@ -354,7 +354,7 @@ impl SpaceViewClass for TimeSeriesSpaceView {
}

let egui_plot::PlotResponse {
inner: time_x,
inner: _,
response,
transform,
} = plot.show(ui, |plot_ui| {
Expand Down Expand Up @@ -407,18 +407,18 @@ impl SpaceViewClass for TimeSeriesSpaceView {
}

state.was_dragging_time_cursor = state.is_dragging_time_cursor;

// decide if the time cursor should be displayed, and if where
current_time
.map(|current_time| (current_time - time_offset) as f64)
.filter(|&x| {
// only display the time cursor when it's actually above the plot area
plot_ui.plot_bounds().min()[0] <= x && x <= plot_ui.plot_bounds().max()[0]
})
.map(|x| plot_ui.screen_from_plot([x, 0.0].into()).x)
});

if let Some(time_x) = time_x {
// Decide if the time cursor should be displayed, and if so where:
let time_x = current_time
.map(|current_time| (current_time - time_offset) as f64)
.filter(|&x| {
// only display the time cursor when it's actually above the plot area
transform.bounds().min()[0] <= x && x <= transform.bounds().max()[0]
})
.map(|x| transform.position_from_point(&PlotPoint::new(x, 0.0)).x);

if let Some(mut time_x) = time_x {
let interact_radius = ui.style().interaction.resize_grab_radius_side;
let line_rect = egui::Rect::from_x_y_ranges(time_x..=time_x, response.rect.y_range())
.expand(interact_radius);
Expand All @@ -431,27 +431,29 @@ impl SpaceViewClass for TimeSeriesSpaceView {
state.is_dragging_time_cursor = false;
if response.dragged() {
if let Some(pointer_pos) = ui.input(|i| i.pointer.hover_pos()) {
let time =
time_offset + transform.value_from_position(pointer_pos).x.round() as i64;
let new_offset_time = transform.value_from_position(pointer_pos).x;
let new_time = time_offset + new_offset_time.round() as i64;

// Avoid frame-delay:
time_x = pointer_pos.x;

let mut time_ctrl = ctx.rec_cfg.time_ctrl.write();
time_ctrl.set_time(time);
time_ctrl.set_time(new_time);
time_ctrl.pause();

state.is_dragging_time_cursor = true;
}
}

let stroke = if response.dragged() {
ui.style().visuals.widgets.active.fg_stroke
} else if response.hovered() {
ui.style().visuals.widgets.hovered.fg_stroke
} else {
ui.visuals().widgets.inactive.fg_stroke
};
ctx.re_ui
.paint_time_cursor(ui.painter(), time_x, response.rect.y_range(), stroke);
ctx.re_ui.paint_time_cursor(
ui,
ui.painter(),
&response,
time_x,
response.rect.y_range(),
);
}

Ok(())
}
}
Expand Down
20 changes: 8 additions & 12 deletions crates/re_time_panel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1281,11 +1281,11 @@ fn time_marker_ui(
let is_anything_being_dragged = ui.memory(|mem| mem.is_anything_being_dragged());
let interact_radius = ui.style().interaction.resize_grab_radius_side;

let mut is_hovering = false;
let mut is_hovering_time_cursor = false;

// show current time as a line:
if let Some(time) = time_ctrl.time() {
if let Some(x) = time_ranges_ui.x_from_time_f32(time) {
if let Some(mut x) = time_ranges_ui.x_from_time_f32(time) {
if timeline_rect.x_range().contains(x) {
let line_rect =
Rect::from_x_y_ranges(x..=x, timeline_rect.top()..=ui.max_rect().bottom())
Expand All @@ -1295,30 +1295,26 @@ fn time_marker_ui(
.interact(line_rect, time_drag_id, egui::Sense::drag())
.on_hover_and_drag_cursor(timeline_cursor_icon);

is_hovering = !is_anything_being_dragged && response.hovered();
is_hovering_time_cursor = response.hovered();

if response.dragged() {
if let Some(pointer_pos) = pointer_pos {
if let Some(time) = time_ranges_ui.time_from_x_f32(pointer_pos.x) {
let time = time_ranges_ui.clamp_time(time);
time_ctrl.set_time(time);
time_ctrl.pause();

x = pointer_pos.x; // avoid frame-delay
}
}
}

let stroke = if response.dragged() {
ui.style().visuals.widgets.active.fg_stroke
} else if is_hovering {
ui.style().visuals.widgets.hovered.fg_stroke
} else {
ui.visuals().widgets.inactive.fg_stroke
};
re_ui.paint_time_cursor(
ui,
time_area_painter,
&response,
x,
Rangef::new(timeline_rect.top(), ui.max_rect().bottom()),
stroke,
);
}
}
Expand All @@ -1329,7 +1325,7 @@ fn time_marker_ui(
let is_pointer_in_timeline_rect = timeline_rect.contains(pointer_pos);

// Show preview?
if !is_hovering
if !is_hovering_time_cursor
&& is_pointer_in_timeline_rect
&& !is_anything_being_dragged
&& !is_hovering_the_loop_selection
Expand Down
11 changes: 10 additions & 1 deletion crates/re_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,11 +1073,20 @@ impl ReUi {
#[allow(clippy::unused_self)]
pub fn paint_time_cursor(
&self,
ui: &egui::Ui,
painter: &egui::Painter,
response: &egui::Response,
x: f32,
y: Rangef,
stroke: egui::Stroke,
) {
let stroke = if response.dragged() {
ui.style().visuals.widgets.active.fg_stroke
} else if response.hovered() {
ui.style().visuals.widgets.hovered.fg_stroke
} else {
ui.visuals().widgets.inactive.fg_stroke
};

let Rangef {
min: y_min,
max: y_max,
Expand Down
Loading