Skip to content

Commit

Permalink
Improve performance for Blueprint & Streams Panel for many entities (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
abey79 authored Jan 28, 2025
1 parent bf4c684 commit a54c80d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 deletions.
16 changes: 12 additions & 4 deletions crates/viewer/re_blueprint_tree/src/blueprint_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ impl BlueprintTree {

let item_response = ui
.list_item()
.render_offscreen(false)
.selected(ctx.selection().contains_item(&item))
.draggable(true) // allowed for consistency but results in an invalid drag
.drop_target_style(self.is_candidate_drop_parent_container(&container_data.id))
Expand Down Expand Up @@ -272,6 +273,7 @@ impl BlueprintTree {
..
} = ui
.list_item()
.render_offscreen(false)
.selected(ctx.selection().contains_item(&item))
.draggable(true)
.drop_target_style(self.is_candidate_drop_parent_container(&container_data.id))
Expand Down Expand Up @@ -360,6 +362,7 @@ impl BlueprintTree {
..
} = ui
.list_item()
.render_offscreen(false)
.selected(ctx.selection().contains_item(&item))
.draggable(true)
.force_hovered(is_item_hovered)
Expand All @@ -375,10 +378,13 @@ impl BlueprintTree {
}

if !view_data.projection_trees.is_empty() {
ui.list_item().interactive(false).show_flat(
ui,
list_item::LabelContent::new("Projections:").italics(true),
);
ui.list_item()
.render_offscreen(false)
.interactive(false)
.show_flat(
ui,
list_item::LabelContent::new("Projections:").italics(true),
);

for projection in &view_data.projection_trees {
self.data_result_ui(ctx, viewport_blueprint, ui, projection, view_visible);
Expand Down Expand Up @@ -481,6 +487,7 @@ impl BlueprintTree {
DataResultKind::OriginProjectionPlaceholder => {
if ui
.list_item()
.render_offscreen(false)
.show_hierarchical(
ui,
list_item::LabelContent::new("$origin")
Expand All @@ -507,6 +514,7 @@ impl BlueprintTree {

let list_item = ui
.list_item()
.render_offscreen(false)
.draggable(true)
.selected(is_selected)
.force_hovered(is_item_hovered);
Expand Down
29 changes: 17 additions & 12 deletions crates/viewer/re_time_panel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ impl TimePanel {
..
} = ui
.list_item()
.render_offscreen(false)
.selected(is_selected)
.draggable(true)
.force_hovered(is_item_hovered)
Expand Down Expand Up @@ -925,6 +926,7 @@ impl TimePanel {

let response = ui
.list_item()
.render_offscreen(false)
.selected(ctx.selection().contains_item(&item.to_item()))
.force_hovered(
ctx.selection_state()
Expand Down Expand Up @@ -975,18 +977,21 @@ impl TimePanel {
format!("{} times", re_format::format_uint(num_messages))
};

ui.list_item().interactive(false).show_flat(
ui,
list_item::LabelContent::new(format!(
"{kind} component, logged {num_messages}"
))
.truncate(false)
.with_icon(if is_static {
&re_ui::icons::COMPONENT_STATIC
} else {
&re_ui::icons::COMPONENT_TEMPORAL
}),
);
ui.list_item()
.interactive(false)
.render_offscreen(false)
.show_flat(
ui,
list_item::LabelContent::new(format!(
"{kind} component, logged {num_messages}"
))
.truncate(false)
.with_icon(if is_static {
&re_ui::icons::COMPONENT_STATIC
} else {
&re_ui::icons::COMPONENT_TEMPORAL
}),
);

// Static components are not displayed at all on the timeline, so cannot be
// previewed there. So we display their content in this tooltip instead.
Expand Down
23 changes: 23 additions & 0 deletions crates/viewer/re_ui/src/list_item/list_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub struct ListItem {
force_background: Option<egui::Color32>,
pub collapse_openness: Option<f32>,
height: f32,
render_offscreen: bool,
}

impl Default for ListItem {
Expand All @@ -62,6 +63,7 @@ impl Default for ListItem {
force_background: None,
collapse_openness: None,
height: DesignTokens::list_item_height(),
render_offscreen: true,
}
}
}
Expand Down Expand Up @@ -140,6 +142,18 @@ impl ListItem {
self
}

/// Controls whether [`Self`] calls [`ListItemContent::ui`] when the item is not currently
/// visible.
///
/// Skipping rendering can increase performances for long lists that are mostly out of view, but
/// this will prevent any side effects from [`ListItemContent::ui`] from occurring. For this
/// reason, this is an opt-in optimization.
#[inline]
pub fn render_offscreen(mut self, render_offscreen: bool) -> Self {
self.render_offscreen = render_offscreen;
self
}

/// Draw the item as part of a flat list.
///
/// *Important*: must be called while nested in a [`super::list_item_scope`].
Expand Down Expand Up @@ -274,6 +288,7 @@ impl ListItem {
force_background,
collapse_openness,
height,
render_offscreen,
} = self;

let collapse_extra = if collapse_openness.is_some() {
Expand Down Expand Up @@ -329,6 +344,14 @@ impl ListItem {
// allocate past the available width.
response.rect = rect;

let should_render = render_offscreen || ui.is_rect_visible(rect);
if !should_render {
return ListItemResponse {
response,
collapse_response: None,
};
}

// override_hover should not affect the returned response
let mut style_response = response.clone();
if force_hovered {
Expand Down

0 comments on commit a54c80d

Please sign in to comment.