diff --git a/.vscode/launch.json b/.vscode/launch.json index 63ff594e3064..c26e49b82213 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -30,6 +30,7 @@ "args": [ "build", "--package=rerun-cli", + "--no-default-features", "--features=native_viewer" ], "filter": { @@ -49,7 +50,9 @@ "cargo": { "args": [ "build", - "--package=rerun-cli" + "--package=rerun-cli", + "--no-default-features", + "--features=native_viewer" ], "filter": { "name": "rerun", @@ -68,7 +71,9 @@ "cargo": { "args": [ "build", - "--package=rerun-cli" + "--package=rerun-cli", + "--no-default-features", + "--features=native_viewer" ], "filter": { "name": "rerun", diff --git a/Cargo.lock b/Cargo.lock index a6e95f923a30..d22be1116e4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ dependencies = [ "anyhow", "clap", "glam", - "itertools", + "itertools 0.11.0", "ndarray", "ndarray-rand", "rand", @@ -1074,7 +1074,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -1095,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -1339,7 +1339,7 @@ dependencies = [ name = "dna" version = "0.8.0-alpha.0" dependencies = [ - "itertools", + "itertools 0.11.0", "rand", "rerun", ] @@ -1487,15 +1487,12 @@ dependencies = [ [[package]] name = "egui_tiles" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f501eb342a1d53e11842687f360bb9ba5c7971ba443057ac252add5dd2b3d3d" +source = "git+https://github.com/rerun-io/egui_tiles.git?rev=0127ad5eeed91beefd03b0ff1733200b32fb9a12#0127ad5eeed91beefd03b0ff1733200b32fb9a12" dependencies = [ + "ahash 0.8.3", "egui", - "getrandom", - "itertools", + "itertools 0.11.0", "log", - "nohash-hasher", - "rand", "serde", ] @@ -2429,6 +2426,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.6" @@ -3650,7 +3656,7 @@ checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", "heck 0.4.1", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "multimap", @@ -3671,7 +3677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", @@ -3918,7 +3924,7 @@ dependencies = [ "criterion", "document-features", "indent", - "itertools", + "itertools 0.11.0", "mimalloc", "nohash-hasher", "parking_lot 0.12.1", @@ -3977,7 +3983,7 @@ dependencies = [ "glam", "half 2.2.1", "image", - "itertools", + "itertools 0.11.0", "lazy_static", "ndarray", "nohash-hasher", @@ -3999,7 +4005,7 @@ name = "re_crash_handler" version = "0.8.0-alpha.0" dependencies = [ "backtrace", - "itertools", + "itertools 0.11.0", "libc", "parking_lot 0.12.1", "re_analytics", @@ -4013,7 +4019,7 @@ dependencies = [ "ahash 0.8.3", "criterion", "document-features", - "itertools", + "itertools 0.11.0", "mimalloc", "nohash-hasher", "rand", @@ -4039,7 +4045,7 @@ dependencies = [ "egui", "egui_extras", "image", - "itertools", + "itertools 0.11.0", "nohash-hasher", "re_arrow_store", "re_components", @@ -4134,7 +4140,7 @@ dependencies = [ "crossbeam", "document-features", "fixed", - "itertools", + "itertools 0.11.0", "nohash-hasher", "num-derive", "num-traits", @@ -4162,7 +4168,7 @@ dependencies = [ "ahash 0.8.3", "backtrace", "emath", - "itertools", + "itertools 0.11.0", "memory-stats", "nohash-hasher", "once_cell", @@ -4182,7 +4188,7 @@ dependencies = [ "arrow2", "criterion", "document-features", - "itertools", + "itertools 0.11.0", "mimalloc", "polars-core", "re_arrow_store", @@ -4216,7 +4222,7 @@ dependencies = [ "gltf", "half 2.2.1", "image", - "itertools", + "itertools 0.11.0", "log", "macaw", "never", @@ -4339,7 +4345,7 @@ dependencies = [ "eframe", "egui", "glam", - "itertools", + "itertools 0.11.0", "macaw", "nohash-hasher", "parking_lot 0.12.1", @@ -4473,7 +4479,7 @@ name = "re_time_panel" version = "0.8.0-alpha.0" dependencies = [ "egui", - "itertools", + "itertools 0.11.0", "re_arrow_store", "re_data_store", "re_data_ui", @@ -4516,7 +4522,7 @@ dependencies = [ "document-features", "ecolor", "glam", - "itertools", + "itertools 0.11.0", "macaw", "re_build_tools", "re_types_builder", @@ -4571,7 +4577,7 @@ dependencies = [ "egui", "egui-wgpu", "image", - "itertools", + "itertools 0.11.0", "objc", "poll-promise", "puffin", @@ -4625,7 +4631,7 @@ dependencies = [ "egui-wgpu", "glam", "half 2.2.1", - "itertools", + "itertools 0.11.0", "lazy_static", "macaw", "ndarray", @@ -4661,7 +4667,7 @@ dependencies = [ "enumset", "glam", "image", - "itertools", + "itertools 0.11.0", "nohash-hasher", "re_arrow_store", "re_components", @@ -4780,7 +4786,7 @@ dependencies = [ "anyhow", "clap", "document-features", - "itertools", + "itertools 0.11.0", "puffin", "rayon", "re_analytics", @@ -4825,7 +4831,7 @@ dependencies = [ "arrow2", "document-features", "image", - "itertools", + "itertools 0.11.0", "mimalloc", "numpy", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 78b81dcc215b..e0e7e502375f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,7 @@ glam = "0.22" gltf = "1.1" half = "2.0" image = { version = "0.24", default-features = false } -itertools = "0.10" +itertools = "0.11" lazy_static = "1.4" macaw = "0.18" mimalloc = "0.1.29" @@ -143,3 +143,5 @@ debug = true # If that is not possible, patch to a branch that has a PR open on the upstream repo. # 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. + +egui_tiles = { git = "https://github.com/rerun-io/egui_tiles.git", rev = "0127ad5eeed91beefd03b0ff1733200b32fb9a12" } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index d3290e90c41a..01f2f8c4919f 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -60,7 +60,10 @@ impl DataUi for EntityComponentWithInstances { ui.label(ctx.re_ui.error_text("Error: missing instance key")); } } else if one_line { - ui.label(format!("{num_instances} values")); + ui.label(format!( + "{} values", + re_format::format_large_number(num_instances as _) + )); } else { egui_extras::TableBuilder::new(ui) .resizable(false) diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index 35f45b719368..9e59abcb4666 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -278,12 +278,10 @@ fn egui_debug_options_ui(ui: &mut egui::Ui) { ) .on_hover_text("Show an overlay on all interactive widgets.") .changed(); - - // This option currently causes the viewer to hang. - // any_clicked |= ui - // .checkbox(&mut debug.show_blocking_widget, "Show blocking widgets") - // .on_hover_text("Show what widget blocks the interaction of another widget.") - // .changed(); + any_clicked |= ui + .checkbox(&mut debug.show_blocking_widget, "Show blocking widgets") + .on_hover_text("Show what widget blocks the interaction of another widget.") + .changed(); if any_clicked { let mut style = (*ui.ctx().style()).clone(); diff --git a/crates/re_viewport/src/auto_layout.rs b/crates/re_viewport/src/auto_layout.rs index acf3d4c21659..352a26c8ce6f 100644 --- a/crates/re_viewport/src/auto_layout.rs +++ b/crates/re_viewport/src/auto_layout.rs @@ -47,13 +47,11 @@ enum SplitDirection { pub(crate) fn tree_from_space_views( ctx: &mut ViewerContext<'_>, viewport_size: egui::Vec2, - visible: &std::collections::BTreeSet, space_views: &BTreeMap, space_view_states: &HashMap>, ) -> egui_tiles::Tree { let mut space_make_infos = space_views .iter() - .filter(|(space_view_id, _space_view)| visible.contains(space_view_id)) // Sort for determinism: .sorted_by_key(|(space_view_id, space_view)| { ( diff --git a/crates/re_viewport/src/blueprint_components/mod.rs b/crates/re_viewport/src/blueprint_components/mod.rs index f13f0f6e6601..8028c7d6b878 100644 --- a/crates/re_viewport/src/blueprint_components/mod.rs +++ b/crates/re_viewport/src/blueprint_components/mod.rs @@ -4,6 +4,4 @@ mod space_view; mod viewport; pub use space_view::SpaceViewComponent; -pub use viewport::{ - AutoSpaceViews, SpaceViewMaximized, SpaceViewVisibility, ViewportLayout, VIEWPORT_PATH, -}; +pub use viewport::{AutoSpaceViews, SpaceViewMaximized, ViewportLayout, VIEWPORT_PATH}; diff --git a/crates/re_viewport/src/blueprint_components/viewport.rs b/crates/re_viewport/src/blueprint_components/viewport.rs index a399e0ac1e54..4b2661676eaf 100644 --- a/crates/re_viewport/src/blueprint_components/viewport.rs +++ b/crates/re_viewport/src/blueprint_components/viewport.rs @@ -1,12 +1,9 @@ -use ahash::HashMap; use arrow2_convert::{ArrowDeserialize, ArrowField, ArrowSerialize}; use re_log_types::{serde_field::SerdeField, Component, ComponentName}; pub use re_viewer_context::SpaceViewId; -use crate::viewport::VisibilitySet; - pub const VIEWPORT_PATH: &str = "viewport"; /// A flag indicating space views should be automatically populated @@ -32,31 +29,6 @@ impl Component for AutoSpaceViews { } } -/// The set of currently visible spaces -/// -/// ## Example -/// ``` -/// # use re_viewport::blueprint_components::SpaceViewVisibility; -/// # use arrow2_convert::field::ArrowField; -/// # use arrow2::datatypes::{DataType, Field}; -/// assert_eq!( -/// SpaceViewVisibility::data_type(), -/// DataType::Binary -/// ); -/// ``` -#[derive(Clone, Default, ArrowField, ArrowSerialize, ArrowDeserialize)] -#[arrow_field(transparent)] -pub struct SpaceViewVisibility( - #[arrow_field(type = "SerdeField")] pub VisibilitySet, -); - -impl Component for SpaceViewVisibility { - #[inline] - fn name() -> ComponentName { - "rerun.blueprint.space_view_visibility".into() - } -} - /// Whether a space view is maximized /// /// ## Example @@ -93,7 +65,7 @@ impl Component for SpaceViewMaximized { /// ViewportLayout::data_type(), /// DataType::Struct(vec![ /// Field::new("space_view_keys", DataType::Binary, false), -/// Field::new("trees", DataType::Binary, false), +/// Field::new("tree", DataType::Binary, false), /// Field::new("has_been_user_edited", DataType::Boolean, false), /// ]) /// ); @@ -102,8 +74,10 @@ impl Component for SpaceViewMaximized { pub struct ViewportLayout { #[arrow_field(type = "SerdeField>")] pub space_view_keys: std::collections::BTreeSet, - #[arrow_field(type = "SerdeField>>")] - pub trees: HashMap>, + + #[arrow_field(type = "SerdeField>")] + pub tree: egui_tiles::Tree, + pub has_been_user_edited: bool, } diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index 987ada2e6a17..4b017aa5a604 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -23,10 +23,14 @@ use crate::{ space_view_highlights::highlights_for_space_view, }; -// ---------------------------------------------------------------------------- +#[must_use] +#[derive(Clone, Copy, Debug, PartialEq)] +enum TreeAction { + Keep, + Remove, +} -/// What views are visible? -pub type VisibilitySet = std::collections::BTreeSet; +// ---------------------------------------------------------------------------- /// Describes the layout and contents of the Viewport Panel. #[derive(Clone, Default, serde::Deserialize, serde::Serialize)] @@ -37,15 +41,8 @@ pub struct Viewport { /// Not a hashmap in order to preserve the order of the space views. pub space_views: BTreeMap, - /// Which views are visible. - pub visible: VisibilitySet, - /// The layouts of all the space views. - /// - /// One for each combination of what views are visible. - /// So if a user toggles the visibility of one SpaceView, we - /// switch which layout we are using. This is somewhat hacky. - pub trees: HashMap>, + pub tree: egui_tiles::Tree, /// Show one tab as maximized? pub maximized: Option, @@ -87,8 +84,7 @@ impl Viewport { pub(crate) fn remove(&mut self, space_view_id: &SpaceViewId) -> Option { let Self { space_views, - visible, - trees, + tree, maximized, has_been_user_edited, auto_space_views: _, @@ -96,13 +92,14 @@ impl Viewport { *has_been_user_edited = true; - trees.retain(|vis_set, _| !vis_set.contains(space_view_id)); - if *maximized == Some(*space_view_id) { *maximized = None; } - visible.remove(space_view_id); + if let Some(tile_id) = tree.tiles.find_pane(space_view_id) { + tree.tiles.remove(tile_id); + } + space_views.remove(space_view_id) } @@ -113,20 +110,10 @@ impl Viewport { egui::ScrollArea::both() .auto_shrink([true, false]) .show(ui, |ui| { - let space_view_ids = self - .space_views - .keys() - .sorted_by_key(|space_view_id| { - ( - &self.space_views[space_view_id].space_origin, - *space_view_id, - ) - }) - .copied() - .collect_vec(); - - for space_view_id in &space_view_ids { - self.space_view_entry_ui(ctx, ui, space_view_id); + if let Some(root) = self.tree.root() { + if self.tile_ui(ctx, ui, root) == TreeAction::Remove { + self.tree.root = None; + } } }); } @@ -137,21 +124,110 @@ impl Viewport { 2 <= num_children && num_children <= 3 } + fn tile_ui( + &mut self, + ctx: &mut ViewerContext<'_>, + ui: &mut egui::Ui, + tile_id: egui_tiles::TileId, + ) -> TreeAction { + // Temporarily remove the tile so we don't get borrow checker fights: + let Some(mut tile) = self.tree.tiles.remove(tile_id) else { return TreeAction::Remove; }; + + let action = match &mut tile { + egui_tiles::Tile::Container(container) => { + self.container_tree_ui(ctx, ui, tile_id, container) + } + egui_tiles::Tile::Pane(space_view_id) => { + // A space view + self.space_view_entry_ui(ctx, ui, tile_id, space_view_id) + } + }; + + self.tree.tiles.insert(tile_id, tile); + + if action == TreeAction::Remove { + for tile in self.tree.tiles.remove_recursively(tile_id) { + if let egui_tiles::Tile::Pane(space_view_id) = tile { + self.remove(&space_view_id); + } + } + } + + action + } + + fn container_tree_ui( + &mut self, + ctx: &mut ViewerContext<'_>, + ui: &mut egui::Ui, + tile_id: egui_tiles::TileId, + container: &mut egui_tiles::Container, + ) -> TreeAction { + if let Some(child_id) = container.only_child() { + // Maybe a tab container with only one child - collapse it in the tree view to make it more easily understood. + // This means we won't be showing the visibility button of the parent container, + // so if the child is made invisible, we should do the same for the parent. + let child_is_visible = self.tree.is_visible(child_id); + self.tree.set_visible(tile_id, child_is_visible); + return self.tile_ui(ctx, ui, child_id); + } + + let mut visibility_changed = false; + let mut action = TreeAction::Keep; + let mut visible = self.tree.is_visible(tile_id); + + let default_open = true; + egui::collapsing_header::CollapsingState::load_with_default_open( + ui.ctx(), + egui::Id::new((tile_id, "tree")), + default_open, + ) + .show_header(ui, |ui| { + blueprint_row_with_buttons( + ctx.re_ui, + ui, + true, + visible, + |ui| ui.label(format!("{:?}", container.kind())), + |re_ui, ui| { + visibility_changed = + visibility_button_ui(re_ui, ui, true, &mut visible).changed(); + if re_ui + .small_icon_button(ui, &re_ui::icons::REMOVE) + .on_hover_text("Remove container") + .clicked() + { + action = TreeAction::Remove; + } + }, + ); + }) + .body(|ui| container.retain(|child| self.tile_ui(ctx, ui, child) == TreeAction::Keep)); + + if visibility_changed { + self.has_been_user_edited = true; + self.tree.set_visible(tile_id, visible); + } + + action + } + fn space_view_entry_ui( &mut self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, + tile_id: egui_tiles::TileId, space_view_id: &SpaceViewId, - ) { + ) -> TreeAction { let Some(space_view) = self.space_views.get_mut(space_view_id) else { re_log::warn_once!("Bug: asked to show a ui for a Space View that doesn't exist"); - return; + return TreeAction::Remove; }; debug_assert_eq!(space_view.id, *space_view_id); let mut visibility_changed = false; - let mut removed_space_view = false; - let mut is_space_view_visible = self.visible.contains(space_view_id); + let mut action = TreeAction::Keep; + let mut visible = self.tree.is_visible(tile_id); let root_group = space_view.data_blueprint.root_group(); let default_open = Self::default_open_for_group(root_group); @@ -166,23 +242,24 @@ impl Viewport { ctx.re_ui, ui, true, - is_space_view_visible, + visible, |ui| { let response = crate::item_ui::space_view_button(ctx, ui, space_view); if response.clicked() { - if let Some(tree) = self.trees.get_mut(&self.visible) { - focus_tab(tree, space_view_id); - } + focus_tab(&mut self.tree, space_view_id); } response }, |re_ui, ui| { visibility_changed = - visibility_button_ui(re_ui, ui, true, &mut is_space_view_visible).changed(); - removed_space_view = re_ui + visibility_button_ui(re_ui, ui, true, &mut visible).changed(); + if re_ui .small_icon_button(ui, &re_ui::icons::REMOVE) .on_hover_text("Remove Space View from the viewport.") - .clicked(); + .clicked() + { + action = TreeAction::Remove; + } }, ); }) @@ -192,22 +269,20 @@ impl Viewport { ui, space_view.data_blueprint.root_handle(), space_view, - self.visible.contains(space_view_id), + visible, ); }); - if removed_space_view { - self.remove(space_view_id); - } - if visibility_changed { self.has_been_user_edited = true; - if is_space_view_visible { - self.visible.insert(*space_view_id); - } else { - self.visible.remove(space_view_id); - } + self.tree.set_visible(tile_id, visible); + } + + if action == TreeAction::Remove { + self.remove(space_view_id); } + + action } fn data_blueprint_tree_ui( @@ -347,7 +422,7 @@ impl Viewport { } pub fn add_space_view(&mut self, mut space_view: SpaceViewBlueprint) -> SpaceViewId { - let id = space_view.id; + let space_view_id = space_view.id; // Find a unique name for the space view let mut candidate_name = space_view.display_name.clone(); @@ -366,10 +441,19 @@ impl Viewport { space_view.display_name = unique_name; - self.space_views.insert(id, space_view); - self.visible.insert(id); - self.trees.clear(); // Reset them - id + self.space_views.insert(space_view_id, space_view); + + if let Some(root_id) = self.tree.root { + // Try to insert it in the tree, in the top level: + let tile_id = self.tree.tiles.insert_pane(space_view_id); + if let Some(egui_tiles::Tile::Container(container)) = self.tree.tiles.get_mut(root_id) { + container.add_child(tile_id); + } else { + self.tree = Default::default(); // we'll just re-initialize later instead + } + } + + space_view_id } pub fn on_frame_start( @@ -443,25 +527,24 @@ impl Viewport { } } - let visible_space_views = if let Some(space_view_id) = self.maximized { - std::iter::once(space_view_id).collect() - } else { - self.visible.clone() - }; + let mut maximized_tree; - // Lazily create a layout tree based on which SpaceViews should be visible: - let tree = self - .trees - .entry(visible_space_views.clone()) - .or_insert_with(|| { - super::auto_layout::tree_from_space_views( + let tree = if let Some(space_view_id) = self.maximized { + let mut tiles = egui_tiles::Tiles::default(); + let root = tiles.insert_pane(space_view_id); + maximized_tree = egui_tiles::Tree::new(root, tiles); + &mut maximized_tree + } else { + if self.tree.root().is_none() { + self.tree = super::auto_layout::tree_from_space_views( ctx, ui.available_size(), - &visible_space_views, &self.space_views, &state.space_view_states, - ) - }); + ); + } + &mut self.tree + }; ui.scope(|ui| { let mut tab_viewer = TabViewer { @@ -471,6 +554,8 @@ impl Viewport { maximized: &mut self.maximized, }; ui.spacing_mut().item_spacing.x = re_ui::ReUi::view_padding(); + + re_tracing::profile_scope!("tree.ui"); tree.ui(&mut tab_viewer, ui); }); } @@ -701,10 +786,11 @@ impl<'a, 'b> egui_tiles::Behavior for TabViewer<'a, 'b> { } fn tab_title_for_pane(&mut self, space_view_id: &SpaceViewId) -> egui::WidgetText { - let space_view = self - .space_views - .get_mut(space_view_id) - .expect("Should have been populated beforehand"); + let Some(space_view) = self.space_views.get_mut(space_view_id) else { + // this shouldn't happen unless we have a bug + re_log::debug_once!("SpaceViewId missing during egui_tiles"); + return "internal_error".into(); + }; let mut text = egui::WidgetText::RichText(egui::RichText::new(space_view.display_name.clone())); @@ -737,6 +823,10 @@ impl<'a, 'b> egui_tiles::Behavior for TabViewer<'a, 'b> { } } + fn retain_pane(&mut self, space_view_id: &SpaceViewId) -> bool { + self.space_views.contains_key(space_view_id) + } + fn top_bar_rtl_ui( &mut self, tiles: &egui_tiles::Tiles, @@ -755,7 +845,7 @@ impl<'a, 'b> egui_tiles::Behavior for TabViewer<'a, 'b> { space_view.class_name(), ); - let num_space_views = tiles.tiles.values().filter(|tile| tile.is_pane()).count(); + let num_space_views = tiles.tiles().filter(|tile| tile.is_pane()).count(); ui.add_space(8.0); // margin within the frame diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 39c6bbd39b29..d2a0b89e6524 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -10,8 +10,7 @@ use re_viewer_context::{CommandSender, Item, SpaceViewId, SystemCommand, SystemC use crate::{ blueprint_components::{ - AutoSpaceViews, SpaceViewComponent, SpaceViewMaximized, SpaceViewVisibility, - ViewportLayout, VIEWPORT_PATH, + AutoSpaceViews, SpaceViewComponent, SpaceViewMaximized, ViewportLayout, VIEWPORT_PATH, }, SpaceViewBlueprint, Viewport, }; @@ -151,11 +150,6 @@ fn load_viewport( ) }); - let space_view_visibility = blueprint_db - .store() - .query_timeless_component::(&VIEWPORT_PATH.into()) - .unwrap_or_default(); - let space_view_maximized = blueprint_db .store() .query_timeless_component::(&VIEWPORT_PATH.into()) @@ -179,8 +173,7 @@ fn load_viewport( let mut viewport = Viewport { space_views: known_space_views, - visible: space_view_visibility.0, - trees: viewport_layout.trees, + tree: viewport_layout.tree, maximized: space_view_maximized.0, has_been_user_edited: viewport_layout.has_been_user_edited, auto_space_views: auto_space_views.0, @@ -250,41 +243,20 @@ fn sync_viewport(deltas: &mut Vec, viewport: &Viewport, snapshot: &View add_delta_from_single_component(deltas, &entity_path, &timepoint, component); } - if viewport.visible != snapshot.visible { - let component = SpaceViewVisibility(viewport.visible.clone()); - add_delta_from_single_component(deltas, &entity_path, &timepoint, component); - } - if viewport.maximized != snapshot.maximized { let component = SpaceViewMaximized(viewport.maximized); add_delta_from_single_component(deltas, &entity_path, &timepoint, component); } - // Note: we can't just check `viewport.trees != snapshot.trees` because the - // tree contains serde[skip]'d state that won't match in PartialEq. - if viewport.trees.len() != snapshot.trees.len() - || !viewport.trees.iter().zip(snapshot.trees.iter()).all( - |((left_vis, left_tree), (right_vis, right_tree))| { - left_vis == right_vis - && left_tree.root == right_tree.root - && left_tree.tiles.tiles == right_tree.tiles.tiles - }, - ) + if viewport.tree != snapshot.tree || viewport.has_been_user_edited != snapshot.has_been_user_edited { let component = ViewportLayout { space_view_keys: viewport.space_views.keys().cloned().collect(), - trees: viewport.trees.clone(), + tree: viewport.tree.clone(), has_been_user_edited: viewport.has_been_user_edited, }; add_delta_from_single_component(deltas, &entity_path, &timepoint, component); - - // TODO(jleibs): Sort out this causality mess - // If we are saving a new layout, we also need to save the visibility-set because - // it gets mutated on load but isn't guaranteed to be mutated on layout-change - // which means it won't get saved. - let component = SpaceViewVisibility(viewport.visible.clone()); - add_delta_from_single_component(deltas, &entity_path, &timepoint, component); } } diff --git a/examples/rust/api_demo/Cargo.toml b/examples/rust/api_demo/Cargo.toml index b7cb3aea6f48..38ab9d203bd5 100644 --- a/examples/rust/api_demo/Cargo.toml +++ b/examples/rust/api_demo/Cargo.toml @@ -15,7 +15,7 @@ rerun = { path = "../../../crates/rerun", features = [ anyhow = "1.0" clap = { version = "4.0", features = ["derive"] } glam = "0.22" -itertools = "0.10" +itertools = "0.11" ndarray = "0.15" ndarray-rand = "0.14" rand = "0.8" diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index 742afa568339..0ff45aa71627 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -9,5 +9,5 @@ publish = false [dependencies] rerun = { path = "../../../crates/rerun", features = ["native_viewer"] } -itertools = "0.10" +itertools = "0.11" rand = "0.8"