diff --git a/Cargo.lock b/Cargo.lock index eab6fd468f22..be632cbe1088 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2669,9 +2669,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "infer" diff --git a/crates/re_data_ui/src/annotation_context.rs b/crates/re_data_ui/src/annotation_context.rs index 843e293cba04..9e8a3c7e3d38 100644 --- a/crates/re_data_ui/src/annotation_context.rs +++ b/crates/re_data_ui/src/annotation_context.rs @@ -17,7 +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, + _db: &re_entity_db::EntityDb, ) { let annotations = crate::annotations(ctx, query, entity_path); let class = annotations @@ -63,7 +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, + _db: &re_entity_db::EntityDb, ) { if let Some(info) = annotation_info(ctx, entity_path, query, self.0) { ui.horizontal(|ui| { @@ -102,7 +102,7 @@ impl DataUi for AnnotationContext { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small | UiVerbosity::Reduced => { diff --git a/crates/re_data_ui/src/app_id.rs b/crates/re_data_ui/src/app_id.rs index 50c55d0336f6..31ea2ca0f470 100644 --- a/crates/re_data_ui/src/app_id.rs +++ b/crates/re_data_ui/src/app_id.rs @@ -13,7 +13,7 @@ impl crate::DataUi for ApplicationId { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &EntityDb, ) { egui::Grid::new("application_id") .num_columns(2) diff --git a/crates/re_data_ui/src/blueprint_data.rs b/crates/re_data_ui/src/blueprint_data.rs index 344033d5abbf..5cae1a5ec929 100644 --- a/crates/re_data_ui/src/blueprint_data.rs +++ b/crates/re_data_ui/src/blueprint_data.rs @@ -10,12 +10,12 @@ impl DataUi for BlueprintId { ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { entity_path_button_to( ctx, query, - store, + db, ui, None, &self.as_entity_path(), diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 95976dbf4043..d7973d302eeb 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -1,7 +1,10 @@ +use std::sync::Arc; + use egui::NumExt; -use re_entity_db::{EntityPath, InstancePath}; -use re_query::ComponentWithInstances; +use re_entity_db::{ + external::re_query_cache2::CachedLatestAtComponentResults, EntityPath, InstancePath, +}; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -9,38 +12,33 @@ use re_viewer_context::{UiVerbosity, ViewerContext}; use super::{table_for_verbosity, DataUi}; use crate::item_ui; -// We do NOT implement `DataUi` for just `ComponentWithInstances` -// because we also want the context of what entity it is part of! - /// All the values of a specific [`re_log_types::ComponentPath`]. -pub struct EntityComponentWithInstances { +pub struct EntityLatestAtResults { pub entity_path: EntityPath, - pub component_data: ComponentWithInstances, -} - -impl EntityComponentWithInstances { - pub fn component_name(&self) -> ComponentName { - self.component_data.name() - } - - pub fn num_instances(&self) -> usize { - self.component_data.len() - } + pub component_name: ComponentName, + pub results: Arc, } -impl DataUi for EntityComponentWithInstances { +impl DataUi for EntityLatestAtResults { fn data_ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - re_tracing::profile_function!(self.component_name().full_name()); + re_tracing::profile_function!(self.component_name); - let instance_keys = self.component_data.instance_keys(); - let num_instances = self.num_instances(); + // TODO(#5607): what should happen if the promise is still pending? + let Some(num_instances) = self + .results + .raw(db.resolver(), self.component_name) + .map(|data| data.len()) + else { + ui.weak(""); + return; + }; let one_line = match verbosity { UiVerbosity::Small => true, @@ -71,7 +69,7 @@ impl DataUi for EntityComponentWithInstances { // ├───┼───┼───┼───┤ │ // │ │ x │…+2│…+3│ │ // └───┴───┴───┴───┘ ┘ - let displayed_row = if num_instances <= max_row { + let num_displayed_rows = if num_instances <= max_row { num_instances } else { // this accounts for the "…x more" using a row and handles `num_instances == 0` @@ -81,20 +79,16 @@ impl DataUi for EntityComponentWithInstances { if num_instances == 0 { ui.weak("(empty)"); } else if num_instances == 1 { - if let Some(instance_key) = instance_keys.first() { - ctx.component_ui_registry.ui( - ctx, - ui, - verbosity, - query, - store, - &self.entity_path, - &self.component_data, - instance_key, - ); - } else { - ui.label(ctx.re_ui.error_text("Error: missing instance key")); - } + ctx.component_ui_registry.ui( + ctx, + ui, + verbosity, + query, + db, + &self.entity_path, + &self.results, + &re_types::components::InstanceKey(0), + ); } else if one_line { ui.label(format!("{} values", re_format::format_uint(num_instances))); } else { @@ -106,49 +100,49 @@ impl DataUi for EntityComponentWithInstances { .header(re_ui::ReUi::table_header_height(), |mut header| { re_ui::ReUi::setup_table_header(&mut header); header.col(|ui| { - ui.label("Index"); + ui.label("Instance"); }); header.col(|ui| { - ui.label(self.component_name().short_name()); + ui.label(self.component_name.short_name()); }); }) .body(|mut body| { re_ui::ReUi::setup_table_body(&mut body); let row_height = re_ui::ReUi::table_line_height(); - body.rows(row_height, displayed_row, |mut row| { - if let Some(instance_key) = instance_keys.get(row.index()) { - row.col(|ui| { - let instance_path = - InstancePath::instance(self.entity_path.clone(), *instance_key); - item_ui::instance_path_button_to( - ctx, - query, - store, - ui, - None, - &instance_path, - instance_key.syntax_highlighted(ui.style()), - ); - }); - row.col(|ui| { - ctx.component_ui_registry.ui( - ctx, - ui, - UiVerbosity::Small, - query, - store, - &self.entity_path, - &self.component_data, - instance_key, - ); - }); - } + body.rows(row_height, num_displayed_rows, |mut row| { + let instance_key = re_types::components::InstanceKey(row.index() as _); + row.col(|ui| { + let instance_path = + InstancePath::instance(self.entity_path.clone(), instance_key); + item_ui::instance_path_button_to( + ctx, + query, + db, + ui, + None, + &instance_path, + instance_key.syntax_highlighted(ui.style()), + ); + }); + row.col(|ui| { + ctx.component_ui_registry.ui( + ctx, + ui, + UiVerbosity::Small, + query, + db, + &self.entity_path, + &self.results, + &instance_key, + ); + }); }); }); - if num_instances > displayed_row { + + if num_instances > num_displayed_rows { ui.label(format!( "…and {} more.", - re_format::format_uint(num_instances - displayed_row) + re_format::format_uint(num_instances - num_displayed_rows) )); } } diff --git a/crates/re_data_ui/src/component_path.rs b/crates/re_data_ui/src/component_path.rs index 49496d789fe0..35af64c88430 100644 --- a/crates/re_data_ui/src/component_path.rs +++ b/crates/re_data_ui/src/component_path.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use re_log_types::ComponentPath; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -10,7 +12,7 @@ impl DataUi for ComponentPath { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let Self { entity_path, @@ -21,27 +23,31 @@ impl DataUi for ComponentPath { ui.label(format!( "Indicator component for the {archetype_name} archetype" )); - } else if let Some((_, _, component_data)) = - re_query::get_component_with_instances(store, query, entity_path, *component_name) - { - super::component::EntityComponentWithInstances { - entity_path: self.entity_path.clone(), - component_data, - } - .data_ui(ctx, ui, verbosity, query, store); - } else if let Some(entity_tree) = ctx.recording().tree().subtree(entity_path) { - if entity_tree.entity.components.contains_key(component_name) { - ui.label(""); + } else { + let results = + db.query_caches2() + .latest_at(db.store(), query, entity_path, [*component_name]); + if let Some(results) = results.components.get(component_name) { + crate::EntityLatestAtResults { + entity_path: entity_path.clone(), + component_name: *component_name, + results: Arc::clone(results), + } + .data_ui(ctx, ui, verbosity, query, db); + } else if let Some(entity_tree) = ctx.recording().tree().subtree(entity_path) { + if entity_tree.entity.components.contains_key(component_name) { + ui.label(""); + } else { + ui.label(format!( + "Entity {entity_path:?} has no component {component_name:?}" + )); + } } else { - ui.label(format!( - "Entity {entity_path:?} has no component {component_name:?}" - )); + ui.label( + ctx.re_ui + .error_text(format!("Unknown component path: {self}")), + ); } - } else { - ui.label( - ctx.re_ui - .error_text(format!("Unknown component path: {self}")), - ); } } } diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 28ed1571b684..e576b76c0b66 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,6 +1,6 @@ -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::LatestAtQuery; +use re_entity_db::{external::re_query_cache2::CachedLatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; -use re_query::ComponentWithInstances; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; @@ -39,18 +39,13 @@ pub fn add_to_registry(registry: &mut Com registry.add( C::name(), Box::new( - |ctx, ui, verbosity, query, store, entity_path, component, instance| match component - .lookup::(instance) - { - Ok(component) => { - component.entity_data_ui(ctx, ui, verbosity, entity_path, query, store); - } - Err(re_query::QueryError::ComponentNotFound(_)) => { + |ctx, ui, verbosity, query, db, entity_path, component, instance| { + // TODO(#5607): what should happen if the promise is still pending? + if let Some(component) = component.instance::(db.resolver(), instance.0 as _) { + component.entity_data_ui(ctx, ui, verbosity, entity_path, query, db); + } else { ui.weak("(not found)"); } - Err(err) => { - re_log::warn_once!("Expected component {}, {}", C::name(), err); - } }, ), ); @@ -62,13 +57,20 @@ fn fallback_component_ui( ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &LatestAtQuery, - _store: &DataStore, + db: &EntityDb, _entity_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { + // TODO(#5607): what should happen if the promise is still pending? + let value = component + .component_name(db.resolver()) + .and_then(|component_name| { + component.instance_raw(db.resolver(), component_name, instance_key.0 as _) + }); + // No special ui implementation - use a generic one: - if let Some(value) = component.lookup_arrow(instance_key) { + if let Some(value) = value { arrow_ui(ui, verbosity, &*value); } else { ui.weak("(null)"); diff --git a/crates/re_data_ui/src/data.rs b/crates/re_data_ui/src/data.rs index 234a141c2b4f..ec481568d639 100644 --- a/crates/re_data_ui/src/data.rs +++ b/crates/re_data_ui/src/data.rs @@ -16,7 +16,7 @@ impl DataUi for [u8; 4] { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let [r, g, b, a] = self; let color = egui::Color32::from_rgba_unmultiplied(*r, *g, *b, *a); @@ -37,7 +37,7 @@ impl DataUi for Color { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let [r, g, b, a] = self.to_array(); let color = egui::Color32::from_rgba_unmultiplied(r, g, b, a); @@ -58,7 +58,7 @@ impl DataUi for ViewCoordinates { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small => { @@ -79,7 +79,7 @@ impl DataUi for re_types::datatypes::Mat3x3 { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { egui::Grid::new("mat3").num_columns(3).show(ui, |ui| { ui.monospace(self[0].to_string()); @@ -107,7 +107,7 @@ impl DataUi for re_types::datatypes::Vec2D { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.label(self.to_string()); } @@ -120,7 +120,7 @@ impl DataUi for re_types::datatypes::Vec3D { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.label(self.to_string()); } @@ -133,7 +133,7 @@ impl DataUi for LineStrip2D { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small | UiVerbosity::Reduced => { @@ -180,7 +180,7 @@ impl DataUi for LineStrip3D { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small | UiVerbosity::Reduced => { @@ -233,7 +233,7 @@ impl DataUi for MeshProperties { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let show_optional_indices = |ui: &mut egui::Ui| { if let Some(indices) = self.indices.as_ref() { diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs index b1e90ccf1977..bdf3ed05db01 100644 --- a/crates/re_data_ui/src/data_source.rs +++ b/crates/re_data_ui/src/data_source.rs @@ -10,7 +10,7 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.label(self.to_string()); diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index f00b01b17bcc..425cbc28eeca 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -1,9 +1,9 @@ // TODO(jleibs): Turn this into a trait use egui::NumExt as _; -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::LatestAtQuery; +use re_entity_db::{external::re_query_cache2::CachedLatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; -use re_query::ComponentWithInstances; use re_types::{ components::{ Color, MarkerShape, MarkerSize, Name, Radius, ScalarScattering, StrokeWidth, Text, @@ -20,16 +20,16 @@ fn edit_color_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_color = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_color(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_color(ctx, query, db, entity_path)); let current_color = current_color.into(); let mut edit_color = current_color; @@ -49,7 +49,7 @@ fn edit_color_ui( fn default_color( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> Color { Color::from_rgb(255, 255, 255) @@ -63,16 +63,16 @@ fn edit_text_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_text(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_text(ctx, query, db, entity_path)); let current_text = current_text.to_string(); let mut edit_text = current_text.clone(); @@ -90,7 +90,7 @@ fn edit_text_ui( fn default_text( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, entity_path: &EntityPath, ) -> Text { Text::from(entity_path.to_string()) @@ -103,16 +103,16 @@ fn edit_name_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_name(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_name(ctx, query, db, entity_path)); let current_text = current_text.to_string(); let mut edit_text = current_text.clone(); @@ -130,7 +130,7 @@ fn edit_name_ui( fn default_name( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, entity_path: &EntityPath, ) -> Name { Name::from(entity_path.to_string()) @@ -144,16 +144,16 @@ fn edit_scatter_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_scatter = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_scatter(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_scatter(ctx, query, db, entity_path)); let current_scatter = current_scatter.0; let mut edit_scatter = current_scatter; @@ -179,7 +179,7 @@ fn edit_scatter_ui( fn default_scatter( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> ScalarScattering { ScalarScattering::from(false) @@ -193,16 +193,16 @@ fn edit_radius_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_radius = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_radius(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_radius(ctx, query, db, entity_path)); let current_radius = current_radius.0; let mut edit_radius = current_radius; @@ -226,7 +226,7 @@ fn edit_radius_ui( fn default_radius( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> Radius { Radius::from(1.0) @@ -240,16 +240,16 @@ fn edit_marker_shape_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_marker_shape(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_marker_shape(ctx, query, db, entity_path)); let mut edit_marker = current_marker; @@ -290,7 +290,7 @@ fn edit_marker_shape_ui( fn default_marker_shape( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> MarkerShape { MarkerShape::default() @@ -326,16 +326,16 @@ fn edit_stroke_width_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_stroke_width = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_stroke_width(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_stroke_width(ctx, query, db, entity_path)); let current_stroke_width = current_stroke_width.0; let mut edit_stroke_width = current_stroke_width; @@ -359,7 +359,7 @@ fn edit_stroke_width_ui( fn default_stroke_width( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> StrokeWidth { StrokeWidth::from(1.0) @@ -373,16 +373,16 @@ fn edit_marker_size_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker_size = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_marker_size(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_marker_size(ctx, query, db, entity_path)); let current_marker_size = current_marker_size.0; let mut edit_marker_size = current_marker_size; @@ -406,7 +406,7 @@ fn edit_marker_size_ui( fn default_marker_size( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> MarkerSize { MarkerSize::from(1.0) @@ -416,16 +416,16 @@ fn default_marker_size( fn register_editor<'a, C: Component + Loggable + 'static>( registry: &mut re_viewer_context::ComponentUiRegistry, - default: fn(&ViewerContext<'_>, &LatestAtQuery, &DataStore, &EntityPath) -> C, + default: fn(&ViewerContext<'_>, &LatestAtQuery, &EntityDb, &EntityPath) -> C, edit: fn( &ViewerContext<'_>, &mut egui::Ui, UiVerbosity, &LatestAtQuery, - &DataStore, + &EntityDb, &EntityPath, &EntityPath, - &ComponentWithInstances, + &CachedLatestAtComponentResults, &re_types::components::InstanceKey, ), ) where @@ -433,8 +433,8 @@ fn register_editor<'a, C: Component + Loggable + 'static>( { registry.add_editor( C::name(), - Box::new(move |ctx, query, store, entity_path| { - let c = default(ctx, query, store, entity_path); + Box::new(move |ctx, query, db, entity_path| { + let c = default(ctx, query, db, entity_path); [c].into() }), Box::new(edit), diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 4faa5b61b30d..57a0007fa6f4 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -12,7 +12,7 @@ impl crate::DataUi for EntityDb { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let re_ui = &ctx.re_ui; diff --git a/crates/re_data_ui/src/entity_path.rs b/crates/re_data_ui/src/entity_path.rs index c4dd7d1df55c..6348b21ddbac 100644 --- a/crates/re_data_ui/src/entity_path.rs +++ b/crates/re_data_ui/src/entity_path.rs @@ -10,8 +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, + db: &re_entity_db::EntityDb, ) { - InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query, store); + InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query, db); } } diff --git a/crates/re_data_ui/src/image.rs b/crates/re_data_ui/src/image.rs index 0548957b5993..491320baeb82 100644 --- a/crates/re_data_ui/src/image.rs +++ b/crates/re_data_ui/src/image.rs @@ -34,7 +34,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, + db: &re_entity_db::EntityDb, ) { re_tracing::profile_function!(); @@ -53,7 +53,7 @@ impl EntityDataUi for re_types::components::TensorData { tensor_ui( ctx, query, - store, + db, ui, verbosity, entity_path, @@ -74,7 +74,7 @@ impl EntityDataUi for re_types::components::TensorData { pub fn tensor_ui( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, verbosity: UiVerbosity, entity_path: &re_entity_db::EntityPath, @@ -90,7 +90,7 @@ pub 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, query, store); + let meaning = image_meaning_for_entity(entity_path, query, db.store()); let meter = if meaning == TensorDataMeaning::Depth { // TODO(#5607): what should happen if the promise is still pending? diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index 192c4206d470..11152fedd6f0 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -1,6 +1,7 @@ +use std::sync::Arc; + use re_entity_db::InstancePath; use re_log_types::ComponentPath; -use re_query::get_component_with_instances; use re_viewer_context::{UiVerbosity, ViewerContext}; use super::DataUi; @@ -13,14 +14,17 @@ impl DataUi for InstancePath { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let Self { entity_path, instance_key, } = self; - let Some(components) = store.all_components(&query.timeline(), entity_path) else { + let Some(components) = ctx + .recording_store() + .all_components(&query.timeline(), entity_path) + else { if ctx.recording().is_known_entity(entity_path) { // This is fine - e.g. we're looking at `/world` and the user has only logged to `/world/car`. ui.label(format!( @@ -71,9 +75,13 @@ impl DataUi for InstancePath { .num_columns(2) .show(ui, |ui| { for component_name in normal_components { - let Some((_, _, component_data)) = - get_component_with_instances(store, query, entity_path, component_name) - else { + let results = db.query_caches2().latest_at( + db.store(), + query, + entity_path, + [component_name], + ); + let Some(results) = results.components.get(&component_name) else { continue; // no need to show components that are unset at this point in time }; @@ -84,20 +92,21 @@ impl DataUi for InstancePath { ); if instance_key.is_splat() { - super::component::EntityComponentWithInstances { + crate::EntityLatestAtResults { entity_path: entity_path.clone(), - component_data, + component_name, + results: Arc::clone(results), } - .data_ui(ctx, ui, UiVerbosity::Small, query, store); + .data_ui(ctx, ui, UiVerbosity::Small, query, db); } else { ctx.component_ui_registry.ui( ctx, ui, UiVerbosity::Small, query, - store, + db, entity_path, - &component_data, + results, instance_key, ); } diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 3d4c60dc58c2..001c3320297d 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -36,7 +36,7 @@ use super::DataUi; pub fn entity_path_button( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, entity_path: &EntityPath, @@ -44,7 +44,7 @@ pub fn entity_path_button( instance_path_button_to( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(entity_path.clone()), @@ -56,7 +56,7 @@ pub fn entity_path_button( pub fn entity_path_parts_buttons( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, entity_path: &EntityPath, @@ -68,7 +68,7 @@ pub fn entity_path_parts_buttons( // Show one single icon up-front instead: let instance_path = InstancePath::entity_splat(entity_path.clone()); - ui.add(instance_path_icon(&query.timeline(), store, &instance_path).as_image()); + ui.add(instance_path_icon(&query.timeline(), db, &instance_path).as_image()); let mut accumulated = Vec::new(); for part in entity_path.iter() { @@ -78,7 +78,7 @@ pub fn entity_path_parts_buttons( instance_path_button_to_ex( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(accumulated.clone().into()), @@ -94,7 +94,7 @@ pub fn entity_path_parts_buttons( pub fn entity_path_button_to( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, entity_path: &EntityPath, @@ -103,7 +103,7 @@ pub fn entity_path_button_to( instance_path_button_to( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(entity_path.clone()), @@ -115,7 +115,7 @@ pub fn entity_path_button_to( pub fn instance_path_button( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, @@ -123,7 +123,7 @@ pub fn instance_path_button( instance_path_button_to( ctx, query, - store, + db, ui, space_view_id, instance_path, @@ -137,12 +137,13 @@ pub fn instance_path_button( /// _on the current timeline_. pub fn instance_path_icon( timeline: &re_data_store::Timeline, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, instance_path: &InstancePath, ) -> &'static icons::Icon { if instance_path.is_splat() { // It is an entity path - if store + if db + .store() .all_components(timeline, &instance_path.entity_path) .is_some() { @@ -186,29 +187,20 @@ pub fn guess_instance_path_icon( instance_path: &InstancePath, ) -> &'static re_ui::icons::Icon { let (query, db) = guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); - instance_path_icon(&query.timeline(), db.store(), instance_path) + instance_path_icon(&query.timeline(), db, instance_path) } /// Show an instance id and make it selectable. pub fn instance_path_button_to( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, text: impl Into, ) -> egui::Response { - instance_path_button_to_ex( - ctx, - query, - store, - ui, - space_view_id, - instance_path, - text, - true, - ) + instance_path_button_to_ex(ctx, query, db, ui, space_view_id, instance_path, text, true) } /// Show an instance id and make it selectable. @@ -216,7 +208,7 @@ pub fn instance_path_button_to( fn instance_path_button_to_ex( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, @@ -232,7 +224,7 @@ fn instance_path_button_to_ex( let response = if with_icon { ctx.re_ui.selectable_label_with_icon( ui, - instance_path_icon(&query.timeline(), store, instance_path), + instance_path_icon(&query.timeline(), db, instance_path), text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, @@ -242,7 +234,7 @@ fn instance_path_button_to_ex( }; let response = response.on_hover_ui(|ui| { - instance_hover_card_ui(ui, ctx, query, store, instance_path); + instance_hover_card_ui(ui, ctx, query, db, instance_path); }); cursor_interact_with_selectable(ctx, response, item) @@ -252,7 +244,7 @@ fn instance_path_button_to_ex( pub fn instance_path_parts_buttons( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, @@ -263,7 +255,7 @@ pub fn instance_path_parts_buttons( ui.spacing_mut().item_spacing.x = 2.0; // Show one single icon up-front instead: - ui.add(instance_path_icon(&query.timeline(), store, instance_path).as_image()); + ui.add(instance_path_icon(&query.timeline(), db, instance_path).as_image()); let mut accumulated = Vec::new(); for part in instance_path.entity_path.iter() { @@ -273,7 +265,7 @@ pub fn instance_path_parts_buttons( instance_path_button_to_ex( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(accumulated.clone().into()), @@ -287,7 +279,7 @@ pub fn instance_path_parts_buttons( instance_path_button_to_ex( ctx, query, - store, + db, ui, space_view_id, instance_path, @@ -413,7 +405,7 @@ pub fn component_path_button_to( pub fn data_blueprint_button_to( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, text: impl Into, space_view_id: SpaceViewId, @@ -426,7 +418,7 @@ pub fn data_blueprint_button_to( let response = ui .selectable_label(ctx.selection().contains_item(&item), text) .on_hover_ui(|ui| { - entity_hover_card_ui(ui, ctx, query, store, entity_path); + entity_hover_card_ui(ui, ctx, query, db, entity_path); }); cursor_interact_with_selectable(ctx, response, item) } @@ -510,7 +502,7 @@ pub fn instance_hover_card_ui( ui: &mut egui::Ui, ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, instance_path: &InstancePath, ) { if !ctx.recording().is_known_entity(&instance_path.entity_path) { @@ -537,7 +529,7 @@ pub fn instance_hover_card_ui( // TODO(emilk): per-component stats } - instance_path.data_ui(ctx, ui, UiVerbosity::Reduced, query, store); + instance_path.data_ui(ctx, ui, UiVerbosity::Reduced, query, db); } /// Displays the "hover card" (i.e. big tooltip) for an entity. @@ -545,11 +537,11 @@ pub fn entity_hover_card_ui( ui: &mut egui::Ui, ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, entity_path: &EntityPath, ) { let instance_path = InstancePath::entity_splat(entity_path.clone()); - instance_hover_card_ui(ui, ctx, query, store, &instance_path); + instance_hover_card_ui(ui, ctx, query, db, &instance_path); } pub fn app_id_button_ui( @@ -572,8 +564,8 @@ pub fn app_id_button_ui( ctx, ui, re_viewer_context::UiVerbosity::Reduced, - &ctx.current_query(), // unused - ctx.recording_store(), // unused + &ctx.current_query(), // unused + ctx.recording(), // unused ); }); @@ -601,7 +593,7 @@ pub fn data_source_button_ui( ui, re_viewer_context::UiVerbosity::Reduced, &ctx.current_query(), - ctx.recording_store(), // unused + ctx.recording(), // unused ); }); @@ -704,7 +696,7 @@ pub fn entity_db_button_ui( ui, re_viewer_context::UiVerbosity::Reduced, &ctx.current_query(), - entity_db.store(), + entity_db, ); }); diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 24f54eb4fa20..ab92ba5fd344 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -35,7 +35,7 @@ pub use crate::image::{ show_zoomed_image_region, show_zoomed_image_region_area_outline, tensor_summary_ui_grid_contents, }; -pub use component::EntityComponentWithInstances; +pub use component::EntityLatestAtResults; pub use component_ui_registry::{add_to_registry, create_component_ui_registry}; pub use image_meaning::image_meaning_for_entity; @@ -71,7 +71,7 @@ pub trait DataUi { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ); } @@ -87,7 +87,7 @@ pub trait EntityDataUi { verbosity: UiVerbosity, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ); } @@ -102,12 +102,12 @@ where verbosity: UiVerbosity, entity: &EntityPath, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { // This ensures that UI state is maintained per entity. For example, the collapsed state for // `AnnotationContext` component is not saved by all instances of the component. ui.push_id(entity.hash(), |ui| { - self.data_ui(ctx, ui, verbosity, query, store); + self.data_ui(ctx, ui, verbosity, query, db); }); } } @@ -121,7 +121,7 @@ impl DataUi for TimePoint { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.vertical(|ui| { egui::Grid::new("time_point").num_columns(2).show(ui, |ui| { @@ -143,7 +143,7 @@ impl DataUi for [DataCell] { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let mut sorted = self.to_vec(); sorted.sort_by_key(|cb| cb.component_name()); diff --git a/crates/re_data_ui/src/log_msg.rs b/crates/re_data_ui/src/log_msg.rs index a6636b5983e3..86559d0d0e67 100644 --- a/crates/re_data_ui/src/log_msg.rs +++ b/crates/re_data_ui/src/log_msg.rs @@ -13,11 +13,11 @@ impl DataUi for LogMsg { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match self { - LogMsg::SetStoreInfo(msg) => msg.data_ui(ctx, ui, verbosity, query, store), - LogMsg::ArrowMsg(_, msg) => msg.data_ui(ctx, ui, verbosity, query, store), + LogMsg::SetStoreInfo(msg) => msg.data_ui(ctx, ui, verbosity, query, db), + LogMsg::ArrowMsg(_, msg) => msg.data_ui(ctx, ui, verbosity, query, db), LogMsg::BlueprintActivationCommand(BlueprintActivationCommand { blueprint_id, make_active, @@ -38,7 +38,7 @@ impl DataUi for SetStoreInfo { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let SetStoreInfo { row_id: _, info } = self; let StoreInfo { @@ -96,7 +96,7 @@ impl DataUi for ArrowMsg { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let table = match DataTable::from_arrow_msg(self) { Ok(table) => table, @@ -115,15 +115,15 @@ impl DataUi for ArrowMsg { Ok(row) => { egui::Grid::new("fields").num_columns(2).show(ui, |ui| { ui.monospace("entity_path:"); - item_ui::entity_path_button(ctx, query, store, ui, None, row.entity_path()); + item_ui::entity_path_button(ctx, query, db, ui, None, row.entity_path()); ui.end_row(); ui.monospace("time_point:"); - row.timepoint().data_ui(ctx, ui, verbosity, query, store); + row.timepoint().data_ui(ctx, ui, verbosity, query, db); ui.end_row(); ui.monospace("components:"); - row.cells().data_ui(ctx, ui, verbosity, query, store); + row.cells().data_ui(ctx, ui, verbosity, query, db); ui.end_row(); }); } diff --git a/crates/re_data_ui/src/material.rs b/crates/re_data_ui/src/material.rs index d17aba5c17a9..1e39d0197b57 100644 --- a/crates/re_data_ui/src/material.rs +++ b/crates/re_data_ui/src/material.rs @@ -10,11 +10,11 @@ impl DataUi for Material { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { 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, store); + Color(albedo_factor).data_ui(ctx, ui, verbosity, query, db); } else { ui.weak("(empty)"); } diff --git a/crates/re_data_ui/src/pinhole.rs b/crates/re_data_ui/src/pinhole.rs index 7b8b48b06838..0237e5b25e04 100644 --- a/crates/re_data_ui/src/pinhole.rs +++ b/crates/re_data_ui/src/pinhole.rs @@ -10,7 +10,7 @@ impl DataUi for PinholeProjection { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { if verbosity == UiVerbosity::Small { // See if this is a trivial pinhole, and can be displayed as such: @@ -24,12 +24,12 @@ impl DataUi for PinholeProjection { }; ui.label(format!("Focal length: {fl}\nPrincipal point: {pp}")) - .on_hover_ui(|ui| self.data_ui(ctx, ui, UiVerbosity::Reduced, query, store)); + .on_hover_ui(|ui| self.data_ui(ctx, ui, UiVerbosity::Reduced, query, db)); return; } } - self.0.data_ui(ctx, ui, verbosity, query, store); + self.0.data_ui(ctx, ui, verbosity, query, db); } } @@ -40,7 +40,7 @@ impl DataUi for Resolution { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let [x, y] = self.0 .0; ui.monospace(format!("{x}x{y}")); diff --git a/crates/re_data_ui/src/rotation3d.rs b/crates/re_data_ui/src/rotation3d.rs index 5a30b308d885..5b17d32cacaf 100644 --- a/crates/re_data_ui/src/rotation3d.rs +++ b/crates/re_data_ui/src/rotation3d.rs @@ -13,9 +13,9 @@ impl DataUi for components::Rotation3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - self.0.data_ui(ctx, ui, verbosity, query, store); + self.0.data_ui(ctx, ui, verbosity, query, db); } } @@ -26,7 +26,7 @@ impl DataUi for datatypes::Rotation3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match self { datatypes::Rotation3D::Quaternion(q) => { @@ -36,7 +36,7 @@ impl DataUi for datatypes::Rotation3D { datatypes::Rotation3D::AxisAngle(RotationAxisAngle { axis, angle }) => { egui::Grid::new("axis_angle").num_columns(2).show(ui, |ui| { ui.label("axis"); - axis.data_ui(ctx, ui, verbosity, query, store); + axis.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); ui.label("angle"); diff --git a/crates/re_data_ui/src/store_id.rs b/crates/re_data_ui/src/store_id.rs index 3aef5003ed2a..ca173439d8e2 100644 --- a/crates/re_data_ui/src/store_id.rs +++ b/crates/re_data_ui/src/store_id.rs @@ -5,10 +5,10 @@ impl crate::DataUi for re_log_types::StoreId { ui: &mut egui::Ui, verbosity: re_viewer_context::UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { if let Some(entity_db) = ctx.store_context.bundle.get(self) { - entity_db.data_ui(ctx, ui, verbosity, query, store); + entity_db.data_ui(ctx, ui, verbosity, query, db); } else { ui.label(format!("{} ID {} (not found)", self.kind, self.id)); } diff --git a/crates/re_data_ui/src/transform3d.rs b/crates/re_data_ui/src/transform3d.rs index bb81f4b75266..7b334afc9be1 100644 --- a/crates/re_data_ui/src/transform3d.rs +++ b/crates/re_data_ui/src/transform3d.rs @@ -11,13 +11,13 @@ impl DataUi for re_types::components::Transform3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small => { // TODO(andreas): Preview some information instead of just a label with hover ui. ui.label("3D transform").on_hover_ui(|ui| { - self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, store); + self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, db); }); } @@ -36,7 +36,7 @@ impl DataUi for re_types::components::Transform3D { ui.label("3D transform"); ui.indent("transform_repr", |ui| { ui.label(dir_string); - self.0.data_ui(ctx, ui, verbosity, query, store); + self.0.data_ui(ctx, ui, verbosity, query, db); }); }); } @@ -52,9 +52,9 @@ impl DataUi for re_types::components::OutOfTreeTransform3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - re_types::components::Transform3D(self.0).data_ui(ctx, ui, verbosity, query, store); + re_types::components::Transform3D(self.0).data_ui(ctx, ui, verbosity, query, db); } } @@ -66,21 +66,21 @@ impl DataUi for Transform3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small => { ui.label("3D transform").on_hover_ui(|ui| { - self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, store); + self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, db); }); } UiVerbosity::Full | UiVerbosity::LimitHeight | UiVerbosity::Reduced => match self { Transform3D::TranslationAndMat3x3(translation_matrix) => { - translation_matrix.data_ui(ctx, ui, verbosity, query, store); + translation_matrix.data_ui(ctx, ui, verbosity, query, db); } Transform3D::TranslationRotationScale(translation_rotation_scale) => { - translation_rotation_scale.data_ui(ctx, ui, verbosity, query, store); + translation_rotation_scale.data_ui(ctx, ui, verbosity, query, db); } }, } @@ -94,7 +94,7 @@ impl DataUi for TranslationRotationScale3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let TranslationRotationScale3D { translation, @@ -110,19 +110,19 @@ impl DataUi for TranslationRotationScale3D { // We still skip zero translations though since they are typically not logged explicitly. if let Some(translation) = translation { ui.label("translation"); - translation.data_ui(ctx, ui, verbosity, query, store); + translation.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } if let Some(rotation) = rotation { ui.label("rotation"); - rotation.data_ui(ctx, ui, verbosity, query, store); + rotation.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } if let Some(scale) = scale { ui.label("scale"); - scale.data_ui(ctx, ui, verbosity, query, store); + scale.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } }); @@ -136,14 +136,14 @@ impl DataUi for Scale3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match self { Scale3D::Uniform(scale) => { ui.label(re_format::format_f32(*scale)); } Scale3D::ThreeD(v) => { - v.data_ui(ctx, ui, verbosity, query, store); + v.data_ui(ctx, ui, verbosity, query, db); } } } @@ -156,7 +156,7 @@ impl DataUi for TranslationAndMat3x3 { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let TranslationAndMat3x3 { translation, @@ -169,13 +169,13 @@ impl DataUi for TranslationAndMat3x3 { .show(ui, |ui| { if let Some(translation) = translation { ui.label("translation"); - translation.data_ui(ctx, ui, verbosity, query, store); + translation.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } if let Some(matrix) = mat3x3 { ui.label("matrix"); - matrix.data_ui(ctx, ui, verbosity, query, store); + matrix.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } }); diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query2/benches/latest_at.rs index fbc5e5959225..15e41c055b8c 100644 --- a/crates/re_query2/benches/latest_at.rs +++ b/crates/re_query2/benches/latest_at.rs @@ -282,8 +282,8 @@ fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Color::name()); let points = points .iter_dense::(&resolver) @@ -324,8 +324,8 @@ fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Text::name()); let points = points .iter_dense::(&resolver) diff --git a/crates/re_query2/examples/latest_at.rs b/crates/re_query2/examples/latest_at.rs index 90e44f48d0f9..9fd0c7764e35 100644 --- a/crates/re_query2/examples/latest_at.rs +++ b/crates/re_query2/examples/latest_at.rs @@ -40,9 +40,9 @@ fn main() -> anyhow::Result<()> { // * `get_required` returns an error if the component batch is missing // * `get_or_empty` returns an empty set of results if the component if missing // * `get` returns an option - let points: &LatestAtComponentResults = results.get_required::()?; - let colors: &LatestAtComponentResults = results.get_or_empty::(); - let labels: &LatestAtComponentResults = results.get_or_empty::(); + let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query2/src/latest_at/results.rs index 0a2800c153a0..aef7167423dc 100644 --- a/crates/re_query2/src/latest_at/results.rs +++ b/crates/re_query2/src/latest_at/results.rs @@ -43,34 +43,45 @@ impl LatestAtResults { self.components.contains_key(&component_name.into()) } - /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. #[inline] - pub fn get(&self) -> Option<&LatestAtComponentResults> { - self.components.get(&C::name()) + pub fn get( + &self, + component_name: impl Into, + ) -> Option<&LatestAtComponentResults> { + self.components.get(&component_name.into()) } - /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. /// /// Returns an error if the component is not present. #[inline] - pub fn get_required(&self) -> crate::Result<&LatestAtComponentResults> { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_required( + &self, + component_name: impl Into, + ) -> crate::Result<&LatestAtComponentResults> { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { Ok(component) } else { Err(DeserializationError::MissingComponent { - component: C::name(), + component: component_name, backtrace: ::backtrace::Backtrace::new_unresolved(), } .into()) } } - /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty(&self) -> &LatestAtComponentResults { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_or_empty( + &self, + component_name: impl Into, + ) -> &LatestAtComponentResults { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { component } else { static DEFAULT: LatestAtComponentResults = LatestAtComponentResults::EMPTY; diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs index 531b1a24dfa1..ac92c6aed7c2 100644 --- a/crates/re_query2/src/lib.rs +++ b/crates/re_query2/src/lib.rs @@ -60,3 +60,17 @@ pub enum QueryError { } pub type Result = std::result::Result; + +// --- + +/// Helper extension trait to convert query results into [`re_types_core::Archetype`]s. +pub trait ToArchetype { + /// Converts the result into an [`re_types_core::Archetype`]. + /// + /// Automatically handles all aspects of the query process: deserialization, caching, promise + /// resolution, etc. + fn to_archetype( + &self, + resolver: &crate::PromiseResolver, + ) -> crate::PromiseResult>; +} diff --git a/crates/re_query2/src/promise.rs b/crates/re_query2/src/promise.rs index 65c44891b3af..a8f473c725a5 100644 --- a/crates/re_query2/src/promise.rs +++ b/crates/re_query2/src/promise.rs @@ -118,6 +118,15 @@ impl PromiseResult { } } + /// Returns the inner value if it's ready. + #[inline] + pub fn ok(self) -> Option { + match self { + PromiseResult::Ready(v) => Some(v), + _ => None, + } + } + /// Unwraps the resolved result if it's `Ready`, panics otherwise. #[inline] pub fn unwrap(self) -> T { diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query2/tests/latest_at.rs index ad49831db10c..2ab2a5714302 100644 --- a/crates/re_query2/tests/latest_at.rs +++ b/crates/re_query2/tests/latest_at.rs @@ -60,10 +60,10 @@ fn simple_query() -> anyhow::Result<()> { Some(MyColor::from_rgb(255, 0, 0)), ]; - let points = results.get_required::()?; + let points = results.get_required(MyPoint::name())?; let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - let colors = results.get_or_empty::(); + let colors = results.get_or_empty(MyColor::name()); let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); @@ -130,10 +130,10 @@ fn static_query() -> anyhow::Result<()> { Some(MyColor::from_rgb(255, 0, 0)), ]; - let points = results.get_required::()?; + let points = results.get_required(MyPoint::name())?; let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - let colors = results.get_or_empty::(); + let colors = results.get_or_empty(MyColor::name()); let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); @@ -199,10 +199,10 @@ fn no_instance_join_query() -> anyhow::Result<()> { Some(MyColor::from_rgb(0, 255, 0)), ]; - let points = results.get_required::()?; + let points = results.get_required(MyPoint::name())?; let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - let colors = results.get_or_empty::(); + let colors = results.get_or_empty(MyColor::name()); let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml index c953b1124bf6..b87432ff1fb8 100644 --- a/crates/re_query_cache2/Cargo.toml +++ b/crates/re_query_cache2/Cargo.toml @@ -18,7 +18,10 @@ all-features = true [features] -default = [] +default = ["to_archetype"] + +## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. +to_archetype = ["dep:re_types"] [dependencies] # Rerun dependencies: @@ -31,6 +34,9 @@ re_query2.workspace = true re_tracing.workspace = true re_types_core.workspace = true +# Rerun dependencies (optional): +re_types = { workspace = true, optional = true } + # External dependencies: ahash.workspace = true anyhow.workspace = true @@ -57,6 +63,11 @@ similar-asserts.workspace = true bench = false +[[example]] +name = "latest_at_archetype" +required-features = ["to_archetype"] + + [[bench]] name = "flat_vec_deque" harness = false diff --git a/crates/re_query_cache2/benches/latest_at.rs b/crates/re_query_cache2/benches/latest_at.rs index f7c608209224..27e1824a0168 100644 --- a/crates/re_query_cache2/benches/latest_at.rs +++ b/crates/re_query_cache2/benches/latest_at.rs @@ -296,8 +296,8 @@ fn query_and_visit_points( Points2D::all_components().iter().cloned(), // no generics! ); - let points = results.get_required::().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Color::name()); let points = points .iter_dense::(&resolver) @@ -347,8 +347,8 @@ fn query_and_visit_strings( Points2D::all_components().iter().cloned(), // no generics! ); - let points = results.get_required::().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Text::name()); let points = points .iter_dense::(&resolver) diff --git a/crates/re_query_cache2/examples/latest_at.rs b/crates/re_query_cache2/examples/latest_at.rs index 160154bf0589..bb170472ff2a 100644 --- a/crates/re_query_cache2/examples/latest_at.rs +++ b/crates/re_query_cache2/examples/latest_at.rs @@ -41,9 +41,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let points: &CachedLatestAtComponentResults = results.get_required::()?; - let colors: &CachedLatestAtComponentResults = results.get_or_empty::(); - let labels: &CachedLatestAtComponentResults = results.get_or_empty::(); + let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query_cache2/examples/latest_at_archetype.rs b/crates/re_query_cache2/examples/latest_at_archetype.rs new file mode 100644 index 000000000000..f0ae3059e944 --- /dev/null +++ b/crates/re_query_cache2/examples/latest_at_archetype.rs @@ -0,0 +1,105 @@ +use itertools::Itertools; +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; +use re_types::{ + archetypes::Points2D, + components::{Color, Position2D, Text}, +}; +use re_types_core::{Archetype as _, Loggable as _}; + +use re_query_cache2::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; + +// --- + +fn main() -> anyhow::Result<()> { + let store = store()?; + eprintln!("store:\n{}", store.to_data_table()?); + + let resolver = PromiseResolver::default(); + + let entity_path = "points"; + let timeline = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::latest(timeline); + eprintln!("query:{query:?}"); + + let caches = re_query_cache2::Caches::new(&store); + + // First, get the results for this query. + // + // They might or might not already be cached. We won't know for sure until we try to access + // each individual component's data below. + let results: CachedLatestAtResults = caches.latest_at( + &store, + &query, + &entity_path.into(), + Points2D::all_components().iter().cloned(), // no generics! + ); + + // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and + // cache an entire archetype all at once. + use re_query_cache2::ToArchetype as _; + + let arch: Points2D = match results.to_archetype(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(arch) => arch, + PromiseResult::Error(err) => return Err(err.into()), + }; + + // With the data now fully resolved/converted and deserialized, some joining logic can be + // applied if desired. + // + // In most cases this will be either a clamped zip, or no joining at all. + + let color_default_fn = || None; + let label_default_fn = || None; + + let results = clamped_zip_1x2( + arch.positions.iter(), + arch.colors + .iter() + .flat_map(|colors| colors.iter().map(Some)), + color_default_fn, + arch.labels + .iter() + .flat_map(|labels| labels.iter().map(Some)), + label_default_fn, + ) + .collect_vec(); + + eprintln!("results:\n{results:?}"); + + Ok(()) +} + +// --- + +fn store() -> anyhow::Result { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + re_types::components::InstanceKey::name(), + Default::default(), + ); + + let entity_path = "points"; + + { + let timepoint = [build_frame_nr(123)]; + + let points = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![Color::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let labels = vec![Text("a".into()), Text("b".into())]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + store.insert_row(&row)?; + } + + Ok(store) +} diff --git a/crates/re_query_cache2/src/latest_at/helpers.rs b/crates/re_query_cache2/src/latest_at/helpers.rs index 559bc013336f..9273e12e0fc9 100644 --- a/crates/re_query_cache2/src/latest_at/helpers.rs +++ b/crates/re_query_cache2/src/latest_at/helpers.rs @@ -1,8 +1,227 @@ use re_data_store::{DataStore, LatestAtQuery}; use re_log_types::{EntityPath, RowId, TimeInt}; use re_types_core::Component; +use re_types_core::{external::arrow2::array::Array, ComponentName}; -use crate::{Caches, PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtComponentResults, Caches, PromiseResolver, PromiseResult}; + +// --- + +impl CachedLatestAtComponentResults { + /// Returns the component data as a dense vector. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn dense(&self, resolver: &PromiseResolver) -> Option<&[C]> { + let component_name = C::name(); + let level = re_log::Level::Warn; + match self.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); + None + } + PromiseResult::Ready(data) => Some(data), + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data as an arrow array. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn raw( + &self, + resolver: &PromiseResolver, + component_name: impl Into, + ) -> Option> { + let component_name = component_name.into(); + let level = re_log::Level::Warn; + match self.resolved(resolver) { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't get {component_name}: promise still pending"); + None + } + PromiseResult::Ready(cell) => Some(cell.to_arrow()), + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the single instance. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn mono(&self, resolver: &PromiseResolver) -> Option { + let component_name = C::name(); + let level = re_log::Level::Warn; + match self.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); + None + } + PromiseResult::Ready(data) if data.len() == 1 => Some(data[0].clone()), + PromiseResult::Ready(data) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: not a mono-batch (length: {})", + data.len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the single instance as an arrow array. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn mono_raw( + &self, + resolver: &PromiseResolver, + component_name: impl Into, + ) -> Option> { + let component_name = component_name.into(); + let level = re_log::Level::Warn; + match self.resolved(resolver) { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't get {component_name}: promise still pending"); + None + } + PromiseResult::Ready(cell) if cell.as_arrow_ref().len() == 1 => { + Some(cell.as_arrow_ref().sliced(0, 1)) + } + PromiseResult::Ready(cell) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: not a mono-batch (length: {})", + cell.as_arrow_ref().len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the specified instance. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized, or + /// the index doesn't exist. + #[inline] + pub fn instance(&self, resolver: &PromiseResolver, index: usize) -> Option { + let component_name = C::name(); + let level = re_log::Level::Warn; + match self.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); + None + } + PromiseResult::Ready(data) => { + // TODO(#5303): Figure out we'd like to integrate clamping semantics into selection panel. + // + // For now, we simply always clamp, which is the closest to the legacy behavior that the UI + // expects. + let index = usize::min(index, data.len().saturating_sub(1)); + + if data.len() > index { + Some(data[index].clone()) + } else { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: index not found (index: {index}, length: {})", + data.len(), + ); + None + } + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the specified instance as an arrow array. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized, or + /// the index doesn't exist. + #[inline] + pub fn instance_raw( + &self, + resolver: &PromiseResolver, + component_name: impl Into, + index: usize, + ) -> Option> { + let component_name = component_name.into(); + let level = re_log::Level::Warn; + match self.resolved(resolver) { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't get {component_name}: promise still pending"); + None + } + PromiseResult::Ready(cell) if cell.as_arrow_ref().len() > index => { + Some(cell.as_arrow_ref().sliced(index, 1)) + } + PromiseResult::Ready(cell) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: index not found (index: {index}, length: {})", + cell.as_arrow_ref().len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } +} // --- @@ -33,8 +252,6 @@ impl std::ops::Deref for CachedLatestAtMonoResult { } } -// --- - impl Caches { /// Get the latest index and value for a given dense [`re_types_core::Component`]. /// @@ -59,7 +276,7 @@ impl Caches { re_tracing::profile_function!(); let results = self.latest_at(store, query, entity_path, [C::name()]); - let result = results.get::()?; + let result = results.get(C::name())?; let index @ (data_time, row_id) = *result.index(); diff --git a/crates/re_query_cache2/src/latest_at/mod.rs b/crates/re_query_cache2/src/latest_at/mod.rs index 4ed943205a5a..82fd889bce0b 100644 --- a/crates/re_query_cache2/src/latest_at/mod.rs +++ b/crates/re_query_cache2/src/latest_at/mod.rs @@ -2,6 +2,9 @@ mod helpers; mod query; mod results; +#[cfg(feature = "to_archetype")] +mod to_archetype; + pub use self::helpers::CachedLatestAtMonoResult; pub use self::query::LatestAtCache; pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 3355be18c032..99319de5d4b9 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -51,20 +51,29 @@ impl CachedLatestAtResults { /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. #[inline] - pub fn get(&self) -> Option<&CachedLatestAtComponentResults> { - self.components.get(&C::name()).map(|arc| &**arc) + pub fn get( + &self, + component_name: impl Into, + ) -> Option<&CachedLatestAtComponentResults> { + self.components + .get(&component_name.into()) + .map(|arc| &**arc) } /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] - pub fn get_required(&self) -> crate::Result<&CachedLatestAtComponentResults> { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_required( + &self, + component_name: impl Into, + ) -> crate::Result<&CachedLatestAtComponentResults> { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { Ok(component) } else { Err(DeserializationError::MissingComponent { - component: C::name(), + component: component_name, backtrace: ::backtrace::Backtrace::new_unresolved(), } .into()) @@ -75,8 +84,12 @@ impl CachedLatestAtResults { /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty(&self) -> &CachedLatestAtComponentResults { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_or_empty( + &self, + component_name: impl Into, + ) -> &CachedLatestAtComponentResults { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { component } else { static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); @@ -139,6 +152,15 @@ impl CachedLatestAtComponentResults { cached_heap_size_bytes: AtomicU64::new(0), } } + + /// Returns the [`ComponentName`] of the resolved data, if available. + #[inline] + pub fn component_name(&self, resolver: &PromiseResolver) -> Option { + match self.resolved(resolver) { + PromiseResult::Ready(cell) => Some(cell.component_name()), + _ => None, + } + } } impl SizeBytes for CachedLatestAtComponentResults { @@ -173,6 +195,16 @@ impl CachedLatestAtComponentResults { &self.index } + /// Returns the raw resolved data, if it's ready. + #[inline] + pub fn resolved(&self, resolver: &PromiseResolver) -> PromiseResult { + if let Some(cell) = self.promise.as_ref() { + resolver.resolve(cell) + } else { + PromiseResult::Pending + } + } + /// Returns the component data as a dense vector. /// /// Returns an error if the component is missing or cannot be deserialized. diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes new file mode 100644 index 000000000000..b074eccb685e --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes @@ -0,0 +1,30 @@ +# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs + +.gitattributes linguist-generated=true +annotation_context.rs linguist-generated=true +arrows2d.rs linguist-generated=true +arrows3d.rs linguist-generated=true +asset3d.rs linguist-generated=true +bar_chart.rs linguist-generated=true +boxes2d.rs linguist-generated=true +boxes3d.rs linguist-generated=true +clear.rs linguist-generated=true +depth_image.rs linguist-generated=true +disconnected_space.rs linguist-generated=true +image.rs linguist-generated=true +line_strips2d.rs linguist-generated=true +line_strips3d.rs linguist-generated=true +mesh3d.rs linguist-generated=true +mod.rs linguist-generated=true +pinhole.rs linguist-generated=true +points2d.rs linguist-generated=true +points3d.rs linguist-generated=true +scalar.rs linguist-generated=true +segmentation_image.rs linguist-generated=true +series_line.rs linguist-generated=true +series_point.rs linguist-generated=true +tensor.rs linguist-generated=true +text_document.rs linguist-generated=true +text_log.rs linguist-generated=true +transform3d.rs linguist-generated=true +view_coordinates.rs linguist-generated=true diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs new file mode 100644 index 000000000000..9b11a29180f6 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::AnnotationContext; + let context = match self.get_required(::name()) { + Ok(context) => context, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let context = match context.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::AnnotationContext { context }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs new file mode 100644 index 000000000000..7f058b601e53 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Vector2D; + let vectors = match self.get_required(::name()) { + Ok(vectors) => vectors, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let vectors = match vectors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position2D; + let origins = if let Some(origins) = self.get(::name()) { + match origins.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Arrows2D { + vectors, + origins, + radii, + colors, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs new file mode 100644 index 000000000000..1b8361441273 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Vector3D; + let vectors = match self.get_required(::name()) { + Ok(vectors) => vectors, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let vectors = match vectors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position3D; + let origins = if let Some(origins) = self.get(::name()) { + match origins.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Arrows3D { + vectors, + origins, + radii, + colors, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs new file mode 100644 index 000000000000..ea1848353286 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Blob; + let blob = match self.get_required(::name()) { + Ok(blob) => blob, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let blob = match blob.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::MediaType; + let media_type = if let Some(media_type) = self.get(::name()) { + match media_type.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::OutOfTreeTransform3D; + let transform = if let Some(transform) = self.get(::name()) { + match transform.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Asset3D { + blob, + media_type, + transform, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs new file mode 100644 index 000000000000..208250b38c98 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let values = match self.get_required(::name()) { + Ok(values) => values, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let values = match values.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::BarChart { values, color }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs new file mode 100644 index 000000000000..a91d137e3f08 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs @@ -0,0 +1,136 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::HalfSizes2D; + let half_sizes = match self.get_required(::name()) { + Ok(half_sizes) => half_sizes, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let half_sizes = match half_sizes.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position2D; + let centers = if let Some(centers) = self.get(::name()) { + match centers.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Boxes2D { + half_sizes, + centers, + colors, + radii, + labels, + draw_order, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs new file mode 100644 index 000000000000..eeda7ca0d848 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs @@ -0,0 +1,136 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::HalfSizes3D; + let half_sizes = match self.get_required(::name()) { + Ok(half_sizes) => half_sizes, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let half_sizes = match half_sizes.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position3D; + let centers = if let Some(centers) = self.get(::name()) { + match centers.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Rotation3D; + let rotations = if let Some(rotations) = self.get(::name()) { + match rotations.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Boxes3D { + half_sizes, + centers, + rotations, + colors, + radii, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs b/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs new file mode 100644 index 000000000000..66f2a4fc0632 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types_core::components::ClearIsRecursive; + let is_recursive = match self.get_required(::name()) { + Ok(is_recursive) => is_recursive, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let is_recursive = match is_recursive.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types_core::archetypes::Clear { is_recursive }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs b/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs new file mode 100644 index 000000000000..72241e116757 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::DepthMeter; + let meter = if let Some(meter) = self.get(::name()) { + match meter.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::DepthImage { + data, + meter, + draw_order, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs new file mode 100644 index 000000000000..fb260af9ea10 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::DisconnectedSpace; + let disconnected_space = match self.get_required(::name()) { + Ok(disconnected_space) => disconnected_space, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let disconnected_space = match disconnected_space.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::DisconnectedSpace { disconnected_space }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/image.rs b/crates/re_query_cache2/src/latest_at/to_archetype/image.rs new file mode 100644 index 000000000000..075dbb43ddf4 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/image.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Image { data, draw_order }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs new file mode 100644 index 000000000000..76aac8acec22 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::LineStrip2D; + let strips = match self.get_required(::name()) { + Ok(strips) => strips, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let strips = match strips.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::LineStrips2D { + strips, + radii, + colors, + labels, + draw_order, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs new file mode 100644 index 000000000000..dab31b78577a --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs @@ -0,0 +1,106 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::LineStrip3D; + let strips = match self.get_required(::name()) { + Ok(strips) => strips, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let strips = match strips.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::LineStrips3D { + strips, + radii, + colors, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs new file mode 100644 index 000000000000..6b6ef86c0aef --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs @@ -0,0 +1,151 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Position3D; + let vertex_positions = match self.get_required(::name()) { + Ok(vertex_positions) => vertex_positions, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let vertex_positions = match vertex_positions.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::MeshProperties; + let mesh_properties = if let Some(mesh_properties) = self.get(::name()) { + match mesh_properties.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Vector3D; + let vertex_normals = if let Some(vertex_normals) = self.get(::name()) { + match vertex_normals.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let vertex_colors = if let Some(vertex_colors) = self.get(::name()) { + match vertex_colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Texcoord2D; + let vertex_texcoords = if let Some(vertex_texcoords) = self.get(::name()) { + match vertex_texcoords.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Material; + let mesh_material = if let Some(mesh_material) = self.get(::name()) { + match mesh_material.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::TensorData; + let albedo_texture = if let Some(albedo_texture) = self.get(::name()) { + match albedo_texture.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Mesh3D { + vertex_positions, + mesh_properties, + vertex_normals, + vertex_colors, + vertex_texcoords, + mesh_material, + albedo_texture, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs new file mode 100644 index 000000000000..a66a21691f82 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs @@ -0,0 +1,28 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +mod annotation_context; +mod arrows2d; +mod arrows3d; +mod asset3d; +mod bar_chart; +mod boxes2d; +mod boxes3d; +mod clear; +mod depth_image; +mod disconnected_space; +mod image; +mod line_strips2d; +mod line_strips3d; +mod mesh3d; +mod pinhole; +mod points2d; +mod points3d; +mod scalar; +mod segmentation_image; +mod series_line; +mod series_point; +mod tensor; +mod text_document; +mod text_log; +mod transform3d; +mod view_coordinates; diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs b/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs new file mode 100644 index 000000000000..8d7cd53ce764 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::PinholeProjection; + let image_from_camera = match self.get_required(::name()) { + Ok(image_from_camera) => image_from_camera, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let image_from_camera = match image_from_camera.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Resolution; + let resolution = if let Some(resolution) = self.get(::name()) { + match resolution.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ViewCoordinates; + let camera_xyz = if let Some(camera_xyz) = self.get(::name()) { + match camera_xyz.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Pinhole { + image_from_camera, + resolution, + camera_xyz, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs new file mode 100644 index 000000000000..8bd79e0895fb --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs @@ -0,0 +1,136 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Position2D; + let positions = match self.get_required(::name()) { + Ok(positions) => positions, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let positions = match positions.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::KeypointId; + let keypoint_ids = if let Some(keypoint_ids) = self.get(::name()) { + match keypoint_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Points2D { + positions, + radii, + colors, + labels, + draw_order, + class_ids, + keypoint_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs new file mode 100644 index 000000000000..b2bc78bc0760 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Position3D; + let positions = match self.get_required(::name()) { + Ok(positions) => positions, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let positions = match positions.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::KeypointId; + let keypoint_ids = if let Some(keypoint_ids) = self.get(::name()) { + match keypoint_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Points3D { + positions, + radii, + colors, + labels, + class_ids, + keypoint_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs b/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs new file mode 100644 index 000000000000..89594fd0bd5e --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Scalar; + let scalar = match self.get_required(::name()) { + Ok(scalar) => scalar, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let scalar = match scalar.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::Scalar { scalar }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs new file mode 100644 index 000000000000..5e09d7522f89 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::SegmentationImage { data, draw_order }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs b/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs new file mode 100644 index 000000000000..83f309cd79ed --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs @@ -0,0 +1,72 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::StrokeWidth; + let width = if let Some(width) = self.get(::name()) { + match width.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Name; + let name = if let Some(name) = self.get(::name()) { + match name.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::SeriesLine { color, width, name }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs b/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs new file mode 100644 index 000000000000..8e7f5faa6a2c --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs @@ -0,0 +1,91 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::MarkerShape; + let marker = if let Some(marker) = self.get(::name()) { + match marker.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Name; + let name = if let Some(name) = self.get(::name()) { + match name.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::MarkerSize; + let marker_size = if let Some(marker_size) = self.get(::name()) { + match marker_size.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::SeriesPoint { + color, + marker, + name, + marker_size, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs b/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs new file mode 100644 index 000000000000..8144906d8d73 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::Tensor { data }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs b/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs new file mode 100644 index 000000000000..c644acbd170b --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Text; + let text = match self.get_required(::name()) { + Ok(text) => text, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let text = match text.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::MediaType; + let media_type = if let Some(media_type) = self.get(::name()) { + match media_type.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::TextDocument { text, media_type }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs b/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs new file mode 100644 index 000000000000..759cd69501aa --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs @@ -0,0 +1,79 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Text; + let text = match self.get_required(::name()) { + Ok(text) => text, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let text = match text.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::TextLogLevel; + let level = if let Some(level) = self.get(::name()) { + match level.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::TextLog { text, level, color }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs new file mode 100644 index 000000000000..16a9cd0cc53a --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Transform3D; + let transform = match self.get_required(::name()) { + Ok(transform) => transform, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let transform = match transform.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::Transform3D { transform }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs new file mode 100644 index 000000000000..9d4a252d55da --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::ViewCoordinates; + let xyz = match self.get_required(::name()) { + Ok(xyz) => xyz, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let xyz = match xyz.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::ViewCoordinates { xyz }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs index 49e5ce210e3b..58e3f4b46669 100644 --- a/crates/re_query_cache2/src/lib.rs +++ b/crates/re_query_cache2/src/lib.rs @@ -14,6 +14,7 @@ pub(crate) use self::latest_at::LatestAtCache; pub use re_query2::{ clamped_zip::*, Promise, PromiseId, PromiseResolver, PromiseResult, QueryError, Result, + ToArchetype, }; pub mod external { diff --git a/crates/re_query_cache2/tests/latest_at.rs b/crates/re_query_cache2/tests/latest_at.rs index b87b1bb02da6..4af2ba0b8f12 100644 --- a/crates/re_query_cache2/tests/latest_at.rs +++ b/crates/re_query_cache2/tests/latest_at.rs @@ -486,13 +486,13 @@ fn query_and_compare( MyPoints::all_components().iter().copied(), ); - let cached_points = cached.get_required::().unwrap(); + let cached_points = cached.get_required(MyPoint::name()).unwrap(); let cached_point_data = cached_points .to_dense::(&resolver) .flatten() .unwrap(); - let cached_colors = cached.get_or_empty::(); + let cached_colors = cached.get_or_empty(MyColor::name()); let cached_color_data = cached_colors .to_sparse::(&resolver) .flatten() @@ -505,13 +505,13 @@ fn query_and_compare( MyPoints::all_components().iter().copied(), ); - let expected_points = expected.get_required::().unwrap(); + let expected_points = expected.get_required(MyPoint::name()).unwrap(); let expected_point_data = expected_points .to_dense::(&resolver) .flatten() .unwrap(); - let expected_colors = expected.get_or_empty::(); + let expected_colors = expected.get_or_empty(MyColor::name()); let expected_color_data = expected_colors .to_sparse::(&resolver) .flatten() diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 05f379c5c714..b6189eb53312 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -86,7 +86,6 @@ impl SpaceViewClass for DataframeSpaceView { .cloned() .collect(); - let store = ctx.recording_store(); let latest_at_query = query.latest_at_query(); let sorted_instance_paths: Vec<_>; @@ -108,7 +107,12 @@ impl SpaceViewClass for DataframeSpaceView { sorted_instance_paths = sorted_entity_paths .iter() .flat_map(|entity_path| { - sorted_instance_paths_for(entity_path, store, &query.timeline, &latest_at_query) + sorted_instance_paths_for( + entity_path, + ctx.recording_store(), + &query.timeline, + &latest_at_query, + ) }) .collect(); @@ -117,7 +121,7 @@ impl SpaceViewClass for DataframeSpaceView { sorted_components = sorted_entity_paths .iter() .flat_map(|entity_path| { - store + ctx.recording_store() .all_components(&query.timeline, entity_path) .unwrap_or_default() }) @@ -148,32 +152,34 @@ impl SpaceViewClass for DataframeSpaceView { // of bounds" (aka cannot be joined to a primary component). row.col(|ui| { - instance_path_button(ctx, &latest_at_query, store, ui, None, instance); + instance_path_button(ctx, &latest_at_query, ctx.recording(), ui, None, instance); }); - for comp in &sorted_components { + for component_name in &sorted_components { row.col(|ui| { // TODO(#4466): make it explicit if that value results // from a splat joint. - if let Some((_, _, comp_inst)) = + let results = ctx.recording().query_caches2().latest_at( + ctx.recording_store(), + &latest_at_query, + &instance.entity_path, + [*component_name], + ); + + if let Some(results) = // This is a duplicate of the one above, but this ok since this codes runs // *only* for visible rows. - get_component_with_instances( - store, - &latest_at_query, - &instance.entity_path, - *comp, - ) + results.components.get(component_name) { ctx.component_ui_registry.ui( ctx, ui, UiVerbosity::Small, &latest_at_query, - store, + ctx.recording(), &instance.entity_path, - &comp_inst, + results, &instance.instance_key, ); } else { diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index c7e32c1a09a3..53e822295b99 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -587,12 +587,18 @@ pub fn picking( item_ui::instance_path_button( ctx, &query.latest_at_query(), - store, + ctx.recording(), ui, Some(query.space_view_id), &instance_path, ); - instance_path.data_ui(ctx, ui, UiVerbosity::Reduced, &ctx.current_query(), store); + instance_path.data_ui( + ctx, + ui, + UiVerbosity::Reduced, + &ctx.current_query(), + ctx.recording(), + ); }) }; } @@ -673,7 +679,7 @@ fn image_hover_ui( ui, UiVerbosity::Small, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ); } else { // Show it all, like we do for any other thing we hover @@ -682,7 +688,7 @@ fn image_hover_ui( ui, UiVerbosity::Small, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ); } diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index d7b2ee356ecc..ca5d0ae97848 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -359,7 +359,6 @@ fn table_ui( body_clip_rect = Some(body.max_rect()); let query = ctx.current_query(); - let store = ctx.recording_store(); let row_heights = entries.iter().map(|te| calc_row_height(te)); body.heterogeneous_rows(row_heights, |mut row| { @@ -410,7 +409,7 @@ fn table_ui( item_ui::entity_path_button( ctx, &query, - store, + ctx.recording(), ui, None, &entry.entity_path, diff --git a/crates/re_time_panel/src/data_density_graph.rs b/crates/re_time_panel/src/data_density_graph.rs index 50c4e5896c48..3a73e4c1c224 100644 --- a/crates/re_time_panel/src/data_density_graph.rs +++ b/crates/re_time_panel/src/data_density_graph.rs @@ -371,7 +371,7 @@ pub fn data_density_graph_ui( data_dentity_graph_painter: &mut DataDensityGraphPainter, ctx: &ViewerContext<'_>, time_ctrl: &mut TimeControl, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, time_area_response: &egui::Response, time_area_painter: &egui::Painter, ui: &egui::Ui, @@ -497,7 +497,7 @@ pub fn data_density_graph_ui( show_row_ids_tooltip( ctx, time_ctrl, - store, + db, ui.ctx(), item, hovered_time_range, @@ -529,7 +529,7 @@ fn make_brighter(color: Color32) -> Color32 { fn show_row_ids_tooltip( ctx: &ViewerContext<'_>, time_ctrl: &TimeControl, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, egui_ctx: &egui::Context, item: &TimePanelItem, time_range: TimeRange, @@ -561,12 +561,12 @@ fn show_row_ids_tooltip( let component_path = ComponentPath::new(entity_path.clone(), *component_name); item_ui::component_path_button(ctx, ui, &component_path); ui.add_space(8.0); - component_path.data_ui(ctx, ui, verbosity, &query, store); + component_path.data_ui(ctx, ui, verbosity, &query, db); } else { let instance_path = re_entity_db::InstancePath::entity_splat(entity_path.clone()); - item_ui::instance_path_button(ctx, &query, store, ui, None, &instance_path); + item_ui::instance_path_button(ctx, &query, db, ui, None, &instance_path); ui.add_space(8.0); - instance_path.data_ui(ctx, ui, verbosity, &query, store); + instance_path.data_ui(ctx, ui, verbosity, &query, db); } }); } diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index 4e5c2e685d3a..6aea8b62c413 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -553,9 +553,9 @@ impl TimePanel { ) { let tree_has_data_in_current_timeline = time_ctrl.tree_has_data_in_current_timeline(tree); - let store = match self.source { - TimePanelSource::Recording => ctx.recording_store(), - TimePanelSource::Blueprint => ctx.store_context.blueprint.store(), + let db = match self.source { + TimePanelSource::Recording => ctx.recording(), + TimePanelSource::Blueprint => ctx.store_context.blueprint, }; // The last part of the path component @@ -632,7 +632,7 @@ impl TimePanel { ui, ctx, &time_ctrl.current_query(), - store, + db, &tree.path, ); }); @@ -689,7 +689,7 @@ impl TimePanel { &mut self.data_density_graph_painter, ctx, time_ctrl, - store, + db, time_area_response, time_area_painter, ui, @@ -807,16 +807,16 @@ impl TimePanel { highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); - let store = match self.source { - TimePanelSource::Recording => ctx.recording_store(), - TimePanelSource::Blueprint => ctx.store_context.blueprint.store(), + let db = match self.source { + TimePanelSource::Recording => ctx.recording(), + TimePanelSource::Blueprint => ctx.store_context.blueprint, }; data_density_graph::data_density_graph_ui( &mut self.data_density_graph_painter, ctx, time_ctrl, - store, + db, time_area_response, time_area_painter, ui, diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index a89613137681..03bef116e80b 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -31,7 +31,7 @@ use crate::{ use super::{ arrow::quote_fqname_as_type_path, blueprint_validation::generate_blueprint_validation, - util::string_from_quoted, + to_archetype::generate_to_archetype_impls, util::string_from_quoted, }; // --- @@ -72,6 +72,7 @@ impl CodeGenerator for RustCodeGenerator { } generate_blueprint_validation(reporter, objects, &mut files_to_write); + generate_to_archetype_impls(reporter, objects, &mut files_to_write); files_to_write } diff --git a/crates/re_types_builder/src/codegen/rust/mod.rs b/crates/re_types_builder/src/codegen/rust/mod.rs index 6179dffcc5dc..33a12cf821d7 100644 --- a/crates/re_types_builder/src/codegen/rust/mod.rs +++ b/crates/re_types_builder/src/codegen/rust/mod.rs @@ -5,6 +5,7 @@ mod arrow; mod blueprint_validation; mod deserializer; mod serializer; +mod to_archetype; mod util; pub use self::api::RustCodeGenerator; diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs new file mode 100644 index 000000000000..9c755a0e7b70 --- /dev/null +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -0,0 +1,274 @@ +//! Generates code in `re_query_cache2` so that cached results can easily be converted to +//! ready-to-use archetypes. +//! +//! That code needs to be generated directly in the caching crates as it needs access to the cached +//! queries and results as well as the promise resolving machinery. +//! Generating such code in the usual places would result in one giant cycle dependency chain. + +use std::collections::BTreeMap; + +use camino::Utf8PathBuf; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +use crate::{objects::FieldKind, Object, ObjectKind, Objects, Reporter}; + +// --- + +const NEWLINE_TOKEN: &str = "NEWLINE_TOKEN"; +const COMMENT_SEPARATOR_TOKEN: &str = "COMMENT_SEPARATOR_TOKEN"; +const COMMENT_REQUIRED_TOKEN: &str = "COMMENT_REQUIRED_TOKEN"; +const COMMENT_RECOMMENDED_OPTIONAL_TOKEN: &str = "COMMENT_RECOMMENDED_OPTIONAL_TOKEN"; + +pub fn generate_to_archetype_impls( + reporter: &Reporter, + objects: &Objects, + files_to_write: &mut BTreeMap, +) { + generate_mod(reporter, objects, files_to_write); + generate_impls(reporter, objects, files_to_write); +} + +fn generate_mod( + _reporter: &Reporter, + objects: &Objects, + files_to_write: &mut BTreeMap, +) { + let generated_path = + Utf8PathBuf::from("crates/re_query_cache2/src/latest_at/to_archetype/mod.rs"); + + let mut code = String::new(); + code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); + + let mut mods = Vec::new(); + + for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { + if obj.scope() == Some("blueprint".to_owned()) { + // TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. + continue; + } + + // TODO(#4478): add a 'testing' scope + if obj.fqname.contains("testing") { + continue; + } + + let arch_name = obj.snake_case_name(); + mods.push(format!("mod {arch_name};")); + } + + code.push_str(&mods.join("\n")); + + files_to_write.insert(generated_path, code); +} + +fn generate_impls( + _reporter: &Reporter, + objects: &Objects, + files_to_write: &mut BTreeMap, +) { + let generated_path = Utf8PathBuf::from("crates/re_query_cache2/src/latest_at/to_archetype"); + + let quoted_imports = quote! { + use std::sync::Arc; + + use re_query2::{PromiseResolver, PromiseResult}; + use re_types_core::{Archetype, Loggable as _}; + + use crate::CachedLatestAtResults; + }; + + for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { + if obj.scope() == Some("blueprint".to_owned()) { + // TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. + continue; + } + + if obj + .try_get_attr::(crate::ATTR_RUST_SERDE_TYPE) + .is_some() + { + // NOTE: legacy serde-based hacks. + continue; + } + + // TODO(#4478): add a 'testing' scope + if obj.fqname.contains("testing") { + continue; + } + + let quoted_imports = quoted_imports.to_string(); + let quoted_impl = quote_to_archetype_impl(objects, obj); + + let mut code = String::new(); + code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); + code.push_str("#![allow(unused_imports)]\n"); + code.push_str("#![allow(unused_parens)]\n"); + code.push_str("#![allow(clippy::clone_on_copy)]\n"); + if obj.deprecation_notice().is_some() { + code.push_str("#![allow(deprecated)]\n"); + } + code.push_str(&format!("\n\n{quoted_imports}\n\n")); + code.push_str("ed_impl.to_string()); + + let arch_name = obj.snake_case_name(); + files_to_write.insert( + generated_path.join([arch_name.as_str(), "rs"].join(".")), + code.replace(&format!("{NEWLINE_TOKEN:?}"), "\n\n") + .replace(&format!("{COMMENT_SEPARATOR_TOKEN:?}"), "\n\n// --- \n\n") + .replace( + &format!("{COMMENT_REQUIRED_TOKEN:?}"), + "\n\n// --- Required ---\n\n", + ) + .replace( + &format!("{COMMENT_RECOMMENDED_OPTIONAL_TOKEN:?}"), + "\n\n// --- Recommended/Optional ---\n\n", + ), + ); + } +} + +fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { + assert!(obj.kind == ObjectKind::Archetype); + + let quoted_arch_fqname = quote_fqname_as_type_path(&obj.crate_name(), &obj.fqname); + + let quoted_required = obj + .fields + .iter() + .filter(|obj_field| obj_field.kind() == Some(FieldKind::Required)) + .filter_map(|obj_field| { + let quoted_name = format_ident!("{}", obj_field.name); + + let type_fqname = obj_field.typ.fqname()?; + let type_name = type_fqname.rsplit_once('.').map(|(_, name)| name)?; + + let quoted_type_name = format_ident!("{type_name}"); + let quoted_type_fqname = + quote_fqname_as_type_path(&objects[type_fqname].crate_name(), type_fqname); + + let quoted_data = if obj_field.typ.is_plural() { + quote!(data.to_vec()) + } else { + quote! {{ + let Some(first) = data.first().cloned() else { + return PromiseResult::Error( + std::sync::Arc::new(re_types_core::DeserializationError::missing_data()) + ); + }; + first + }} + }; + + Some(quote! { + #NEWLINE_TOKEN + + use #quoted_type_fqname; + let #quoted_name = match self.get_required(<#quoted_type_name>::name()) { + Ok(#quoted_name) => #quoted_name, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let #quoted_name = match #quoted_name.to_dense::<#quoted_type_name>(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => #quoted_data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + }) + }); + + let quoted_optional = obj + .fields + .iter() + .filter(|obj_field| obj_field.kind() != Some(FieldKind::Required)) + .filter_map(|obj_field| { + let quoted_name = format_ident!("{}", obj_field.name); + + let type_fqname = obj_field.typ.fqname()?; + let type_name = type_fqname.rsplit_once('.').map(|(_, name)| name)?; + + let quoted_type_name = format_ident!("{type_name}"); + let quoted_type_fqname = + quote_fqname_as_type_path(&objects[type_fqname].crate_name(), type_fqname); + + let quoted_data = if obj_field.typ.is_plural() { + quote!(Some(data.to_vec())) + } else { + quote!(data.first().cloned()) + }; + + Some(quote! { + #NEWLINE_TOKEN + + use #quoted_type_fqname; + let #quoted_name = if let Some(#quoted_name) = self.get(<#quoted_type_name>::name()) { + match #quoted_name.to_dense::<#quoted_type_name>(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => #quoted_data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + }) + }); + + let quoted_fields = obj.fields.iter().map(|obj_field| { + let quoted_name = format_ident!("{}", obj_field.name); + quote!(#quoted_name) + }); + + quote! { + impl crate::ToArchetype<#quoted_arch_fqname> for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + #NEWLINE_TOKEN + re_tracing::profile_function!(<#quoted_arch_fqname>::name()); + #NEWLINE_TOKEN + + // --- Required --- + #COMMENT_REQUIRED_TOKEN + + #(#quoted_required)* + + // --- Recommended/Optional --- + #COMMENT_RECOMMENDED_OPTIONAL_TOKEN + + #(#quoted_optional)* + + // --- + #COMMENT_SEPARATOR_TOKEN + + // TODO(cmc): A lot of useless copying going on since archetypes are fully owned + // types. Probably fine for now since these are very high-level APIs anyhow. + let arch = #quoted_arch_fqname { + #(#quoted_fields),* + }; + + #NEWLINE_TOKEN + + PromiseResult::Ready(Ok(arch)) + } + } + } +} + +// --- + +// TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. +fn quote_fqname_as_type_path(crate_name: &str, fqname: impl AsRef) -> TokenStream { + let fqname = fqname + .as_ref() + .replace('.', "::") + .replace("rerun", crate_name); + let expr: syn::TypePath = syn::parse_str(&fqname).unwrap(); + quote!(#expr) +} diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index b69f46aca3b3..ae6e37ed0594 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -2,11 +2,10 @@ use std::collections::{BTreeMap, BTreeSet}; use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::LatestAtQuery; use re_data_ui::is_component_visible_in_ui; use re_entity_db::{EntityDb, InstancePath}; use re_log_types::{DataCell, DataRow, RowId, StoreKind}; -use re_query_cache::external::re_query::get_component_with_instances; use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; use re_types_core::{ components::{InstanceKey, VisualizerOverrides}, @@ -33,7 +32,6 @@ pub fn override_ui( // entity from the blueprint-inspector since it isn't "part" of a space-view to provide // the overrides. let query = ctx.current_query(); - let store = ctx.recording_store(); let query_result = ctx.lookup_query_result(space_view.id); let Some(data_result) = query_result @@ -80,7 +78,7 @@ pub fn override_ui( add_new_override( ctx, &query, - store, + ctx.recording(), ui, &view_systems, &component_to_vis, @@ -142,23 +140,39 @@ pub fn override_ui( StoreKind::Blueprint => { let store = ctx.store_context.blueprint.store(); let query = ctx.blueprint_query; - get_component_with_instances(store, query, path, *component_name) + ctx.store_context + .blueprint + .query_caches2() + .latest_at(store, query, entity_path, [*component_name]) + .components + .get(component_name) + .cloned() /* arc */ } StoreKind::Recording => { - get_component_with_instances(store, &query, path, *component_name) + ctx.recording() + .query_caches2() + .latest_at( + ctx.recording_store(), + &query, + entity_path, + [*component_name], + ) + .components + .get(component_name) + .cloned() /* arc */ } }; - if let Some((_, _, component_data)) = component_data { + if let Some(results) = component_data { ctx.component_ui_registry.edit_ui( ctx, ui, UiVerbosity::Small, &query, - store, + ctx.recording(), path, &overrides.individual_override_path, - &component_data, + &results, instance_key, ); } else { @@ -176,7 +190,7 @@ pub fn override_ui( pub fn add_new_override( ctx: &ViewerContext<'_>, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, ui: &mut egui::Ui, view_systems: &re_viewer_context::VisualizerCollection, component_to_vis: &BTreeMap, @@ -228,7 +242,8 @@ pub fn add_new_override( let mut splat_cell: DataCell = [InstanceKey::SPLAT].into(); splat_cell.compute_size_bytes(); - let Some(mut initial_data) = store + let Some(mut initial_data) = db + .store() .latest_at(query, &data_result.entity_path, *component, &components) .and_then(|result| result.2[0].clone()) .and_then(|cell| { @@ -243,7 +258,7 @@ pub fn add_new_override( sys.initial_override_value( ctx, query, - store, + db.store(), &data_result.entity_path, component, ) @@ -253,7 +268,7 @@ pub fn add_new_override( ctx.component_ui_registry.default_value( ctx, query, - store, + db, &data_result.entity_path, component, ) diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index 880863647912..5f094b276516 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -202,8 +202,8 @@ fn app_and_its_recordings_ui( ctx, ui, UiVerbosity::Reduced, - &ctx.current_query(), // unused - ctx.recording_store(), // unused + &ctx.current_query(), // unused + ctx.recording(), // unused ); }); diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index d91d4a65bb44..b311b38055bd 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -148,13 +148,7 @@ impl SelectionPanel { } else { (ctx.current_query(), ctx.recording()) }; - data_ui_item.data_ui( - ctx, - ui, - multi_selection_verbosity, - &query, - db.store(), - ); + data_ui_item.data_ui(ctx, ui, multi_selection_verbosity, &query, db); }); } @@ -385,7 +379,7 @@ fn what_is_selected_ui( ui.horizontal(|ui| { ui.label("component of"); - item_ui::entity_path_button(ctx, &query, db.store(), ui, None, entity_path); + item_ui::entity_path_button(ctx, &query, db, ui, None, entity_path); }); list_existing_data_blueprints(ui, ctx, &entity_path.clone().into(), viewport); @@ -443,14 +437,7 @@ fn what_is_selected_ui( guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); ui.horizontal(|ui| { ui.label("Parent"); - item_ui::entity_path_parts_buttons( - ctx, - &query, - db.store(), - ui, - None, - &parent, - ); + item_ui::entity_path_parts_buttons(ctx, &query, db, ui, None, &parent); }); } } @@ -492,7 +479,7 @@ fn what_is_selected_ui( item_ui::entity_path_parts_buttons( ctx, &query, - db.store(), + db, ui, Some(*space_view_id), &parent, @@ -550,7 +537,7 @@ fn list_existing_data_blueprints( item_ui::instance_path_button_to( ctx, &query, - db.store(), + db, ui, Some(*space_view_id), instance_path, @@ -1307,17 +1294,10 @@ fn depth_props_ui( if backproject_depth { ui.label("Pinhole"); - item_ui::entity_path_button( - ctx, - &query, - db.store(), - ui, - None, - &image_projection_ent_path, - ) - .on_hover_text( - "The entity path of the pinhole transform being used to do the backprojection.", - ); + item_ui::entity_path_button(ctx, &query, db, ui, None, &image_projection_ent_path) + .on_hover_text( + "The entity path of the pinhole transform being used to do the backprojection.", + ); ui.end_row(); depth_from_world_scale_ui(ui, &mut entity_props.depth_from_world_scale); diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 5ec1e81f08e9..f687e5ec6168 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -1,9 +1,10 @@ use std::collections::BTreeMap; -use re_data_store::{DataStore, LatestAtQuery}; -use re_entity_db::EntityPath; +use re_data_store::LatestAtQuery; +use re_entity_db::{ + external::re_query_cache2::CachedLatestAtComponentResults, EntityDb, EntityPath, +}; use re_log_types::DataCell; -use re_query::ComponentWithInstances; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; use crate::ViewerContext; @@ -39,9 +40,9 @@ type ComponentUiCallback = Box< &mut egui::Ui, UiVerbosity, &LatestAtQuery, - &DataStore, + &EntityDb, &EntityPath, - &ComponentWithInstances, + &CachedLatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -53,17 +54,17 @@ type ComponentEditCallback = Box< &mut egui::Ui, UiVerbosity, &LatestAtQuery, - &DataStore, + &EntityDb, &EntityPath, &EntityPath, - &ComponentWithInstances, + &CachedLatestAtComponentResults, &InstanceKey, ) + Send + Sync, >; type DefaultValueCallback = Box< - dyn Fn(&ViewerContext<'_>, &LatestAtQuery, &DataStore, &EntityPath) -> DataCell + Send + Sync, + dyn Fn(&ViewerContext<'_>, &LatestAtQuery, &EntityDb, &EntityPath) -> DataCell + Send + Sync, >; /// How to display components in a Ui. @@ -119,14 +120,19 @@ impl ComponentUiRegistry { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &InstanceKey, ) { - re_tracing::profile_function!(component.name().full_name()); + let Some(component_name) = component.component_name(db.resolver()) else { + // TODO(#5607): what should happen if the promise is still pending? + return; + }; + + re_tracing::profile_function!(component_name.full_name()); - if component.name() == InstanceKey::name() { + if component_name == InstanceKey::name() { // The user wants to show a ui for the `InstanceKey` component - well, that's easy: ui.label(instance_key.to_string()); return; @@ -134,14 +140,14 @@ impl ComponentUiRegistry { let ui_callback = self .component_uis - .get(&component.name()) + .get(&component_name) .unwrap_or(&self.fallback_ui); (*ui_callback)( ctx, ui, verbosity, query, - store, + db, entity_path, component, instance_key, @@ -156,21 +162,26 @@ impl ComponentUiRegistry { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &InstanceKey, ) { - re_tracing::profile_function!(component.name().full_name()); + let Some(component_name) = component.component_name(db.resolver()) else { + // TODO(#5607): what should happen if the promise is still pending? + return; + }; + + re_tracing::profile_function!(component_name.full_name()); - if let Some((_, edit_callback)) = self.component_editors.get(&component.name()) { + if let Some((_, edit_callback)) = self.component_editors.get(&component_name) { (*edit_callback)( ctx, ui, verbosity, query, - store, + db, entity_path, override_path, component, @@ -183,7 +194,7 @@ impl ComponentUiRegistry { ui, verbosity, query, - store, + db, entity_path, component, instance_key, @@ -197,7 +208,7 @@ impl ComponentUiRegistry { &self, ctx: &ViewerContext<'_>, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, component: &ComponentName, ) -> Option { @@ -205,6 +216,6 @@ impl ComponentUiRegistry { self.component_editors .get(component) - .map(|(default_value, _)| (*default_value)(ctx, query, store, entity_path)) + .map(|(default_value, _)| (*default_value)(ctx, query, db, entity_path)) } } diff --git a/crates/re_viewport/src/blueprint/data_ui.rs b/crates/re_viewport/src/blueprint/data_ui.rs index ae5010180662..7ed45bc2274a 100644 --- a/crates/re_viewport/src/blueprint/data_ui.rs +++ b/crates/re_viewport/src/blueprint/data_ui.rs @@ -11,10 +11,10 @@ impl DataUi for IncludedSpaceView { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let space_view: SpaceViewId = self.0.into(); - space_view.data_ui(ctx, ui, verbosity, query, store); + space_view.data_ui(ctx, ui, verbosity, query, db); } } @@ -26,10 +26,10 @@ impl DataUi for SpaceViewMaximized { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let space_view: SpaceViewId = self.0.into(); - space_view.data_ui(ctx, ui, verbosity, query, store); + space_view.data_ui(ctx, ui, verbosity, query, db); } } diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 4b59093a9537..23c268f67d63 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -154,7 +154,6 @@ fn add_entities_line_ui( re_tracing::profile_function!(); let query = ctx.current_query(); - let store = ctx.recording_store(); ui.horizontal(|ui| { let entity_path = &entity_tree.path; @@ -177,7 +176,7 @@ fn add_entities_line_ui( let response = item_ui::instance_path_button_to( ctx, &query, - store, + ctx.recording(), ui, Some(space_view.id), &InstancePath::entity_splat(entity_path.clone()), diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index aa57a27e67b1..602d91c32e0a 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -523,8 +523,6 @@ impl Viewport<'_, '_> { space_view_visible: bool, projection_mode: bool, ) { - let store = ctx.recording_store(); - let entity_path = node_or_path.path(); if projection_mode && entity_path == &space_view.space_origin { @@ -662,7 +660,13 @@ impl Viewport<'_, '_> { let response = response.on_hover_ui(|ui| { let query = ctx.current_query(); - re_data_ui::item_ui::entity_hover_card_ui(ui, ctx, &query, store, entity_path); + re_data_ui::item_ui::entity_hover_card_ui( + ui, + ctx, + &query, + ctx.recording(), + entity_path, + ); if empty_origin { ui.label(ctx.re_ui.warning_text( diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 2c53a75d60b9..8c4bce111ac9 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -275,7 +275,7 @@ fn color_space_ui( item_ui::instance_path_button( ctx, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ui, Some(query.space_view_id), &instance, @@ -285,7 +285,7 @@ fn color_space_ui( ui, UiVerbosity::Reduced, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ); }); ctx.select_hovered_on_click(&interact, Item::DataResult(query.space_view_id, instance)); diff --git a/examples/rust/extend_viewer_ui/src/main.rs b/examples/rust/extend_viewer_ui/src/main.rs index d0ac54af050e..fbc37dee872b 100644 --- a/examples/rust/extend_viewer_ui/src/main.rs +++ b/examples/rust/extend_viewer_ui/src/main.rs @@ -1,8 +1,7 @@ //! This example shows how to wrap the Rerun Viewer in your own GUI. use re_viewer::external::{ - arrow2, eframe, egui, re_data_store, re_entity_db, re_log, re_log_types, re_memory, re_query, - re_types, + arrow2, eframe, egui, re_data_store, re_entity_db, re_log, re_log_types, re_memory, re_types, }; // By using `re_memory::AccountingAllocator` Rerun can keep track of exactly how much memory it is using, @@ -153,20 +152,26 @@ fn component_ui( // just show the last value logged for each component: let query = re_data_store::LatestAtQuery::latest(timeline); - if let Some((_, _, component)) = re_query::get_component_with_instances( + let results = entity_db.query_caches2().latest_at( entity_db.store(), &query, entity_path, - component_name, - ) { + [component_name], + ); + let component = results + .components + .get(&component_name) + .and_then(|result| result.raw(entity_db.resolver(), component_name)); + + if let Some(data) = component { egui::ScrollArea::vertical() .auto_shrink([false, true]) .show(ui, |ui| { // Iterate over all the instances (e.g. all the points in the point cloud): - for instance_key in component.instance_keys() { - if let Some(value) = component.lookup_arrow(&instance_key) { - ui.label(format_arrow(&*value)); - } + + let num_instances = data.len(); + for i in 0..num_instances { + ui.label(format_arrow(&*data.sliced(i, 1))); } }); };