Skip to content

Commit

Permalink
New debug option to show an actual timeline for the Blueprint (#4609)
Browse files Browse the repository at this point in the history
### What
- Resolves: #4283

Lots of goodies here:
- Add a new toggle which opens a second timeline showing a view of the
blueprint store.
- Introduce a Blueprint Timeline and log all blueprint events as
temporal on the blueprint timeline.
 - Make it possible to query data using the blueprint timeline.
- And last but not least, use the blueprint time control to drive all
our viewport queries when we're in the blueprint inspection mode.

In debug, Ctrl-Shift-I now opens this inspector, or it's available via
rerun debug menu.


![image](https://github.com/rerun-io/rerun/assets/3312232/8df37cf9-d99a-4eff-bce6-8a0037c1d335)

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/4609/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/4609/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/4609/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/4609)
- [Docs
preview](https://rerun.io/preview/79e395a32b11f73f87c6ec92825a8a03d75d0f48/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/79e395a32b11f73f87c6ec92825a8a03d75d0f48/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
jleibs authored Jan 19, 2024
1 parent 803cbaf commit 2921f3c
Show file tree
Hide file tree
Showing 54 changed files with 755 additions and 293 deletions.
3 changes: 3 additions & 0 deletions crates/re_data_ui/src/annotation_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ impl crate::EntityDataUi for re_types::components::ClassId {
verbosity: re_viewer_context::UiVerbosity,
entity_path: &re_log_types::EntityPath,
query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
let annotations = crate::annotations(ctx, query, entity_path);
let class = annotations
Expand Down Expand Up @@ -62,6 +63,7 @@ impl crate::EntityDataUi for re_types::components::KeypointId {
_verbosity: re_viewer_context::UiVerbosity,
entity_path: &re_log_types::EntityPath,
query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
if let Some(info) = annotation_info(ctx, entity_path, query, self.0) {
ui.horizontal(|ui| {
Expand Down Expand Up @@ -100,6 +102,7 @@ impl DataUi for AnnotationContext {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
match verbosity {
UiVerbosity::Small | UiVerbosity::Reduced => {
Expand Down
22 changes: 16 additions & 6 deletions crates/re_data_ui/src/blueprint_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ impl DataUi for IncludedQueries {
_ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
match verbosity {
UiVerbosity::Small => {
ui.label(format!("{} Queries", self.0.len()));
}
UiVerbosity::Full | UiVerbosity::LimitHeight | UiVerbosity::Reduced => {
for query in &self.0 {
let query: DataQueryId = (*query).into();
query.data_ui(_ctx, ui, verbosity, _query);
for data_query in &self.0 {
let data_query: DataQueryId = (*data_query).into();
data_query.data_ui(_ctx, ui, verbosity, query, store);
ui.end_row();
}
}
Expand All @@ -36,8 +37,17 @@ impl<T: BlueprintIdRegistry> DataUi for BlueprintId<T> {
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
entity_path_button_to(ctx, ui, None, &self.as_entity_path(), self.to_string());
entity_path_button_to(
ctx,
query,
store,
ui,
None,
&self.as_entity_path(),
self.to_string(),
);
}
}
5 changes: 5 additions & 0 deletions crates/re_data_ui/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl DataUi for EntityComponentWithInstances {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
re_tracing::profile_function!(self.component_name().full_name());

Expand Down Expand Up @@ -84,6 +85,7 @@ impl DataUi for EntityComponentWithInstances {
ui,
verbosity,
query,
store,
&self.entity_path,
&self.component_data,
instance_key,
Expand Down Expand Up @@ -120,6 +122,8 @@ impl DataUi for EntityComponentWithInstances {
InstancePath::instance(self.entity_path.clone(), *instance_key);
item_ui::instance_path_button_to(
ctx,
query,
store,
ui,
None,
&instance_path,
Expand All @@ -132,6 +136,7 @@ impl DataUi for EntityComponentWithInstances {
ui,
UiVerbosity::Small,
query,
store,
&self.entity_path,
&self.component_data,
instance_key,
Expand Down
11 changes: 2 additions & 9 deletions crates/re_data_ui/src/component_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,13 @@ impl DataUi for ComponentPath {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
let Self {
entity_path,
component_name,
} = self;

let store = if ctx.app_options.show_blueprint_in_timeline
&& ctx.store_context.blueprint.is_logged_entity(entity_path)
{
ctx.store_context.blueprint.store()
} else {
ctx.entity_db.store()
};

if let Some(archetype_name) = component_name.indicator_component_archetype() {
ui.label(format!(
"Indicator component for the {archetype_name} archetype"
Expand All @@ -35,7 +28,7 @@ impl DataUi for ComponentPath {
entity_path: self.entity_path.clone(),
component_data,
}
.data_ui(ctx, ui, verbosity, query);
.data_ui(ctx, ui, verbosity, query, store);
} else if let Some(entity_tree) = ctx.entity_db.tree().subtree(entity_path) {
if entity_tree.entity.components.contains_key(component_name) {
ui.label("<unset>");
Expand Down
8 changes: 5 additions & 3 deletions crates/re_data_ui/src/component_ui_registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use re_data_store::LatestAtQuery;
use re_data_store::{DataStore, LatestAtQuery};
use re_log_types::{external::arrow2, EntityPath};
use re_query::ComponentWithInstances;
use re_types::external::arrow2::array::Utf8Array;
Expand Down Expand Up @@ -37,11 +37,11 @@ pub fn add_to_registry<C: EntityDataUi + re_types::Component>(registry: &mut Com
registry.add(
C::name(),
Box::new(
|ctx, ui, verbosity, query, entity_path, component, instance| match component
|ctx, ui, verbosity, query, store, entity_path, component, instance| match component
.lookup::<C>(instance)
{
Ok(component) => {
component.entity_data_ui(ctx, ui, verbosity, entity_path, query);
component.entity_data_ui(ctx, ui, verbosity, entity_path, query, store);
}
Err(re_query::QueryError::ComponentNotFound(_)) => {
ui.weak("(not found)");
Expand All @@ -54,11 +54,13 @@ pub fn add_to_registry<C: EntityDataUi + re_types::Component>(registry: &mut Com
);
}

#[allow(clippy::too_many_arguments)]
fn fallback_component_ui(
_ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &LatestAtQuery,
_store: &DataStore,
_entity_path: &EntityPath,
component: &ComponentWithInstances,
instance_key: &re_types::components::InstanceKey,
Expand Down
12 changes: 11 additions & 1 deletion crates/re_data_ui/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl DataUi for [u8; 4] {
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
let [r, g, b, a] = self;
let color = egui::Color32::from_rgba_unmultiplied(*r, *g, *b, *a);
Expand All @@ -38,6 +39,7 @@ impl DataUi for Color {
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
let [r, g, b, a] = self.to_array();
let color = egui::Color32::from_rgba_unmultiplied(r, g, b, a);
Expand All @@ -58,6 +60,7 @@ impl DataUi for ViewCoordinates {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
match verbosity {
UiVerbosity::Small => {
Expand All @@ -77,6 +80,7 @@ impl DataUi for re_types::datatypes::Mat3x3 {
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
egui::Grid::new("mat3").num_columns(3).show(ui, |ui| {
ui.monospace(self[0].to_string());
Expand Down Expand Up @@ -104,6 +108,7 @@ impl DataUi for re_types::datatypes::Vec2D {
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
ui.label(self.to_string());
}
Expand All @@ -116,6 +121,7 @@ impl DataUi for re_types::datatypes::Vec3D {
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
ui.label(self.to_string());
}
Expand All @@ -128,6 +134,7 @@ impl DataUi for LineStrip2D {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
match verbosity {
UiVerbosity::Small | UiVerbosity::Reduced => {
Expand Down Expand Up @@ -174,6 +181,7 @@ impl DataUi for LineStrip3D {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
match verbosity {
UiVerbosity::Small | UiVerbosity::Reduced => {
Expand Down Expand Up @@ -226,10 +234,11 @@ impl DataUi for Material {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
let show_optional_albedo_factor = |ui: &mut egui::Ui| {
if let Some(albedo_factor) = self.albedo_factor {
Color(albedo_factor).data_ui(ctx, ui, verbosity, query);
Color(albedo_factor).data_ui(ctx, ui, verbosity, query, store);
} else {
ui.weak("(empty)");
}
Expand Down Expand Up @@ -257,6 +266,7 @@ impl DataUi for MeshProperties {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
let show_optional_indices = |ui: &mut egui::Ui| {
if let Some(indices) = self.indices.as_ref() {
Expand Down
1 change: 1 addition & 0 deletions crates/re_data_ui/src/entity_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ impl crate::DataUi for re_entity_db::EntityDb {
ui: &mut egui::Ui,
verbosity: re_viewer_context::UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
let re_ui = &ctx.re_ui;

Expand Down
3 changes: 2 additions & 1 deletion crates/re_data_ui/src/entity_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ impl DataUi for re_entity_db::EntityPath {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query);
InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query, store);
}
}
9 changes: 7 additions & 2 deletions crates/re_data_ui/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl EntityDataUi for re_types::components::TensorData {
verbosity: UiVerbosity,
entity_path: &re_log_types::EntityPath,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
re_tracing::profile_function!();

Expand All @@ -45,6 +46,8 @@ impl EntityDataUi for re_types::components::TensorData {
let annotations = crate::annotations(ctx, query, entity_path);
tensor_ui(
ctx,
query,
store,
ui,
verbosity,
entity_path,
Expand All @@ -64,6 +67,8 @@ impl EntityDataUi for re_types::components::TensorData {
#[allow(clippy::too_many_arguments)]
fn tensor_ui(
ctx: &ViewerContext<'_>,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
ui: &mut egui::Ui,
verbosity: UiVerbosity,
entity_path: &re_entity_db::EntityPath,
Expand All @@ -79,12 +84,12 @@ fn tensor_ui(
.entry(|c: &mut TensorStatsCache| c.entry(tensor_data_row_id, tensor));
let debug_name = entity_path.to_string();

let meaning = image_meaning_for_entity(entity_path, ctx);
let meaning = image_meaning_for_entity(entity_path, query, store);

let meter = if meaning == TensorDataMeaning::Depth {
ctx.entity_db
.store()
.query_latest_component::<DepthMeter>(entity_path, &ctx.current_query())
.query_latest_component::<DepthMeter>(entity_path, query)
.map(|meter| meter.value.0)
} else {
None
Expand Down
7 changes: 3 additions & 4 deletions crates/re_data_ui/src/image_meaning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ use re_types::{
tensor_data::TensorDataMeaning,
Archetype,
};
use re_viewer_context::ViewerContext;

pub fn image_meaning_for_entity(
entity_path: &EntityPath,
ctx: &ViewerContext<'_>,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) -> TensorDataMeaning {
let store = ctx.entity_db.store();
let timeline = &ctx.current_query().timeline;
let timeline = &query.timeline;
if store.entity_has_component(timeline, entity_path, &DepthImage::indicator().name()) {
TensorDataMeaning::Depth
} else if store.entity_has_component(
Expand Down
12 changes: 3 additions & 9 deletions crates/re_data_ui/src/instance_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,13 @@ impl DataUi for InstancePath {
ui: &mut egui::Ui,
verbosity: UiVerbosity,
query: &re_data_store::LatestAtQuery,
store: &re_data_store::DataStore,
) {
let Self {
entity_path,
instance_key,
} = self;

let store = if ctx.app_options.show_blueprint_in_timeline
&& ctx.store_context.blueprint.is_logged_entity(entity_path)
{
ctx.store_context.blueprint.store()
} else {
ctx.entity_db.store()
};

let Some(components) = store.all_components(&query.timeline, entity_path) else {
if ctx.entity_db.is_known_entity(entity_path) {
// This is fine - e.g. we're looking at `/world` and the user has only logged to `/world/car`.
Expand Down Expand Up @@ -83,13 +76,14 @@ impl DataUi for InstancePath {
entity_path: entity_path.clone(),
component_data,
}
.data_ui(ctx, ui, UiVerbosity::Small, query);
.data_ui(ctx, ui, UiVerbosity::Small, query, store);
} else {
ctx.component_ui_registry.ui(
ctx,
ui,
UiVerbosity::Small,
query,
store,
entity_path,
&component_data,
instance_key,
Expand Down
Loading

0 comments on commit 2921f3c

Please sign in to comment.