From f5eb74a992b95824bb9993dde01d94e979050b8b Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 May 2023 15:48:46 +0200 Subject: [PATCH 1/3] separate time_control and time_control_ui more strictly --- crates/re_viewer/src/app.rs | 5 +- crates/re_viewer/src/misc/mod.rs | 3 +- crates/re_viewer/src/misc/time_control.rs | 5 +- crates/re_viewer/src/misc/time_control_ui.rs | 91 +++++++++----- crates/re_viewer/src/ui/time_panel/mod.rs | 124 +++++++++++-------- 5 files changed, 139 insertions(+), 89 deletions(-) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 8fb48087732a..4f6c8a47105c 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -1021,7 +1021,10 @@ impl AppState { // move time last, so we get to see the first data first! ctx.rec_cfg .time_ctrl - .move_time(ui.ctx(), log_db.times_per_timeline()); + .move_time(log_db.times_per_timeline(), ui.ctx().input(|i| i.stable_dt)); + if ctx.rec_cfg.time_ctrl.play_state() == PlayState::Playing { + ui.ctx().request_repaint(); + } if WATERMARK { re_ui.paint_watermark(); diff --git a/crates/re_viewer/src/misc/mod.rs b/crates/re_viewer/src/misc/mod.rs index cdeca4706c80..0bce51c5e0a3 100644 --- a/crates/re_viewer/src/misc/mod.rs +++ b/crates/re_viewer/src/misc/mod.rs @@ -5,7 +5,7 @@ pub mod queries; pub(crate) mod space_info; mod space_view_highlights; pub(crate) mod time_control; -pub(crate) mod time_control_ui; +mod time_control_ui; mod transform_cache; mod viewer_context; @@ -23,6 +23,7 @@ pub(crate) mod profiler; #[cfg(not(target_arch = "wasm32"))] pub mod clipboard; +pub use time_control_ui::TimeControlUi; pub use transform_cache::{TransformCache, UnreachableTransform}; pub use space_view_highlights::{ diff --git a/crates/re_viewer/src/misc/time_control.rs b/crates/re_viewer/src/misc/time_control.rs index bc5a2a6f1cc4..8f3c15beacf1 100644 --- a/crates/re_viewer/src/misc/time_control.rs +++ b/crates/re_viewer/src/misc/time_control.rs @@ -114,7 +114,7 @@ impl Default for TimeControl { impl TimeControl { /// Update the current time - pub fn move_time(&mut self, egui_ctx: &egui::Context, times_per_timeline: &TimesPerTimeline) { + pub fn move_time(&mut self, times_per_timeline: &TimesPerTimeline, stable_dt: f32) { self.select_a_valid_timeline(times_per_timeline); let Some(full_range) = self.full_range(times_per_timeline) else { @@ -136,7 +136,7 @@ impl TimeControl { }); } PlayState::Playing => { - let dt = egui_ctx.input(|i| i.stable_dt).at_most(0.1) * self.speed; + let dt = stable_dt.at_most(0.1) * self.speed; let state = self .states @@ -166,7 +166,6 @@ impl TimeControl { } TimeType::Time => state.time += TimeReal::from(Duration::from_secs(dt)), } - egui_ctx.request_repaint(); // keep playing next frame if let Some(loop_range) = loop_range { if state.time > loop_range.max { diff --git a/crates/re_viewer/src/misc/time_control_ui.rs b/crates/re_viewer/src/misc/time_control_ui.rs index f35b23bb14d0..60e8ee7e41a5 100644 --- a/crates/re_viewer/src/misc/time_control_ui.rs +++ b/crates/re_viewer/src/misc/time_control_ui.rs @@ -5,34 +5,43 @@ use re_log_types::TimeType; use super::time_control::{Looping, PlayState, TimeControl}; -impl TimeControl { +#[derive(serde::Deserialize, serde::Serialize, Default)] +pub struct TimeControlUi; + +impl TimeControlUi { + #[allow(clippy::unused_self)] pub fn timeline_selector_ui( &mut self, + time_control: &mut TimeControl, times_per_timeline: &TimesPerTimeline, ui: &mut egui::Ui, ) { - self.select_a_valid_timeline(times_per_timeline); + time_control.select_a_valid_timeline(times_per_timeline); egui::ComboBox::from_id_source("timeline") - .selected_text(self.timeline().name().as_str()) + .selected_text(time_control.timeline().name().as_str()) .show_ui(ui, |ui| { ui.style_mut().wrap = Some(false); ui.set_min_width(64.0); for timeline in times_per_timeline.timelines() { if ui - .selectable_label(timeline == self.timeline(), timeline.name().as_str()) + .selectable_label( + timeline == time_control.timeline(), + timeline.name().as_str(), + ) .clicked() { - self.set_timeline(*timeline); + time_control.set_timeline(*timeline); } } }); } - pub fn fps_ui(&mut self, ui: &mut egui::Ui) { - if self.time_type() == TimeType::Sequence { - if let Some(mut fps) = self.fps() { + #[allow(clippy::unused_self)] + pub fn fps_ui(&mut self, time_control: &mut TimeControl, ui: &mut egui::Ui) { + if time_control.time_type() == TimeType::Sequence { + if let Some(mut fps) = time_control.fps() { ui.add( egui::DragValue::new(&mut fps) .suffix(" FPS") @@ -40,50 +49,55 @@ impl TimeControl { .clamp_range(0.0..=f32::INFINITY), ) .on_hover_text("Frames Per Second"); - self.set_fps(fps); + time_control.set_fps(fps); } } } pub fn play_pause_ui( &mut self, + time_control: &mut TimeControl, re_ui: &re_ui::ReUi, times_per_timeline: &TimesPerTimeline, ui: &mut egui::Ui, ) { ui.horizontal(|ui| { ui.spacing_mut().item_spacing.x = 5.0; // from figma - self.play_button_ui(re_ui, ui, times_per_timeline); - self.follow_button_ui(re_ui, ui, times_per_timeline); - self.pause_button_ui(re_ui, ui); - self.step_time_button_ui(re_ui, ui, times_per_timeline); - self.loop_button_ui(re_ui, ui); + self.play_button_ui(time_control, re_ui, ui, times_per_timeline); + self.follow_button_ui(time_control, re_ui, ui, times_per_timeline); + self.pause_button_ui(time_control, re_ui, ui); + self.step_time_button_ui(time_control, re_ui, ui, times_per_timeline); + self.loop_button_ui(time_control, re_ui, ui); }); } + #[allow(clippy::unused_self)] fn play_button_ui( &mut self, + time_control: &mut TimeControl, re_ui: &re_ui::ReUi, ui: &mut egui::Ui, times_per_timeline: &TimesPerTimeline, ) { - let is_playing = self.play_state() == PlayState::Playing; + let is_playing = time_control.play_state() == PlayState::Playing; if re_ui .large_button_selected(ui, &re_ui::icons::PLAY, is_playing) .on_hover_text(format!("Play.{}", toggle_playback_text(ui.ctx()))) .clicked() { - self.set_play_state(times_per_timeline, PlayState::Playing); + time_control.set_play_state(times_per_timeline, PlayState::Playing); } } + #[allow(clippy::unused_self)] fn follow_button_ui( &mut self, + time_control: &mut TimeControl, re_ui: &re_ui::ReUi, ui: &mut egui::Ui, times_per_timeline: &TimesPerTimeline, ) { - let is_following = self.play_state() == PlayState::Following; + let is_following = time_control.play_state() == PlayState::Following; if re_ui .large_button_selected(ui, &re_ui::icons::FOLLOW, is_following) .on_hover_text(format!( @@ -92,23 +106,31 @@ impl TimeControl { )) .clicked() { - self.set_play_state(times_per_timeline, PlayState::Following); + time_control.set_play_state(times_per_timeline, PlayState::Following); } } - fn pause_button_ui(&mut self, re_ui: &re_ui::ReUi, ui: &mut egui::Ui) { - let is_paused = self.play_state() == PlayState::Paused; + #[allow(clippy::unused_self)] + fn pause_button_ui( + &mut self, + time_control: &mut TimeControl, + re_ui: &re_ui::ReUi, + ui: &mut egui::Ui, + ) { + let is_paused = time_control.play_state() == PlayState::Paused; if re_ui .large_button_selected(ui, &re_ui::icons::PAUSE, is_paused) .on_hover_text(format!("Pause.{}", toggle_playback_text(ui.ctx()))) .clicked() { - self.pause(); + time_control.pause(); } } + #[allow(clippy::unused_self)] fn step_time_button_ui( &mut self, + time_control: &mut TimeControl, re_ui: &re_ui::ReUi, ui: &mut egui::Ui, times_per_timeline: &TimesPerTimeline, @@ -118,7 +140,7 @@ impl TimeControl { .on_hover_text("Step back to previous time with any new data (left arrow)") .clicked() { - self.step_time_back(times_per_timeline); + time_control.step_time_back(times_per_timeline); } if re_ui @@ -126,23 +148,29 @@ impl TimeControl { .on_hover_text("Step forwards to next time with any new data (right arrow)") .clicked() { - self.step_time_fwd(times_per_timeline); + time_control.step_time_fwd(times_per_timeline); } } - fn loop_button_ui(&mut self, re_ui: &re_ui::ReUi, ui: &mut egui::Ui) { + #[allow(clippy::unused_self)] + fn loop_button_ui( + &mut self, + time_control: &mut TimeControl, + re_ui: &re_ui::ReUi, + ui: &mut egui::Ui, + ) { let icon = &re_ui::icons::LOOP; ui.scope(|ui| { // Loop-button cycles between states: - match self.looping() { + match time_control.looping() { Looping::Off => { if re_ui .large_button_selected(ui, icon, false) .on_hover_text("Looping is off") .clicked() { - self.set_looping(Looping::All); + time_control.set_looping(Looping::All); } } Looping::All => { @@ -152,7 +180,7 @@ impl TimeControl { .on_hover_text("Looping entire recording") .clicked() { - self.set_looping(Looping::Selection); + time_control.set_looping(Looping::Selection); } } Looping::Selection => { @@ -163,15 +191,16 @@ impl TimeControl { .on_hover_text("Looping selection") .clicked() { - self.set_looping(Looping::Off); + time_control.set_looping(Looping::Off); } } } }); } - pub fn playback_speed_ui(&mut self, ui: &mut egui::Ui) { - let mut speed = self.speed(); + #[allow(clippy::unused_self)] + pub fn playback_speed_ui(&mut self, time_control: &mut TimeControl, ui: &mut egui::Ui) { + let mut speed = time_control.speed(); let drag_speed = (speed * 0.02).at_least(0.01); ui.add( egui::DragValue::new(&mut speed) @@ -179,7 +208,7 @@ impl TimeControl { .suffix("x"), ) .on_hover_text("Playback speed."); - self.set_speed(speed); + time_control.set_speed(speed); } } diff --git a/crates/re_viewer/src/ui/time_panel/mod.rs b/crates/re_viewer/src/ui/time_panel/mod.rs index dbbb95937e54..d590e50cef63 100644 --- a/crates/re_viewer/src/ui/time_panel/mod.rs +++ b/crates/re_viewer/src/ui/time_panel/mod.rs @@ -12,7 +12,7 @@ use re_data_store::{EntityTree, InstancePath, TimeHistogram}; use re_log_types::{ComponentPath, EntityPathPart, TimeInt, TimeRange, TimeReal}; use re_viewer_context::Item; -use crate::{TimeControl, TimeView, ViewerContext}; +use crate::{misc::TimeControlUi, TimeControl, TimeView, ViewerContext}; use super::{data_ui::DataUi, item_ui, selection_panel::what_is_selected_ui, Blueprint}; @@ -37,6 +37,9 @@ pub(crate) struct TimePanel { /// The time axis view, regenerated each frame. #[serde(skip)] time_ranges_ui: TimeRangesUi, + + /// Ui elements for controlling time. + time_control_ui: TimeControlUi, } impl Default for TimePanel { @@ -46,6 +49,7 @@ impl Default for TimePanel { prev_col_width: 400.0, next_col_right: 0.0, time_ranges_ui: Default::default(), + time_control_ui: TimeControlUi::default(), } } } @@ -110,7 +114,7 @@ impl TimePanel { ui.horizontal(|ui| { ui.spacing_mut().interact_size = Vec2::splat(top_bar_height); ui.visuals_mut().button_frame = true; - top_row_ui(ctx, ui); + self.top_row_ui(ctx, ui); }); }) .response @@ -148,13 +152,18 @@ impl TimePanel { let re_ui = &ctx.re_ui; let time_ctrl = &mut ctx.rec_cfg.time_ctrl; let times_per_timeline = ctx.log_db.times_per_timeline(); - time_ctrl.play_pause_ui(re_ui, times_per_timeline, ui); - time_ctrl.playback_speed_ui(ui); - time_ctrl.fps_ui(ui); + self.time_control_ui + .play_pause_ui(time_ctrl, re_ui, times_per_timeline, ui); + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); }); ui.horizontal(|ui| { let time_ctrl = &mut ctx.rec_cfg.time_ctrl; - time_ctrl.timeline_selector_ui(ctx.log_db.times_per_timeline(), ui); + self.time_control_ui.timeline_selector_ui( + time_ctrl, + ctx.log_db.times_per_timeline(), + ui, + ); collapsed_time_marker_and_time(ui, ctx); }); }); @@ -163,10 +172,12 @@ impl TimePanel { let re_ui = &ctx.re_ui; let time_ctrl = &mut ctx.rec_cfg.time_ctrl; let times_per_timeline = ctx.log_db.times_per_timeline(); - time_ctrl.play_pause_ui(re_ui, times_per_timeline, ui); - time_ctrl.timeline_selector_ui(times_per_timeline, ui); - time_ctrl.playback_speed_ui(ui); - time_ctrl.fps_ui(ui); + self.time_control_ui + .play_pause_ui(time_ctrl, re_ui, times_per_timeline, ui); + self.time_control_ui + .timeline_selector_ui(time_ctrl, times_per_timeline, ui); + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); collapsed_time_marker_and_time(ui, ctx); } @@ -565,6 +576,56 @@ impl TimePanel { } } } + + fn top_row_ui(&mut self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui) { + ui.spacing_mut().item_spacing.x = 18.0; // from figma + + if ui.max_rect().width() < 600.0 { + // Responsive ui for narrow screens, e.g. mobile. Split the controls into two rows. + ui.vertical(|ui| { + ui.horizontal(|ui| { + let re_ui = &ctx.re_ui; + let time_ctrl = &mut ctx.rec_cfg.time_ctrl; + let times_per_timeline = ctx.log_db.times_per_timeline(); + self.time_control_ui + .play_pause_ui(time_ctrl, re_ui, times_per_timeline, ui); + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); + }); + ui.horizontal(|ui| { + let time_ctrl = &mut ctx.rec_cfg.time_ctrl; + self.time_control_ui.timeline_selector_ui( + time_ctrl, + ctx.log_db.times_per_timeline(), + ui, + ); + + current_time_ui(ctx, ui); + + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + help_button(ui); + }); + }); + }); + } else { + // One row: + let re_ui = &ctx.re_ui; + let time_ctrl = &mut ctx.rec_cfg.time_ctrl; + let times_per_timeline = ctx.log_db.times_per_timeline(); + + self.time_control_ui + .play_pause_ui(time_ctrl, re_ui, times_per_timeline, ui); + self.time_control_ui + .timeline_selector_ui(time_ctrl, times_per_timeline, ui); + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); + current_time_ui(ctx, ui); + + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + help_button(ui); + }); + } + } } fn collapsed_time_marker_and_time(ui: &mut egui::Ui, ctx: &mut ViewerContext<'_>) { @@ -627,49 +688,6 @@ fn paint_streams_guide_line( ); } -fn top_row_ui(ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui) { - ui.spacing_mut().item_spacing.x = 18.0; // from figma - - if ui.max_rect().width() < 600.0 { - // Responsive ui for narrow screens, e.g. mobile. Split the controls into two rows. - ui.vertical(|ui| { - ui.horizontal(|ui| { - let re_ui = &ctx.re_ui; - let time_ctrl = &mut ctx.rec_cfg.time_ctrl; - let times_per_timeline = ctx.log_db.times_per_timeline(); - time_ctrl.play_pause_ui(re_ui, times_per_timeline, ui); - time_ctrl.playback_speed_ui(ui); - time_ctrl.fps_ui(ui); - }); - ui.horizontal(|ui| { - let time_ctrl = &mut ctx.rec_cfg.time_ctrl; - time_ctrl.timeline_selector_ui(ctx.log_db.times_per_timeline(), ui); - - current_time_ui(ctx, ui); - - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - help_button(ui); - }); - }); - }); - } else { - // One row: - let re_ui = &ctx.re_ui; - let time_ctrl = &mut ctx.rec_cfg.time_ctrl; - let times_per_timeline = ctx.log_db.times_per_timeline(); - - time_ctrl.play_pause_ui(re_ui, times_per_timeline, ui); - time_ctrl.timeline_selector_ui(times_per_timeline, ui); - time_ctrl.playback_speed_ui(ui); - time_ctrl.fps_ui(ui); - current_time_ui(ctx, ui); - - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - help_button(ui); - }); - } -} - fn help_button(ui: &mut egui::Ui) { crate::misc::help_hover_button(ui).on_hover_text( "\ From 558bc3326f8c26493baa82a24ae3e8ec2eb909cd Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 May 2023 15:49:16 +0200 Subject: [PATCH 2/3] remove egui dependency from time_control --- crates/re_viewer/src/misc/time_control.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/re_viewer/src/misc/time_control.rs b/crates/re_viewer/src/misc/time_control.rs index 8f3c15beacf1..0c9634588c99 100644 --- a/crates/re_viewer/src/misc/time_control.rs +++ b/crates/re_viewer/src/misc/time_control.rs @@ -1,7 +1,5 @@ use std::collections::{BTreeMap, BTreeSet}; -use egui::NumExt as _; - use re_data_store::TimesPerTimeline; use re_log_types::{Duration, TimeInt, TimeRange, TimeRangeF, TimeReal, TimeType, Timeline}; @@ -136,7 +134,7 @@ impl TimeControl { }); } PlayState::Playing => { - let dt = stable_dt.at_most(0.1) * self.speed; + let dt = stable_dt.min(0.1) * self.speed; let state = self .states From 101a7dc823985c5df99e2fbe08a697eb6e897819 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 May 2023 15:58:13 +0200 Subject: [PATCH 3/3] moved time control to re_viewer_ctx --- Cargo.lock | 1 + crates/re_viewer/src/app.rs | 4 ++-- crates/re_viewer/src/lib.rs | 2 +- crates/re_viewer/src/misc/mod.rs | 2 -- crates/re_viewer/src/misc/time_control_ui.rs | 2 +- crates/re_viewer/src/misc/transform_cache.rs | 3 +-- crates/re_viewer/src/misc/viewer_context.rs | 3 +-- crates/re_viewer/src/ui/time_panel/mod.rs | 4 ++-- crates/re_viewer/src/ui/time_panel/time_ranges_ui.rs | 3 ++- crates/re_viewer/src/ui/time_panel/time_selection_ui.rs | 3 +-- .../re_viewer/src/ui/view_spatial/scene/scene_part/cameras.rs | 3 ++- crates/re_viewer_context/Cargo.toml | 1 + crates/re_viewer_context/src/lib.rs | 2 ++ .../src/misc => re_viewer_context/src}/time_control.rs | 4 ++-- 14 files changed, 19 insertions(+), 18 deletions(-) rename crates/{re_viewer/src/misc => re_viewer_context/src}/time_control.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index f2a5bf1e19b6..d8aee9e98bf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4241,6 +4241,7 @@ dependencies = [ "itertools", "nohash-hasher", "puffin", + "re_arrow_store", "re_data_store", "re_log_types", "re_renderer", diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 4f6c8a47105c..42a1a2942408 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -14,10 +14,10 @@ use re_log_types::{ApplicationId, LogMsg, RecordingId}; use re_renderer::WgpuResourcePoolStatistics; use re_smart_channel::Receiver; use re_ui::{toasts, Command}; -use re_viewer_context::{AppOptions, Caches}; +use re_viewer_context::{AppOptions, Caches, PlayState}; use crate::{ - misc::{time_control::PlayState, RecordingConfig, ViewerContext}, + misc::{RecordingConfig, ViewerContext}, ui::{data_ui::ComponentUiRegistry, Blueprint}, viewer_analytics::ViewerAnalytics, }; diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 8337b6fc3438..833e71b67745 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -12,7 +12,7 @@ mod remote_viewer_app; mod ui; mod viewer_analytics; -pub(crate) use misc::{mesh_loader, TimeControl, TimeView, ViewerContext}; +pub(crate) use misc::{mesh_loader, ViewerContext}; use re_log_types::PythonVersion; pub(crate) use ui::{memory_panel, selection_panel, time_panel, UiVerbosity}; diff --git a/crates/re_viewer/src/misc/mod.rs b/crates/re_viewer/src/misc/mod.rs index 0bce51c5e0a3..dd5148f2ee3f 100644 --- a/crates/re_viewer/src/misc/mod.rs +++ b/crates/re_viewer/src/misc/mod.rs @@ -4,7 +4,6 @@ pub(crate) mod mesh_loader; pub mod queries; pub(crate) mod space_info; mod space_view_highlights; -pub(crate) mod time_control; mod time_control_ui; mod transform_cache; mod viewer_context; @@ -14,7 +13,6 @@ pub mod instance_hash_conversions; #[cfg(not(target_arch = "wasm32"))] pub(crate) use clipboard::Clipboard; -pub(crate) use time_control::{TimeControl, TimeView}; pub(crate) use viewer_context::*; #[cfg(not(target_arch = "wasm32"))] diff --git a/crates/re_viewer/src/misc/time_control_ui.rs b/crates/re_viewer/src/misc/time_control_ui.rs index 60e8ee7e41a5..644c6b9d7a7d 100644 --- a/crates/re_viewer/src/misc/time_control_ui.rs +++ b/crates/re_viewer/src/misc/time_control_ui.rs @@ -3,7 +3,7 @@ use egui::NumExt as _; use re_data_store::TimesPerTimeline; use re_log_types::TimeType; -use super::time_control::{Looping, PlayState, TimeControl}; +use re_viewer_context::{Looping, PlayState, TimeControl}; #[derive(serde::Deserialize, serde::Serialize, Default)] pub struct TimeControlUi; diff --git a/crates/re_viewer/src/misc/transform_cache.rs b/crates/re_viewer/src/misc/transform_cache.rs index e5c0504ab25e..a719390e321c 100644 --- a/crates/re_viewer/src/misc/transform_cache.rs +++ b/crates/re_viewer/src/misc/transform_cache.rs @@ -3,8 +3,7 @@ use re_arrow_store::LatestAtQuery; use re_data_store::{ log_db::EntityDb, query_latest_single, EntityPath, EntityPropertyMap, EntityTree, }; - -use crate::misc::TimeControl; +use re_viewer_context::TimeControl; /// Provides transforms from an entity to a chosen reference space for all elements in the scene /// for the currently selected time & timeline. diff --git a/crates/re_viewer/src/misc/viewer_context.rs b/crates/re_viewer/src/misc/viewer_context.rs index 0864ec070286..6235300a6bac 100644 --- a/crates/re_viewer/src/misc/viewer_context.rs +++ b/crates/re_viewer/src/misc/viewer_context.rs @@ -1,8 +1,7 @@ use re_data_store::log_db::LogDb; -use re_viewer_context::{AppOptions, Caches, Item, ItemCollection, SelectionState}; +use re_viewer_context::{AppOptions, Caches, Item, ItemCollection, SelectionState, TimeControl}; // TODO(andreas): Either viewer_context independent of these or move to re_viewer_context crate. -use super::TimeControl; use crate::ui::data_ui::ComponentUiRegistry; /// Common things needed by many parts of the viewer. diff --git a/crates/re_viewer/src/ui/time_panel/mod.rs b/crates/re_viewer/src/ui/time_panel/mod.rs index d590e50cef63..dc6369de6925 100644 --- a/crates/re_viewer/src/ui/time_panel/mod.rs +++ b/crates/re_viewer/src/ui/time_panel/mod.rs @@ -10,9 +10,9 @@ use egui::{pos2, Color32, CursorIcon, NumExt, PointerButton, Rect, Shape, Vec2}; use re_data_store::{EntityTree, InstancePath, TimeHistogram}; use re_log_types::{ComponentPath, EntityPathPart, TimeInt, TimeRange, TimeReal}; -use re_viewer_context::Item; +use re_viewer_context::{Item, TimeControl, TimeView}; -use crate::{misc::TimeControlUi, TimeControl, TimeView, ViewerContext}; +use crate::{misc::TimeControlUi, ViewerContext}; use super::{data_ui::DataUi, item_ui, selection_panel::what_is_selected_ui, Blueprint}; diff --git a/crates/re_viewer/src/ui/time_panel/time_ranges_ui.rs b/crates/re_viewer/src/ui/time_panel/time_ranges_ui.rs index ddce13504244..6c137d77b441 100644 --- a/crates/re_viewer/src/ui/time_panel/time_ranges_ui.rs +++ b/crates/re_viewer/src/ui/time_panel/time_ranges_ui.rs @@ -10,8 +10,9 @@ use egui::{lerp, remap, NumExt}; use itertools::Itertools as _; use re_log_types::{TimeInt, TimeRange, TimeRangeF, TimeReal}; +use re_viewer_context::{PlayState, TimeView}; -use crate::{misc::time_control::PlayState, TimeView, ViewerContext}; +use crate::ViewerContext; /// The ideal gap between time segments. /// diff --git a/crates/re_viewer/src/ui/time_panel/time_selection_ui.rs b/crates/re_viewer/src/ui/time_panel/time_selection_ui.rs index 730e3fe657a9..c594d99e05f3 100644 --- a/crates/re_viewer/src/ui/time_panel/time_selection_ui.rs +++ b/crates/re_viewer/src/ui/time_panel/time_selection_ui.rs @@ -2,8 +2,7 @@ use egui::{CursorIcon, Id, NumExt as _, Rect}; use re_data_store::LogDb; use re_log_types::{Duration, TimeInt, TimeRangeF, TimeReal, TimeType}; - -use crate::{misc::time_control::Looping, TimeControl}; +use re_viewer_context::{Looping, TimeControl}; use super::{is_time_safe_to_show, time_ranges_ui::TimeRangesUi}; diff --git a/crates/re_viewer/src/ui/view_spatial/scene/scene_part/cameras.rs b/crates/re_viewer/src/ui/view_spatial/scene/scene_part/cameras.rs index 0c8a7395e923..db579381982f 100644 --- a/crates/re_viewer/src/ui/view_spatial/scene/scene_part/cameras.rs +++ b/crates/re_viewer/src/ui/view_spatial/scene/scene_part/cameras.rs @@ -6,6 +6,7 @@ use re_log_types::{ }; use re_query::{query_entity_with_primary, EntityView, QueryError}; use re_renderer::renderer::LineStripFlags; +use re_viewer_context::TimeControl; use crate::{ misc::{ @@ -30,7 +31,7 @@ use super::{instance_path_hash_for_picking, ScenePart}; /// TODO(andreas): Doing a search upwards here isn't great. Maybe this can be part of the transform cache or similar? fn determine_view_coordinates( entity_db: &re_data_store::log_db::EntityDb, - time_ctrl: &crate::misc::TimeControl, + time_ctrl: &TimeControl, mut entity_path: EntityPath, ) -> ViewCoordinates { loop { diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 091c78658cbf..37575e7d80d7 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -16,6 +16,7 @@ include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"] all-features = true [dependencies] +re_arrow_store.workspace = true re_data_store = { workspace = true, features = ["serde"] } re_log_types = { workspace = true, features = ["ecolor", "glam", "image"] } re_renderer.workspace = true diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 73e5481a5361..6b46a7311f09 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -7,6 +7,7 @@ mod caches; mod item; mod selection_history; mod selection_state; +mod time_control; pub use app_options::AppOptions; pub use caches::{Cache, Caches}; @@ -15,6 +16,7 @@ pub use selection_history::SelectionHistory; pub use selection_state::{ HoverHighlight, HoveredSpace, InteractionHighlight, SelectionHighlight, SelectionState, }; +pub use time_control::{Looping, PlayState, TimeControl, TimeView}; // --------------------------------------------------------------------------- diff --git a/crates/re_viewer/src/misc/time_control.rs b/crates/re_viewer_context/src/time_control.rs similarity index 99% rename from crates/re_viewer/src/misc/time_control.rs rename to crates/re_viewer_context/src/time_control.rs index 0c9634588c99..4202ba1bcf56 100644 --- a/crates/re_viewer/src/misc/time_control.rs +++ b/crates/re_viewer_context/src/time_control.rs @@ -486,12 +486,12 @@ impl TimeControl { } /// The range of time we are currently zoomed in on. - pub(crate) fn time_view(&self) -> Option { + pub fn time_view(&self) -> Option { self.states.get(&self.timeline).and_then(|state| state.view) } /// The range of time we are currently zoomed in on. - pub(crate) fn set_time_view(&mut self, view: TimeView) { + pub fn set_time_view(&mut self, view: TimeView) { self.states .entry(self.timeline) .or_insert_with(|| TimeState::new(view.min))