Skip to content

Commit

Permalink
wired up egui_plots update to selecting entities from plots
Browse files Browse the repository at this point in the history
  • Loading branch information
Wumpf committed Jan 30, 2024
1 parent 2c60146 commit 73e8926
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 51 deletions.
21 changes: 10 additions & 11 deletions Cargo.lock

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

14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,13 @@ debug = true
# As a last resport, patch with a commit to our own repository.
# ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk.

ecolor = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
eframe = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
egui = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
egui_extras = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
egui_plot = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
emath = { git = "https://github.com/emilk/egui.git", rev = "ab39420c2933d2e402999043375b64e7cf0ee9ed" } # egui master 2024-01-29
ecolor = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29
eframe = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29
egui = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29
egui_extras = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29
egui_plot = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29
egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29
emath = { git = "https://github.com/emilk/egui.git", rev = "37aa3973a2046e38c502f9fdb941c76fbd7a5f84" } # egui TODO: 2024-01-29

# Useful while developing:
# ecolor = { path = "../../egui/crates/ecolor" }
Expand Down
29 changes: 3 additions & 26 deletions crates/re_data_ui/src/item_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use re_entity_db::{EntityTree, InstancePath};
use re_log_types::{ComponentPath, EntityPath, TimeInt, Timeline};
use re_ui::SyntaxHighlighting;
use re_viewer_context::{
DataQueryId, HoverHighlight, Item, Selection, SpaceViewId, SystemCommandSender, UiVerbosity,
ViewerContext,
DataQueryId, HoverHighlight, Item, Selection, SpaceViewId, UiVerbosity, ViewerContext,
};

use super::DataUi;
Expand Down Expand Up @@ -347,30 +346,8 @@ pub fn select_hovered_on_click(
response: &egui::Response,
selection: impl Into<Selection>,
) {
re_tracing::profile_function!();

let mut selection = selection.into();
selection.resolve_mono_instance_path_items(ctx);
let selection_state = ctx.selection_state();

if response.hovered() {
selection_state.set_hovered(selection.clone());
}

if response.double_clicked() {
if let Some((item, _)) = selection.first() {
ctx.command_sender
.send_system(re_viewer_context::SystemCommand::SetFocus(item.clone()));
}
}

if response.clicked() {
if response.ctx.input(|i| i.modifiers.command) {
selection_state.toggle_selection(selection);
} else {
selection_state.set_selection(selection);
}
}
// TODO: inline everywhere.
ctx.select_hovered_on_click(response, selection);
}

/// Displays the "hover card" (i.e. big tooltip) for an instance or an entity.
Expand Down
26 changes: 23 additions & 3 deletions crates/re_space_view_time_series/src/space_view_class.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use egui::ahash::HashSet;
use egui::ahash::{HashMap, HashSet};
use egui_plot::{Legend, Line, Plot, Points};

use re_data_store::TimeType;
Expand Down Expand Up @@ -353,10 +353,13 @@ impl SpaceViewClass for TimeSeriesSpaceView {
plot = plot.x_grid_spacer(move |spacer| ns_grid_spacer(canvas_size, &spacer));
}

let mut plot_item_id_to_entity_path = HashMap::default();

let egui_plot::PlotResponse {
inner: time_x,
response,
transform,
hovered_plot_item,
} = plot.show(ui, |plot_ui| {
if plot_ui.response().secondary_clicked() {
let mut time_ctrl_write = ctx.rec_cfg.time_ctrl.write();
Expand All @@ -376,19 +379,23 @@ impl SpaceViewClass for TimeSeriesSpaceView {
.collect::<Vec<_>>();

let color = line.color;
let id = egui::Id::new(line.entity_path.hash());
plot_item_id_to_entity_path.insert(id, line.entity_path.clone());

match line.kind {
PlotSeriesKind::Continuous => plot_ui.line(
Line::new(points)
.name(&line.label)
.color(color)
.width(line.width),
.width(line.width)
.id(id),
),
PlotSeriesKind::Scatter => plot_ui.points(
Points::new(points)
.name(&line.label)
.color(color)
.radius(line.width),
.radius(line.width)
.id(id),
),
}
}
Expand Down Expand Up @@ -416,6 +423,19 @@ impl SpaceViewClass for TimeSeriesSpaceView {
.map(|x| plot_ui.screen_from_plot([x, 0.0].into()).x)
});

// Interact with the plot items (lines, scatters, etc.)
if let Some(hovered_plot_item) = hovered_plot_item {
if let Some(entity_path) = plot_item_id_to_entity_path.get(&hovered_plot_item) {
ctx.select_hovered_on_click(
&response,
re_viewer_context::Item::InstancePath(
Some(query.space_view_id),
entity_path.clone().into(),
),
);
}
}

if let Some(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 Down
15 changes: 12 additions & 3 deletions crates/re_space_view_time_series/src/visualizer_system.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use re_data_store::TimeRange;
use re_log_types::{StoreKind, TimeInt};
use re_log_types::{EntityPath, StoreKind, TimeInt};
use re_query_cache::{MaybeCachedComponentData, QueryError};
use re_types::{
archetypes::TimeSeriesScalar,
Expand Down Expand Up @@ -59,6 +59,7 @@ pub struct PlotSeries {
pub width: f32,
pub kind: PlotSeriesKind,
pub points: Vec<(i64, f64)>,
pub entity_path: EntityPath,
}

/// A scene for a time series plot, with everything needed to render it.
Expand Down Expand Up @@ -362,9 +363,10 @@ impl TimeSeriesSystem {
width: 2.0 * points[0].attrs.radius,
kind: PlotSeriesKind::Scatter,
points: vec![(points[0].time, points[0].value)],
entity_path: data_result.entity_path.clone(),
});
} else {
self.add_line_segments(&line_label, points);
self.add_line_segments(&line_label, points, &data_result.entity_path);
}
}

Expand All @@ -376,7 +378,12 @@ impl TimeSeriesSystem {
// A line segment is a continuous run of points with identical attributes: each time
// we notice a change in attributes, we need a new line segment.
#[inline(never)] // Better callstacks on crashes
fn add_line_segments(&mut self, line_label: &str, points: Vec<PlotPoint>) {
fn add_line_segments(
&mut self,
line_label: &str,
points: Vec<PlotPoint>,
entity_path: &EntityPath,
) {
re_tracing::profile_function!();

let num_points = points.len();
Expand All @@ -391,6 +398,7 @@ impl TimeSeriesSystem {
PlotSeriesKind::Continuous
},
points: Vec::with_capacity(num_points),
entity_path: entity_path.clone(),
};

for (i, p) in points.into_iter().enumerate() {
Expand All @@ -417,6 +425,7 @@ impl TimeSeriesSystem {
width: 2.0 * attrs.radius,
kind,
points: Vec::with_capacity(num_points - i),
entity_path: entity_path.clone(),
},
);
let prev_point = *prev_line.points.last().unwrap();
Expand Down
35 changes: 34 additions & 1 deletion crates/re_viewer_context/src/viewer_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use re_entity_db::entity_db::EntityDb;
use crate::{
query_context::DataQueryResult, AppOptions, ApplicableEntities, ApplicationSelectionState,
Caches, CommandSender, ComponentUiRegistry, DataQueryId, IndicatorMatchingEntities,
PerVisualizer, Selection, SpaceViewClassRegistry, StoreContext, TimeControl,
PerVisualizer, Selection, SpaceViewClassRegistry, StoreContext, SystemCommandSender as _,
TimeControl,
};

/// Common things needed by many parts of the viewer.
Expand Down Expand Up @@ -91,6 +92,38 @@ impl<'a> ViewerContext<'a> {
pub fn current_query(&self) -> re_data_store::LatestAtQuery {
self.rec_cfg.time_ctrl.read().current_query()
}

/// Set hover/select/focus for a given selection based on an egui response.
pub fn select_hovered_on_click(
&self,
response: &egui::Response,
selection: impl Into<Selection>,
) {
re_tracing::profile_function!();

let mut selection = selection.into();
selection.resolve_mono_instance_path_items(self);
let selection_state = self.selection_state();

if response.hovered() {
selection_state.set_hovered(selection.clone());
}

if response.double_clicked() {
if let Some((item, _)) = selection.first() {
self.command_sender
.send_system(crate::SystemCommand::SetFocus(item.clone()));
}
}

if response.clicked() {
if response.ctx.input(|i| i.modifiers.command) {
selection_state.toggle_selection(selection);
} else {
selection_state.set_selection(selection);
}
}
}
}

// ----------------------------------------------------------------------------
Expand Down

0 comments on commit 73e8926

Please sign in to comment.