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

Make Visible History UI more ergonomic and show inherited values #4222

Merged
merged 14 commits into from
Nov 16, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 3 additions & 19 deletions crates/re_data_store/src/entity_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,26 +256,8 @@ pub enum VisibleHistoryBoundary {
}

impl VisibleHistoryBoundary {
/// UI label to use when [`VisibleHistoryBoundary::RelativeToTimeCursor`] is selected.
pub const RELATIVE_LABEL: &'static str = "Relative";

/// UI label to use when [`VisibleHistoryBoundary::Absolute`] is selected.
pub const ABSOLUTE_LABEL: &'static str = "Absolute";

/// UI label to use when [`VisibleHistoryBoundary::Infinite`] is selected.
pub const INFINITE_LABEL: &'static str = "Infinite";

/// Value when the boundary is set to the current time cursor.
pub const AT_CURSOR: Self = Self::RelativeToTimeCursor(0);

/// Label to use in the UI.
pub fn label(&self) -> &'static str {
match self {
Self::RelativeToTimeCursor(_) => Self::RELATIVE_LABEL,
Self::Absolute(_) => Self::ABSOLUTE_LABEL,
Self::Infinite => Self::INFINITE_LABEL,
}
}
}

impl Default for VisibleHistoryBoundary {
Expand Down Expand Up @@ -345,8 +327,10 @@ impl ExtraQueryHistory {
fn with_child(&self, child: &Self) -> Self {
if child.enabled {
*child
} else {
} else if self.enabled {
*self
} else {
Self::default()
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions crates/re_query/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use re_arrow_store::{DataStore, LatestAtQuery, RangeQuery, TimeInt, TimeRange, Timeline};
use re_data_store::{ExtraQueryHistory, VisibleHistory};
use re_data_store::ExtraQueryHistory;
use re_log_types::EntityPath;
use re_types_core::Archetype;

Expand All @@ -17,14 +17,15 @@ pub fn query_archetype_with_history<'a, A: Archetype + 'a, const N: usize>(
re_log_types::TimeType::Sequence => history.sequences,
};

if !history.enabled || visible_history == VisibleHistory::OFF {
let latest_query = LatestAtQuery::new(*timeline, *time);
let min_time = visible_history.from(*time);
let max_time = visible_history.to(*time);

if !history.enabled || min_time == max_time {
let latest_query = LatestAtQuery::new(*timeline, min_time);
let latest = query_archetype::<A>(store, &latest_query, ent_path)?;

Ok(itertools::Either::Left(std::iter::once(latest)))
} else {
let min_time = visible_history.from(*time);
let max_time = visible_history.to(*time);
let range_query = RangeQuery::new(*timeline, TimeRange::new(min_time, max_time));

let range = range_archetype::<A, N>(store, &range_query, ent_path);
Expand Down
5 changes: 5 additions & 0 deletions crates/re_space_view/src/data_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ impl DataQuery for SpaceViewContents {
entity_path: entity_path.clone(),
view_parts,
resolved_properties,
individual_properties: entity_overrides.get_opt(entity_path).cloned(),
override_path: self
.entity_path()
.join(&SpaceViewContents::PROPERTIES_PREFIX.into())
Expand Down Expand Up @@ -219,12 +220,14 @@ impl DataBlueprintGroup {
}

let override_path = base_entity_path.join(&props_path).join(&entity_path);
let individual_properties = overrides.get_opt(&entity_path).cloned();

data_results.insert(DataResultNode {
data_result: DataResult {
entity_path,
view_parts,
resolved_properties,
individual_properties,
override_path,
},
children: Default::default(),
Expand All @@ -251,11 +254,13 @@ impl DataBlueprintGroup {

children.append(&mut recursive_children);

let individual_properties = overrides.get_opt(&group_path).cloned();
data_results.insert(DataResultNode {
data_result: DataResult {
entity_path: group_path,
view_parts: group_view_parts,
resolved_properties: group_resolved_properties,
individual_properties,
override_path: group_override_path,
},
children,
Expand Down
1 change: 1 addition & 0 deletions crates/re_space_view/src/space_view_contents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ impl SpaceViewContents {
let parent_group = self.groups.insert(DataBlueprintGroup {
display_name: path_to_group_name(&parent_path),
children: smallvec![new_group],
group_path: parent_path.clone(),
..Default::default()
});
vacant_mapping.insert(parent_group);
Expand Down
5 changes: 5 additions & 0 deletions crates/re_ui/examples/re_ui_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ impl eframe::App for ExampleApp {
ui.style_mut().wrap = Some(false);
ui.label("Some blueprint stuff here, that might be wide.");
self.re_ui.checkbox(ui, &mut self.dummy_bool, "Checkbox");

self.re_ui.collapsing_header(ui, "Collapsing header", true, |ui| {
ui.label("Some data here");
self.re_ui.checkbox(ui, &mut self.dummy_bool, "Checkbox");
});
});
});
});
Expand Down
133 changes: 96 additions & 37 deletions crates/re_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub use command_palette::CommandPalette;
pub use design_tokens::DesignTokens;
pub use icons::Icon;
pub use layout_job_builder::LayoutJobBuilder;
use std::ops::RangeInclusive;
pub use toggle_switch::toggle_switch;

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -49,7 +48,7 @@ pub struct TopBarStyle {
use crate::list_item::ListItem;
use egui::emath::{Rangef, Rot2};
use egui::epaint::util::FloatOrd;
use egui::{pos2, Align2, Color32, Mesh, NumExt, Rect, Shape, Vec2};
use egui::{pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape, Vec2};

#[derive(Clone)]
pub struct ReUi {
Expand Down Expand Up @@ -446,41 +445,6 @@ impl ReUi {
.inner
}

/// Shows a `egui::DragValue` for a time in nanoseconds.
///
/// The value and unit displayed adapts to the provided allowable time range.
#[allow(clippy::unused_self)]
pub fn time_drag_value(
&self,
ui: &mut egui::Ui,
value: &mut i64,
time_range: &RangeInclusive<i64>,
) {
let span = time_range.end() - time_range.start();

let (unit, factor) = if span / 1_000_000_000 > 0 {
("s", 1_000_000_000.)
} else if span / 1_000_000 > 0 {
("ms", 1_000_000.)
} else if span / 1_000 > 0 {
("μs", 1_000.)
} else {
("ns", 1.)
};

let mut time_unit = *value as f32 / factor;
let time_range = *time_range.start() as f32 / factor..=*time_range.end() as f32 / factor;
let speed = (time_range.end() - time_range.start()) * 0.005;

ui.add(
egui::DragValue::new(&mut time_unit)
.clamp_range(time_range)
.speed(speed)
.suffix(unit),
);
*value = (time_unit * factor).round() as _;
}

pub fn large_button(&self, ui: &mut egui::Ui, icon: &Icon) -> egui::Response {
self.large_button_impl(ui, icon, None, None)
}
Expand Down Expand Up @@ -579,6 +543,101 @@ impl ReUi {
.inner
}

/// Replacement for [`egui::CollapsingHeader`] that respect our style.
///
/// The layout is fine-tuned to fit well in inspector panels (such as Rerun's Selection Panel)
/// where the collapsing header should align nicely with checkboxes and other controls.
#[allow(clippy::unused_self)]
pub fn collapsing_header<R>(
&self,
ui: &mut egui::Ui,
label: &str,
default_open: bool,
add_body: impl FnOnce(&mut egui::Ui) -> R,
) -> egui::CollapsingResponse<R> {
let id = ui.make_persistent_id(label);
let button_padding = ui.spacing().button_padding;

let available = ui.available_rect_before_wrap();
// TODO(ab): use design token for indent — cannot use the global indent value as we must
// align with checkbox, etc.
let indent = 18.0;
let text_pos = available.min + egui::vec2(indent, 0.0);
let wrap_width = available.right() - text_pos.x;
let wrap = Some(false);
let text = egui::WidgetText::from(label).into_galley(
ui,
wrap,
wrap_width,
egui::TextStyle::Button,
);
let text_max_x = text_pos.x + text.size().x;

let mut desired_width = text_max_x + button_padding.x - available.left();
if ui.visuals().collapsing_header_frame {
desired_width = desired_width.max(available.width()); // fill full width
}

let mut desired_size = egui::vec2(desired_width, text.size().y + 2.0 * button_padding.y);
desired_size = desired_size.at_least(ui.spacing().interact_size);
let (_, rect) = ui.allocate_space(desired_size);

let mut header_response = ui.interact(rect, id, egui::Sense::click());
let text_pos = pos2(
text_pos.x,
header_response.rect.center().y - text.size().y / 2.0,
);

let mut state = egui::collapsing_header::CollapsingState::load_with_default_open(
ui.ctx(),
id,
default_open,
);
if header_response.clicked() {
state.toggle(ui);
header_response.mark_changed();
}

let openness = state.openness(ui.ctx());

if ui.is_rect_visible(rect) {
let visuals = ui.style().interact(&header_response);

{
let space_around_icon = 3.0;
let icon_width = ui.spacing().icon_width_inner;

let icon_rect = egui::Rect::from_center_size(
header_response.rect.left_center()
+ egui::vec2(space_around_icon + icon_width / 2.0, 0.0),
egui::Vec2::splat(icon_width),
);

let icon_response = header_response.clone().with_new_rect(icon_rect);
Self::paint_collapsing_triangle(ui, openness, icon_rect, &icon_response);
}

text.paint_with_visuals(ui.painter(), text_pos, visuals);
}

let ret_response = ui
.vertical(|ui| {
ui.spacing_mut().indent = indent;
state.show_body_indented(&header_response, ui, add_body)
})
.inner;

let (body_response, body_returned) =
ret_response.map_or((None, None), |r| (Some(r.response), Some(r.inner)));

CollapsingResponse {
header_response,
body_response,
body_returned,
openness,
}
}

/// Show a prominent collapsing header to be used as section delimitation in side panels.
///
/// Note that a clip rect must be set (typically by the panel) to avoid any overdraw.
Expand Down
2 changes: 2 additions & 0 deletions crates/re_viewer/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod welcome_screen;
pub(crate) mod memory_panel;
pub(crate) mod selection_panel;

pub(crate) mod visible_history;

pub use blueprint_panel::blueprint_panel_ui;
pub use recordings_panel::recordings_panel_ui;
// ----
Expand Down
Loading
Loading