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

[pure refactor] move time control to re_viewer_context #2045

Merged
merged 3 commits into from
May 4, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions crates/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion crates/re_viewer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
5 changes: 2 additions & 3 deletions crates/re_viewer/src/misc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ pub(crate) mod mesh_loader;
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;

Expand All @@ -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"))]
Expand All @@ -23,6 +21,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::{
Expand Down
93 changes: 61 additions & 32 deletions crates/re_viewer/src/misc/time_control_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,87 +3,101 @@ 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};

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")
.speed(1)
.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!(
Expand All @@ -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,
Expand All @@ -118,31 +140,37 @@ 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
.large_button(ui, &re_ui::icons::ARROW_RIGHT)
.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 => {
Expand 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 => {
Expand All @@ -163,23 +191,24 @@ 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)
.speed(drag_speed)
.suffix("x"),
)
.on_hover_text("Playback speed.");
self.set_speed(speed);
time_control.set_speed(speed);
}
}

Expand Down
3 changes: 1 addition & 2 deletions crates/re_viewer/src/misc/transform_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions crates/re_viewer/src/misc/viewer_context.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down