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

Get rid of sync_blueprint_changes #4524

Merged
merged 27 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bbdfa2e
Clear blueprint via command-sender
jleibs Dec 13, 2023
7632b76
First pass tearing out the old viewport sync logic
jleibs Dec 14, 2023
7f55c5c
Fix multi-space-view additions
jleibs Dec 14, 2023
0be8bea
Load blueprint separately and only hold immutable ref
jleibs Dec 14, 2023
86f5c27
Move tree / tree-actions into the Viewport
jleibs Dec 14, 2023
f67ee39
cpp/py codegen
jleibs Dec 14, 2023
0864773
Fix container editing now that we have a mutable tile-tree again
jleibs Dec 14, 2023
54bc722
No-op entities-detetermined-by-user
jleibs Dec 14, 2023
b39fa0c
Don't churn auto_layout / space_views on all interaction
jleibs Dec 14, 2023
28d1a8f
Has edits logic can go away
jleibs Dec 14, 2023
6c757fa
Move the deferred tree action to a single place
jleibs Dec 14, 2023
8293a56
Always reset at beginning of frame
jleibs Dec 14, 2023
e8867de
Also clear queries
jleibs Dec 14, 2023
8f852f0
Rename
jleibs Dec 14, 2023
6190ffe
no need for a reset TreeAction
jleibs Dec 14, 2023
2b8291e
no-op sets are no-op
jleibs Dec 14, 2023
5c9da52
Inline the set_ operations
jleibs Dec 14, 2023
0987ae2
doc-link
jleibs Dec 14, 2023
2b2b0db
When duplicating a SpaceViewBlueprint, also duplicate its Query (#4549)
jleibs Dec 15, 2023
430cf7f
Merge branch 'main' into jleibs/eliminate_sync
jleibs Dec 15, 2023
4021e95
PR cleanup
jleibs Dec 15, 2023
5764be4
Clean up and document save methods
jleibs Dec 15, 2023
774a763
typo
jleibs Dec 15, 2023
e05798a
More comment cleanup
jleibs Dec 15, 2023
2d695ef
proper doc links
jleibs Dec 15, 2023
b5a1371
Expose save API directly on query
jleibs Dec 15, 2023
db70230
lint
jleibs Dec 15, 2023
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
45 changes: 40 additions & 5 deletions crates/re_space_view/src/data_query_blueprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use re_data_store::{
EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, StoreDb,
};
use re_log_types::{DataRow, EntityPath, EntityPathExpr, RowId, TimePoint};
use re_types_core::archetypes::Clear;
use re_viewer_context::{
DataQueryId, DataQueryResult, DataResult, DataResultHandle, DataResultNode, DataResultTree,
EntitiesPerSystem, EntitiesPerSystemPerClass, SpaceViewClassIdentifier, SpaceViewId,
Expand All @@ -28,7 +29,14 @@ use crate::{
/// The results of recursive expressions are only included if they are found within the [`EntityTree`]
/// and for which there is a valid `ViewPart` system. This keeps recursive expressions from incorrectly
/// picking up irrelevant data within the tree.
#[derive(Clone, PartialEq, Eq)]
///
/// Note: [`DataQueryBlueprint`] doesn't implement Clone because it stores an internal
/// uuid used for identifying the path of its data in the blueprint store. It's ambiguous
/// whether the intent is for a clone to write to the same place.
///
/// If you want a new space view otherwise identical to an existing one, use
/// [`DataQueryBlueprint::duplicate`].
#[derive(PartialEq, Eq)]
pub struct DataQueryBlueprint {
pub id: DataQueryId,
pub space_view_class_identifier: SpaceViewClassIdentifier,
Expand All @@ -47,6 +55,10 @@ impl DataQueryBlueprint {
pub const INDIVIDUAL_OVERRIDES_PREFIX: &'static str = "individual_overrides";
pub const RECURSIVE_OVERRIDES_PREFIX: &'static str = "recursive_overrides";

/// Creates a new [`DataQueryBlueprint`].
///
/// This [`DataQueryBlueprint`] is ephemeral. It must be saved by calling
/// `save_to_blueprint_store` on the enclosing `SpaceViewBlueprint`.
pub fn new(
space_view_class_identifier: SpaceViewClassIdentifier,
queries_entities: impl Iterator<Item = EntityPathExpr>,
Expand All @@ -58,25 +70,48 @@ impl DataQueryBlueprint {
}
}

/// Attempt to load a [`DataQueryBlueprint`] from the blueprint store.
pub fn try_from_db(
path: &EntityPath,
id: DataQueryId,
blueprint_db: &StoreDb,
space_view_class_identifier: SpaceViewClassIdentifier,
) -> Option<Self> {
let expressions = blueprint_db
.store()
.query_timeless_component::<QueryExpressions>(path)
.query_timeless_component::<QueryExpressions>(&id.as_entity_path())
.map(|c| c.value)?;

let id = DataQueryId::from_entity_path(path);

Some(Self {
id,
space_view_class_identifier,
expressions,
})
}

/// Persist the entire [`DataQueryBlueprint`] to the blueprint store.
///
/// This only needs to be called if the [`DataQueryBlueprint`] was created with [`Self::new`].
///
/// Otherwise, incremental calls to `set_` functions will write just the necessary component
/// update directly to the store.
pub fn save_to_blueprint_store(&self, ctx: &ViewerContext<'_>) {
ctx.save_blueprint_component(&self.id.as_entity_path(), self.expressions.clone());
}

/// Creates a new [`DataQueryBlueprint`] with a the same contents, but a different [`DataQueryId`]
pub fn duplicate(&self) -> Self {
Self {
id: DataQueryId::random(),
space_view_class_identifier: self.space_view_class_identifier,
expressions: self.expressions.clone(),
}
}

pub fn clear(&self, ctx: &ViewerContext<'_>) {
let clear = Clear::recursive();
ctx.save_blueprint_component(&self.id.as_entity_path(), clear.is_recursive);
}

pub fn build_resolver<'a>(
&self,
container: SpaceViewId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ table ViewportBlueprint (
/// All of the space-views that belong to the viewport.
space_views: rerun.blueprint.components.IncludedSpaceViews ("attr.rerun.component_required", order: 1000);

/// The layout of the space-views
layout: rerun.blueprint.components.ViewportLayout ("attr.rerun.component_required", order: 2000);

// --- Optional ---

/// The layout of the space-views
layout: rerun.blueprint.components.ViewportLayout ("attr.rerun.component_optional", nullable, order: 2000);

/// Show one tab as maximized?
maximized: rerun.blueprint.components.SpaceViewMaximized ("attr.rerun.component_optional", nullable, order: 3000);

Expand Down
1 change: 1 addition & 0 deletions crates/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ impl App {
SystemCommand::ResetBlueprint => {
// By clearing the blueprint it will be re-populated with the defaults
// at the beginning of the next frame.
re_log::debug!("Reset blueprint");
store_hub.clear_blueprint();
}
SystemCommand::UpdateBlueprint(blueprint_id, updates) => {
Expand Down
48 changes: 31 additions & 17 deletions crates/re_viewer/src/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use re_smart_channel::ReceiveSet;
use re_space_view::DataQuery as _;
use re_viewer_context::{
AppOptions, Caches, CommandSender, ComponentUiRegistry, PlayState, RecordingConfig,
SelectionState, SpaceViewClassRegistry, StoreContext, ViewerContext,
SelectionState, SpaceViewClassRegistry, StoreContext, SystemCommandSender as _, ViewerContext,
};
use re_viewport::{
identify_entities_per_system_per_class, SpaceInfoCollection, Viewport, ViewportState,
identify_entities_per_system_per_class, SpaceInfoCollection, Viewport, ViewportBlueprint,
ViewportState,
};

use crate::ui::recordings_panel_ui;
Expand Down Expand Up @@ -104,7 +105,25 @@ impl AppState {
viewport_state,
} = self;

let mut viewport = Viewport::from_db(store_context.blueprint, viewport_state);
let viewport_blueprint = ViewportBlueprint::try_from_db(store_context.blueprint);
let mut viewport = Viewport::new(
&viewport_blueprint,
viewport_state,
space_view_class_registry,
);

// If the blueprint is invalid, reset it.
if viewport.blueprint.is_invalid() {
re_log::warn!("Incompatible blueprint detected. Resetting to default.");
command_sender.send_system(re_viewer_context::SystemCommand::ResetBlueprint);

// The blueprint isn't valid so nothing past this is going to work properly.
// we might as well return and it will get fixed on the next frame.

// TODO(jleibs): If we move viewport loading up to a context where the StoreDb is mutable
// we can run the clear and re-load.
return;
}

recording_config_entry(recording_configs, store_db.store_id().clone(), store_db)
.selection_state
Expand All @@ -125,11 +144,11 @@ impl AppState {
viewport
.blueprint
.space_views
.values_mut()
.values()
.flat_map(|space_view| {
space_view.queries.iter().map(|query| {
let resolver =
query.build_resolver(space_view.id, &space_view.auto_properties);
let props = viewport.state.space_view_props(space_view.id);
let resolver = query.build_resolver(space_view.id, props);
(
query.id,
query.execute_query(
Expand Down Expand Up @@ -163,12 +182,6 @@ impl AppState {
// have the latest information.
let spaces_info = SpaceInfoCollection::new(ctx.store_db);

// If the blueprint is invalid, reset it.
if viewport.blueprint.is_invalid() {
re_log::warn!("Incompatible blueprint detected. Resetting to default.");
viewport.blueprint.reset(&ctx, &spaces_info);
}

viewport.on_frame_start(&ctx, &spaces_info);

// TODO(jleibs): Running the queries a second time is annoying, but we need
Expand All @@ -179,11 +192,11 @@ impl AppState {
viewport
.blueprint
.space_views
.values_mut()
.values()
.flat_map(|space_view| {
space_view.queries.iter().map(|query| {
let resolver =
query.build_resolver(space_view.id, &space_view.auto_properties);
let props = viewport.state.space_view_props(space_view.id);
let resolver = query.build_resolver(space_view.id, props);
(
query.id,
query.execute_query(
Expand Down Expand Up @@ -243,7 +256,7 @@ impl AppState {
ui.add_space(4.0);
}

blueprint_panel_ui(&mut viewport.blueprint, &ctx, ui, &spaces_info);
blueprint_panel_ui(&mut viewport, &ctx, ui, &spaces_info);
},
);

Expand All @@ -266,7 +279,8 @@ impl AppState {
});
});

viewport.sync_blueprint_changes(command_sender);
// Process deferred layout operations and apply updates back to blueprint
viewport.update_and_sync_tile_tree_to_blueprint(&ctx);

{
// We move the time at the very end of the frame,
Expand Down
10 changes: 5 additions & 5 deletions crates/re_viewer/src/ui/blueprint_panel.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use re_viewer_context::{SystemCommandSender as _, ViewerContext};
use re_viewport::{SpaceInfoCollection, ViewportBlueprint};
use re_viewport::{SpaceInfoCollection, Viewport};

/// Show the Blueprint section of the left panel based on the current [`ViewportBlueprint`]
/// Show the Blueprint section of the left panel based on the current [`Viewport`]
pub fn blueprint_panel_ui(
blueprint: &mut ViewportBlueprint<'_>,
viewport: &mut Viewport<'_, '_>,
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
spaces_info: &SpaceInfoCollection,
Expand All @@ -14,15 +14,15 @@ pub fn blueprint_panel_ui(
"Blueprint",
Some("The Blueprint is where you can configure the Rerun Viewer"),
|ui| {
blueprint.add_new_spaceview_button_ui(ctx, ui, spaces_info);
viewport.add_new_spaceview_button_ui(ctx, ui, spaces_info);
reset_blueprint_button_ui(ctx, ui);
},
);
});

// This call is excluded from `panel_content` because it has a ScrollArea, which should not be
// inset. Instead, it calls panel_content itself inside the ScrollArea.
blueprint.tree_ui(ctx, ui);
viewport.tree_ui(ctx, ui);
}

fn reset_blueprint_button_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) {
Expand Down
12 changes: 6 additions & 6 deletions crates/re_viewer/src/ui/selection_history_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl SelectionHistoryUi {
&mut self,
re_ui: &re_ui::ReUi,
ui: &mut egui::Ui,
blueprint: &ViewportBlueprint<'_>,
blueprint: &ViewportBlueprint,
history: &mut SelectionHistory,
) -> Option<ItemCollection> {
let next = self.next_button_ui(re_ui, ui, blueprint, history);
Expand All @@ -27,7 +27,7 @@ impl SelectionHistoryUi {
&mut self,
re_ui: &re_ui::ReUi,
ui: &mut egui::Ui,
blueprint: &ViewportBlueprint<'_>,
blueprint: &ViewportBlueprint,
history: &mut SelectionHistory,
) -> Option<ItemCollection> {
// undo selection
Expand Down Expand Up @@ -77,7 +77,7 @@ impl SelectionHistoryUi {
&mut self,
re_ui: &re_ui::ReUi,
ui: &mut egui::Ui,
blueprint: &ViewportBlueprint<'_>,
blueprint: &ViewportBlueprint,
history: &mut SelectionHistory,
) -> Option<ItemCollection> {
// redo selection
Expand Down Expand Up @@ -126,7 +126,7 @@ impl SelectionHistoryUi {
#[allow(clippy::unused_self)]
fn history_item_ui(
&mut self,
blueprint: &ViewportBlueprint<'_>,
blueprint: &ViewportBlueprint,
ui: &mut egui::Ui,
index: usize,
history: &mut SelectionHistory,
Expand Down Expand Up @@ -157,7 +157,7 @@ fn item_kind_ui(ui: &mut egui::Ui, sel: &Item) {
ui.weak(RichText::new(format!("({})", sel.kind())));
}

fn item_collection_to_string(blueprint: &ViewportBlueprint<'_>, items: &ItemCollection) -> String {
fn item_collection_to_string(blueprint: &ViewportBlueprint, items: &ItemCollection) -> String {
assert!(!items.is_empty()); // history never contains empty selections.
if items.len() == 1 {
item_to_string(blueprint, items.iter().next().unwrap())
Expand All @@ -168,7 +168,7 @@ fn item_collection_to_string(blueprint: &ViewportBlueprint<'_>, items: &ItemColl
}
}

fn item_to_string(blueprint: &ViewportBlueprint<'_>, item: &Item) -> String {
fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String {
match item {
Item::SpaceView(sid) => {
if let Some(space_view) = blueprint.space_view(sid) {
Expand Down
Loading
Loading