From 486d662e46d35abeff2678109b5b2752026a6757 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 27 Jan 2025 10:11:25 +0100 Subject: [PATCH 01/43] Fix mesh casting color components incorrectly (#8807) --- .../viewer/re_view_spatial/src/mesh_loader.rs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/viewer/re_view_spatial/src/mesh_loader.rs b/crates/viewer/re_view_spatial/src/mesh_loader.rs index 3e6dd956ec474..dae03f0867727 100644 --- a/crates/viewer/re_view_spatial/src/mesh_loader.rs +++ b/crates/viewer/re_view_spatial/src/mesh_loader.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use re_chunk_store::RowId; -use re_renderer::{mesh::GpuMesh, RenderContext, Rgba32Unmul}; -use re_types::components::MediaType; +use re_renderer::{mesh::GpuMesh, RenderContext}; +use re_types::{components::MediaType, datatypes}; use re_viewer_context::{gpu_bridge::texture_creation_desc_from_color_image, ImageInfo}; use crate::{mesh_cache::AnyMesh, visualizers::entity_iterator::clamped_vec_or}; @@ -17,15 +17,15 @@ pub struct NativeAsset3D<'a> { pub struct NativeMesh3D<'a> { pub vertex_positions: &'a [glam::Vec3], pub vertex_normals: Option<&'a [glam::Vec3]>, - pub vertex_colors: Option<&'a [re_renderer::Rgba32Unmul]>, + pub vertex_colors: Option<&'a [datatypes::Rgba32]>, pub vertex_texcoords: Option<&'a [glam::Vec2]>, pub triangle_indices: Option<&'a [glam::UVec3]>, - pub albedo_factor: Option, + pub albedo_factor: Option, - pub albedo_texture_buffer: Option, - pub albedo_texture_format: Option, + pub albedo_texture_buffer: Option, + pub albedo_texture_format: Option, } pub struct LoadedMesh { @@ -133,9 +133,14 @@ impl LoadedMesh { let vertex_colors = if let Some(vertex_colors) = vertex_colors { re_tracing::profile_scope!("copy_colors"); - clamped_vec_or(vertex_colors, num_positions, &Rgba32Unmul::WHITE) + vertex_colors + .iter() + .map(|c| re_renderer::Rgba32Unmul::from_rgba_unmul_array(c.to_array())) + .chain(std::iter::repeat(re_renderer::Rgba32Unmul::WHITE)) + .take(num_positions) + .collect::>() } else { - vec![Rgba32Unmul::WHITE; num_positions] + vec![re_renderer::Rgba32Unmul::WHITE; num_positions] }; let vertex_normals = if let Some(normals) = vertex_normals { @@ -183,7 +188,7 @@ impl LoadedMesh { label: name.clone().into(), index_range: 0..num_indices as _, albedo, - albedo_factor: albedo_factor.unwrap_or(re_renderer::Color32::WHITE).into(), + albedo_factor: albedo_factor.unwrap_or(datatypes::Rgba32::WHITE).into(), }], }; @@ -209,8 +214,8 @@ impl LoadedMesh { } fn try_get_or_create_albedo_texture( - albedo_texture_buffer: &Option, - albedo_texture_format: &Option, + albedo_texture_buffer: &Option, + albedo_texture_format: &Option, render_ctx: &RenderContext, texture_key: u64, name: &str, From c6cee9ce87d23a743677d54c2d59208e08e81dd4 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 27 Jan 2025 10:27:52 +0100 Subject: [PATCH 02/43] Move `Time/ComponentColumnDescriptor` to new `re_sorbet` (#8813) ### Related * Part of https://github.com/rerun-io/rerun/issues/8744 ### What Creates a new crate `re_sorbet`. The goal is for it to contain our canonical ways of converting to-and-from arrow metadata and record batches. In this initial PR, I mostly move some code around. --- ARCHITECTURE.md | 3 +- Cargo.lock | 12 + Cargo.toml | 1 + crates/store/re_chunk_store/Cargo.toml | 1 + crates/store/re_chunk_store/src/dataframe.rs | 335 +----------------- crates/store/re_chunk_store/src/lib.rs | 26 +- .../store/re_log_types/src/time_point/mod.rs | 33 +- crates/store/re_sorbet/Cargo.toml | 30 ++ crates/store/re_sorbet/README.md | 12 + .../store/re_sorbet/src/data_column_schema.rs | 241 +++++++++++++ .../re_sorbet/src/index_column_schema.rs | 118 ++++++ crates/store/re_sorbet/src/lib.rs | 16 + crates/store/re_sorbet/src/metadata.rs | 69 ++++ rerun_py/src/arrow.rs | 12 +- 14 files changed, 552 insertions(+), 357 deletions(-) create mode 100644 crates/store/re_sorbet/Cargo.toml create mode 100644 crates/store/re_sorbet/README.md create mode 100644 crates/store/re_sorbet/src/data_column_schema.rs create mode 100644 crates/store/re_sorbet/src/index_column_schema.rs create mode 100644 crates/store/re_sorbet/src/lib.rs create mode 100644 crates/store/re_sorbet/src/metadata.rs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index d38e3fce7df94..f9bbcffd04ebe 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -181,9 +181,10 @@ Update instructions: | --------------- | --------------------------------------------------------------------------------------------- | | re_chunk | A chunk of Rerun data, encoded using Arrow. Used for logging, transport, storage and compute. | | re_chunk_store | An in-memory time series database for Rerun log data, based on Apache Arrow. | +| re_format_arrow | Formatting of Apache Arrow tables. | | re_log_types | The basic building blocks of the Rerun data types and tables. | +| re_sorbet | Rerun arrow metadata and record batch definitions. | | re_types_core | The core traits and types that power Rerun's data model. | -| re_format_arrow | Formatting of Apache Arrow tables. | ### Data flow diff --git a/Cargo.lock b/Cargo.lock index 53ebfcc9378d9..1dad0b098aa93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5758,6 +5758,7 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_protos", + "re_sorbet", "re_tracing", "re_types", "re_types_core", @@ -6469,6 +6470,17 @@ dependencies = [ "web-time", ] +[[package]] +name = "re_sorbet" +version = "0.22.0-alpha.1+dev" +dependencies = [ + "arrow", + "re_log", + "re_log_types", + "re_types_core", + "thiserror 1.0.65", +] + [[package]] name = "re_string_interner" version = "0.22.0-alpha.1+dev" diff --git a/Cargo.toml b/Cargo.toml index cd9451fa11779..e685969997115 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.22.0-al re_log_types = { path = "crates/store/re_log_types", version = "=0.22.0-alpha.1", default-features = false } re_query = { path = "crates/store/re_query", version = "=0.22.0-alpha.1", default-features = false } re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.22.0-alpha.1", default-features = false } +re_sorbet = { path = "crates/store/re_sorbet", version = "=0.22.0-alpha.1", default-features = false } re_types = { path = "crates/store/re_types", version = "=0.22.0-alpha.1", default-features = false } re_types_core = { path = "crates/store/re_types_core", version = "=0.22.0-alpha.1", default-features = false } re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.22.0-alpha.1", default-features = false } diff --git a/crates/store/re_chunk_store/Cargo.toml b/crates/store/re_chunk_store/Cargo.toml index f0fbfbfadb194..f57eda12dbaf2 100644 --- a/crates/store/re_chunk_store/Cargo.toml +++ b/crates/store/re_chunk_store/Cargo.toml @@ -41,6 +41,7 @@ re_log = { workspace = true, features = ["setup"] } re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true re_protos.workspace = true +re_sorbet.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/store/re_chunk_store/src/dataframe.rs b/crates/store/re_chunk_store/src/dataframe.rs index 894eab9f6606e..61c4fb96650b6 100644 --- a/crates/store/re_chunk_store/src/dataframe.rs +++ b/crates/store/re_chunk_store/src/dataframe.rs @@ -12,8 +12,9 @@ use arrow::{ use itertools::Itertools; use re_chunk::TimelineName; -use re_log_types::{ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, Timeline}; -use re_types_core::{ArchetypeFieldName, ArchetypeName, ComponentDescriptor, ComponentName}; +use re_log_types::{EntityPath, ResolvedTimeRange, TimeInt, Timeline}; +use re_sorbet::{ComponentColumnDescriptor, TimeColumnDescriptor}; +use re_types_core::ComponentName; use crate::{ChunkStore, ColumnMetadata}; @@ -76,299 +77,6 @@ impl ColumnDescriptor { } } -/// Describes a time column, such as `log_time`. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TimeColumnDescriptor { - /// The timeline this column is associated with. - pub timeline: Timeline, - - /// The Arrow datatype of the column. - pub datatype: ArrowDatatype, -} - -impl PartialOrd for TimeColumnDescriptor { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for TimeColumnDescriptor { - #[inline] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - let Self { - timeline, - datatype: _, - } = self; - timeline.cmp(&other.timeline) - } -} - -impl TimeColumnDescriptor { - /// Used when returning a null column, i.e. when a lookup failed. - #[inline] - pub fn new_null(name: TimelineName) -> Self { - Self { - // TODO(cmc): I picked a sequence here because I have to pick something. - // It doesn't matter, only the name will remain in the Arrow schema anyhow. - timeline: Timeline::new_sequence(name), - datatype: ArrowDatatype::Null, - } - } - - #[inline] - pub fn timeline(&self) -> Timeline { - self.timeline - } - - #[inline] - pub fn name(&self) -> &TimelineName { - self.timeline.name() - } - - #[inline] - pub fn typ(&self) -> re_log_types::TimeType { - self.timeline.typ() - } - - #[inline] - pub fn datatype(&self) -> &ArrowDatatype { - &self.datatype - } - - #[inline] - pub fn to_arrow_field(&self) -> ArrowField { - let Self { timeline, datatype } = self; - - let nullable = true; // Time column must be nullable since static data doesn't have a time. - - let metadata = std::iter::once(Some(( - "sorbet.index_name".to_owned(), - timeline.name().to_string(), - ))) - .flatten() - .collect(); - - ArrowField::new(timeline.name().to_string(), datatype.clone(), nullable) - .with_metadata(metadata) - } -} - -/// Describes a data/component column, such as `Position3D`. -// -// TODO(#6889): Fully sorbetize this thing? `ArchetypeName` and such don't make sense in that -// context. And whatever `archetype_field_name` ends up being, it needs interning. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ComponentColumnDescriptor { - /// The path of the entity. - pub entity_path: EntityPath, - - /// Optional name of the `Archetype` associated with this data. - /// - /// `None` if the data wasn't logged through an archetype. - /// - /// Example: `rerun.archetypes.Points3D`. - pub archetype_name: Option, - - /// Optional name of the field within `Archetype` associated with this data. - /// - /// `None` if the data wasn't logged through an archetype. - /// - /// Example: `positions`. - pub archetype_field_name: Option, - - /// Semantic name associated with this data. - /// - /// This is fully implied by `archetype_name` and `archetype_field`, but - /// included for semantic convenience. - /// - /// Example: `rerun.components.Position3D`. - pub component_name: ComponentName, - - /// The Arrow datatype of the stored column. - /// - /// This is the log-time datatype corresponding to how this data is encoded - /// in a chunk. Currently this will always be an [`arrow::array::ListArray`], but as - /// we introduce mono-type optimization, this might be a native type instead. - pub store_datatype: ArrowDatatype, - - /// Whether this column represents static data. - pub is_static: bool, - - /// Whether this column represents an indicator component. - pub is_indicator: bool, - - /// Whether this column represents a [`Clear`]-related components. - /// - /// [`Clear`]: re_types_core::archetypes::Clear - pub is_tombstone: bool, - - /// Whether this column contains either no data or only contains null and/or empty values (`[]`). - pub is_semantically_empty: bool, -} - -impl PartialOrd for ComponentColumnDescriptor { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for ComponentColumnDescriptor { - #[inline] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - let Self { - entity_path, - archetype_name, - archetype_field_name, - component_name, - store_datatype: _, - is_static: _, - is_indicator: _, - is_tombstone: _, - is_semantically_empty: _, - } = self; - - entity_path - .cmp(&other.entity_path) - .then_with(|| component_name.cmp(&other.component_name)) - .then_with(|| archetype_name.cmp(&other.archetype_name)) - .then_with(|| archetype_field_name.cmp(&other.archetype_field_name)) - } -} - -impl std::fmt::Display for ComponentColumnDescriptor { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - entity_path, - archetype_name, - archetype_field_name, - component_name, - store_datatype: _, - is_static, - is_indicator: _, - is_tombstone: _, - is_semantically_empty: _, - } = self; - - let descriptor = ComponentDescriptor { - archetype_name: *archetype_name, - archetype_field_name: *archetype_field_name, - component_name: *component_name, - }; - - let s = format!("{entity_path}@{}", descriptor.short_name()); - - if *is_static { - f.write_fmt(format_args!("|{s}|")) - } else { - f.write_str(&s) - } - } -} - -impl From for re_types_core::ComponentDescriptor { - #[inline] - fn from(descr: ComponentColumnDescriptor) -> Self { - Self { - archetype_name: descr.archetype_name, - archetype_field_name: descr.archetype_field_name, - component_name: descr.component_name, - } - } -} - -impl From<&ComponentColumnDescriptor> for re_types_core::ComponentDescriptor { - #[inline] - fn from(descr: &ComponentColumnDescriptor) -> Self { - Self { - archetype_name: descr.archetype_name, - archetype_field_name: descr.archetype_field_name, - component_name: descr.component_name, - } - } -} - -impl ComponentColumnDescriptor { - pub fn component_path(&self) -> ComponentPath { - ComponentPath { - entity_path: self.entity_path.clone(), - component_name: self.component_name, - } - } - - #[inline] - pub fn matches(&self, entity_path: &EntityPath, component_name: &str) -> bool { - &self.entity_path == entity_path && self.component_name.matches(component_name) - } - - fn metadata(&self) -> std::collections::HashMap { - let Self { - entity_path, - archetype_name, - archetype_field_name, - component_name, - store_datatype: _, - is_static, - is_indicator, - is_tombstone, - is_semantically_empty, - } = self; - - [ - (*is_static).then_some(("sorbet.is_static".to_owned(), "yes".to_owned())), - (*is_indicator).then_some(("sorbet.is_indicator".to_owned(), "yes".to_owned())), - (*is_tombstone).then_some(("sorbet.is_tombstone".to_owned(), "yes".to_owned())), - (*is_semantically_empty) - .then_some(("sorbet.is_semantically_empty".to_owned(), "yes".to_owned())), - Some(("sorbet.path".to_owned(), entity_path.to_string())), - Some(( - "sorbet.semantic_type".to_owned(), - component_name.short_name().to_owned(), - )), - archetype_name.map(|name| { - ( - "sorbet.semantic_family".to_owned(), - name.short_name().to_owned(), - ) - }), - archetype_field_name - .as_ref() - .map(|name| ("sorbet.logical_type".to_owned(), name.to_string())), - ] - .into_iter() - .flatten() - .collect() - } - - #[inline] - pub fn returned_datatype(&self) -> ArrowDatatype { - self.store_datatype.clone() - } - - #[inline] - pub fn to_arrow_field(&self) -> ArrowField { - let entity_path = &self.entity_path; - let descriptor = ComponentDescriptor { - archetype_name: self.archetype_name, - archetype_field_name: self.archetype_field_name, - component_name: self.component_name, - }; - - ArrowField::new( - // NOTE: Uncomment this to expose fully-qualified names in the Dataframe APIs! - // I'm not doing that right now, to avoid breaking changes (and we need to talk about - // what the syntax for these fully-qualified paths need to look like first). - format!("{}:{}", entity_path, descriptor.component_name.short_name()), - // format!("{entity_path}@{}", descriptor.short_name()), - self.returned_datatype(), - true, /* nullable */ - ) - // TODO(#6889): This needs some proper sorbetization -- I just threw these names randomly. - .with_metadata(self.metadata()) - } -} - // --- Selectors --- /// Describes a column selection to return as part of a query. @@ -728,12 +436,10 @@ impl ChunkStore { pub fn schema(&self) -> Vec { re_tracing::profile_function!(); - let timelines = self.all_timelines_sorted().into_iter().map(|timeline| { - ColumnDescriptor::Time(TimeColumnDescriptor { - timeline, - datatype: timeline.datatype(), - }) - }); + let timelines = self + .all_timelines_sorted() + .into_iter() + .map(|timeline| ColumnDescriptor::Time(TimeColumnDescriptor::from(timeline))); let mut components = self .per_column_metadata @@ -759,16 +465,17 @@ impl ChunkStore { } = metadata; ComponentColumnDescriptor { - entity_path: entity_path.clone(), - archetype_name: component_descr.archetype_name, - archetype_field_name: component_descr.archetype_field_name, - component_name: component_descr.component_name, // NOTE: The data is always a at least a list, whether it's latest-at or range. // It might be wrapped further in e.g. a dict, but at the very least // it's a list. store_datatype: ArrowListArray::DATA_TYPE_CONSTRUCTOR( ArrowField::new("item", datatype.clone(), true).into(), ), + + entity_path: entity_path.clone(), + archetype_name: component_descr.archetype_name, + archetype_field_name: component_descr.archetype_field_name, + component_name: component_descr.component_name, is_static, is_indicator, is_tombstone, @@ -777,18 +484,7 @@ impl ChunkStore { }) .collect_vec(); - components.sort_by(|descr1, descr2| { - descr1 - .entity_path - .cmp(&descr2.entity_path) - .then(descr1.archetype_name.cmp(&descr2.archetype_name)) - .then( - descr1 - .archetype_field_name - .cmp(&descr2.archetype_field_name), - ) - .then(descr1.component_name.cmp(&descr2.component_name)) - }); + components.sort(); timelines .chain(components.into_iter().map(ColumnDescriptor::Component)) @@ -805,10 +501,7 @@ impl ChunkStore { .copied() .unwrap_or_else(|| Timeline::new_temporal(selector.timeline)); - TimeColumnDescriptor { - timeline, - datatype: timeline.datatype(), - } + TimeColumnDescriptor::from(timeline) } /// Given a [`ComponentColumnSelector`], returns the corresponding [`ComponentColumnDescriptor`]. diff --git a/crates/store/re_chunk_store/src/lib.rs b/crates/store/re_chunk_store/src/lib.rs index 6c64a98e6a6fe..3bb2dcb85f7aa 100644 --- a/crates/store/re_chunk_store/src/lib.rs +++ b/crates/store/re_chunk_store/src/lib.rs @@ -26,22 +26,18 @@ mod writes; mod protobuf_conversions; -pub use self::dataframe::{ - ColumnDescriptor, ColumnSelector, ComponentColumnDescriptor, ComponentColumnSelector, Index, - IndexRange, IndexValue, QueryExpression, SparseFillStrategy, TimeColumnDescriptor, - TimeColumnSelector, ViewContentsSelector, -}; -pub use self::events::{ - ChunkCompactionReport, ChunkStoreDiff, ChunkStoreDiffKind, ChunkStoreEvent, -}; -pub use self::gc::{GarbageCollectionOptions, GarbageCollectionTarget}; -pub use self::stats::{ChunkStoreChunkStats, ChunkStoreStats}; -pub use self::store::{ - ChunkStore, ChunkStoreConfig, ChunkStoreGeneration, ChunkStoreHandle, ColumnMetadata, -}; -pub use self::subscribers::{ - ChunkStoreSubscriber, ChunkStoreSubscriberHandle, PerStoreChunkSubscriber, +pub use self::{ + dataframe::{ + ColumnDescriptor, ColumnSelector, ComponentColumnSelector, Index, IndexRange, IndexValue, + QueryExpression, SparseFillStrategy, TimeColumnSelector, ViewContentsSelector, + }, + events::{ChunkCompactionReport, ChunkStoreDiff, ChunkStoreDiffKind, ChunkStoreEvent}, + gc::{GarbageCollectionOptions, GarbageCollectionTarget}, + stats::{ChunkStoreChunkStats, ChunkStoreStats}, + store::{ChunkStore, ChunkStoreConfig, ChunkStoreGeneration, ChunkStoreHandle, ColumnMetadata}, + subscribers::{ChunkStoreSubscriber, ChunkStoreSubscriberHandle, PerStoreChunkSubscriber}, }; +pub use re_sorbet::{ComponentColumnDescriptor, TimeColumnDescriptor}; pub(crate) use self::store::ColumnMetadataState; diff --git a/crates/store/re_log_types/src/time_point/mod.rs b/crates/store/re_log_types/src/time_point/mod.rs index 2626fb0b4a881..e8977ddfaab0a 100644 --- a/crates/store/re_log_types/src/time_point/mod.rs +++ b/crates/store/re_log_types/src/time_point/mod.rs @@ -3,19 +3,22 @@ use std::{ sync::Arc, }; -mod non_min_i64; -mod time_int; -mod timeline; +use arrow::datatypes::DataType as ArrowDataType; use crate::{ time::{Time, TimeZone}, ResolvedTimeRange, }; -// Re-exports -pub use non_min_i64::{NonMinI64, TryFromIntError}; -pub use time_int::TimeInt; -pub use timeline::{Timeline, TimelineName}; +mod non_min_i64; +mod time_int; +mod timeline; + +pub use self::{ + non_min_i64::{NonMinI64, TryFromIntError}, + time_int::TimeInt, + timeline::{Timeline, TimelineName}, +}; /// A point in time on any number of [`Timeline`]s. /// @@ -188,12 +191,18 @@ impl TimeType { /// Returns the appropriate arrow datatype to represent this timeline. #[inline] - pub fn datatype(self) -> arrow::datatypes::DataType { + pub fn datatype(self) -> ArrowDataType { match self { - Self::Time => { - arrow::datatypes::DataType::Timestamp(arrow::datatypes::TimeUnit::Nanosecond, None) - } - Self::Sequence => arrow::datatypes::DataType::Int64, + Self::Time => ArrowDataType::Timestamp(arrow::datatypes::TimeUnit::Nanosecond, None), + Self::Sequence => ArrowDataType::Int64, + } + } + + pub fn from_arrow_datatype(datatype: &ArrowDataType) -> Option { + match datatype { + ArrowDataType::Timestamp(_, _) => Some(Self::Time), + ArrowDataType::Int64 => Some(Self::Sequence), + _ => None, } } diff --git a/crates/store/re_sorbet/Cargo.toml b/crates/store/re_sorbet/Cargo.toml new file mode 100644 index 0000000000000..9cbedebbf68ef --- /dev/null +++ b/crates/store/re_sorbet/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "re_sorbet" +authors.workspace = true +description = "Rerun arrow metadata definitions" +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +publish = true +readme = "README.md" +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[lints] +workspace = true + +[package.metadata.docs.rs] +all-features = true + + +[dependencies] +re_log_types.workspace = true +re_log.workspace = true +re_types_core.workspace = true + +arrow.workspace = true +thiserror.workspace = true + +# Keep this crate simple, with few dependencies. diff --git a/crates/store/re_sorbet/README.md b/crates/store/re_sorbet/README.md new file mode 100644 index 0000000000000..5864e0eeaf46e --- /dev/null +++ b/crates/store/re_sorbet/README.md @@ -0,0 +1,12 @@ +# re_sorbet + +Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. + +[![Latest version](https://img.shields.io/crates/v/re_sorbet.svg)](https://crates.io/crates/store/re_sorbet?speculative-link) +[![Documentation](https://docs.rs/re_sorbet/badge.svg)](https://docs.rs/re_sorbet?speculative-link) +![MIT](https://img.shields.io/badge/license-MIT-blue.svg) +![Apache](https://img.shields.io/badge/license-Apache-blue.svg) + +Rerun arrow metadata and record batch definitions. + +Handles the structure of arrow record batches and their meta data for different use cases for Rerun. diff --git a/crates/store/re_sorbet/src/data_column_schema.rs b/crates/store/re_sorbet/src/data_column_schema.rs new file mode 100644 index 0000000000000..4c8ef9811dc87 --- /dev/null +++ b/crates/store/re_sorbet/src/data_column_schema.rs @@ -0,0 +1,241 @@ +use arrow::datatypes::{DataType as ArrowDatatype, Field as ArrowField}; + +use re_log_types::{ComponentPath, EntityPath}; +use re_types_core::{ArchetypeFieldName, ArchetypeName, ComponentDescriptor, ComponentName}; + +use crate::{ArrowFieldMetadata, MetadataExt as _, MissingFieldMetadata}; + +/// Describes a data/component column, such as `Position3D`, in a dataframe. +/// +/// This is an [`ArrowField`] that contains specific meta-data. +// +// TODO(#6889): Fully sorbetize this thing? `ArchetypeName` and such don't make sense in that +// context. And whatever `archetype_field_name` ends up being, it needs interning. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ComponentColumnDescriptor { + /// The Arrow datatype of the stored column. + /// + /// This is the log-time datatype corresponding to how this data is encoded + /// in a chunk. Currently this will always be an [`arrow::array::ListArray`], but as + /// we introduce mono-type optimization, this might be a native type instead. + pub store_datatype: ArrowDatatype, + + /// The path of the entity. + pub entity_path: EntityPath, + + /// Optional name of the `Archetype` associated with this data. + /// + /// `None` if the data wasn't logged through an archetype. + /// + /// Example: `rerun.archetypes.Points3D`. + pub archetype_name: Option, + + /// Optional name of the field within `Archetype` associated with this data. + /// + /// `None` if the data wasn't logged through an archetype. + /// + /// Example: `positions`. + pub archetype_field_name: Option, + + /// Semantic name associated with this data. + /// + /// This is fully implied by `archetype_name` and `archetype_field`, but + /// included for semantic convenience. + /// + /// Example: `rerun.components.Position3D`. + pub component_name: ComponentName, + + /// Whether this column represents static data. + pub is_static: bool, + + /// Whether this column represents an indicator component. + pub is_indicator: bool, + + /// Whether this column represents a [`Clear`]-related components. + /// + /// [`Clear`]: re_types_core::archetypes::Clear + pub is_tombstone: bool, + + /// Whether this column contains either no data or only contains null and/or empty values (`[]`). + pub is_semantically_empty: bool, +} + +impl PartialOrd for ComponentColumnDescriptor { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ComponentColumnDescriptor { + #[inline] + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + let Self { + entity_path, + archetype_name, + archetype_field_name, + component_name, + store_datatype: _, + is_static: _, + is_indicator: _, + is_tombstone: _, + is_semantically_empty: _, + } = self; + + entity_path + .cmp(&other.entity_path) + .then_with(|| archetype_name.cmp(&other.archetype_name)) + .then_with(|| archetype_field_name.cmp(&other.archetype_field_name)) + .then_with(|| component_name.cmp(&other.component_name)) + } +} + +impl std::fmt::Display for ComponentColumnDescriptor { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + entity_path, + archetype_name, + archetype_field_name, + component_name, + store_datatype: _, + is_static, + is_indicator: _, + is_tombstone: _, + is_semantically_empty: _, + } = self; + + let descriptor = ComponentDescriptor { + archetype_name: *archetype_name, + archetype_field_name: *archetype_field_name, + component_name: *component_name, + }; + + let s = format!("{entity_path}@{}", descriptor.short_name()); + + if *is_static { + f.write_fmt(format_args!("|{s}|")) + } else { + f.write_str(&s) + } + } +} + +impl From for re_types_core::ComponentDescriptor { + #[inline] + fn from(descr: ComponentColumnDescriptor) -> Self { + Self { + archetype_name: descr.archetype_name, + archetype_field_name: descr.archetype_field_name, + component_name: descr.component_name, + } + } +} + +impl From<&ComponentColumnDescriptor> for re_types_core::ComponentDescriptor { + #[inline] + fn from(descr: &ComponentColumnDescriptor) -> Self { + Self { + archetype_name: descr.archetype_name, + archetype_field_name: descr.archetype_field_name, + component_name: descr.component_name, + } + } +} + +impl ComponentColumnDescriptor { + pub fn component_path(&self) -> ComponentPath { + ComponentPath { + entity_path: self.entity_path.clone(), + component_name: self.component_name, + } + } + + #[inline] + pub fn matches(&self, entity_path: &EntityPath, component_name: &str) -> bool { + &self.entity_path == entity_path && self.component_name.matches(component_name) + } + + fn metadata(&self) -> ArrowFieldMetadata { + let Self { + entity_path, + archetype_name, + archetype_field_name, + component_name, + store_datatype: _, + is_static, + is_indicator, + is_tombstone, + is_semantically_empty, + } = self; + + // TODO(#6889): This needs some proper sorbetization -- I just threw these names randomly. + [ + (*is_static).then_some(("sorbet.is_static".to_owned(), "yes".to_owned())), + (*is_indicator).then_some(("sorbet.is_indicator".to_owned(), "yes".to_owned())), + (*is_tombstone).then_some(("sorbet.is_tombstone".to_owned(), "yes".to_owned())), + (*is_semantically_empty) + .then_some(("sorbet.is_semantically_empty".to_owned(), "yes".to_owned())), + Some(("sorbet.path".to_owned(), entity_path.to_string())), + Some(( + "sorbet.semantic_type".to_owned(), + component_name.short_name().to_owned(), + )), + archetype_name.map(|name| { + ( + "sorbet.semantic_family".to_owned(), + name.short_name().to_owned(), + ) + }), + archetype_field_name + .as_ref() + .map(|name| ("sorbet.logical_type".to_owned(), name.to_string())), + ] + .into_iter() + .flatten() + .collect() + } + + #[inline] + pub fn returned_datatype(&self) -> ArrowDatatype { + self.store_datatype.clone() + } + + #[inline] + pub fn to_arrow_field(&self) -> ArrowField { + let entity_path = &self.entity_path; + let descriptor = ComponentDescriptor { + archetype_name: self.archetype_name, + archetype_field_name: self.archetype_field_name, + component_name: self.component_name, + }; + + ArrowField::new( + // NOTE: Uncomment this to expose fully-qualified names in the Dataframe APIs! + // I'm not doing that right now, to avoid breaking changes (and we need to talk about + // what the syntax for these fully-qualified paths need to look like first). + format!("{}:{}", entity_path, descriptor.component_name.short_name()), + // format!("{entity_path}@{}", descriptor.short_name()), + self.returned_datatype(), + true, /* nullable */ + ) + .with_metadata(self.metadata()) + } +} + +impl TryFrom<&ArrowField> for ComponentColumnDescriptor { + type Error = MissingFieldMetadata; + + fn try_from(field: &ArrowField) -> Result { + Ok(Self { + store_datatype: field.data_type().clone(), + entity_path: EntityPath::parse_forgiving(field.get_or_err("sorbet.path")?), + archetype_name: field.get_opt("sorbet.semantic_family").map(|x| x.into()), + archetype_field_name: field.get_opt("sorbet.logical_type").map(|x| x.into()), + component_name: field.get_or_err("sorbet.semantic_type")?.into(), + is_static: field.get_bool("sorbet.is_static"), + is_indicator: field.get_bool("sorbet.is_indicator"), + is_tombstone: field.get_bool("sorbet.is_tombstone"), + is_semantically_empty: field.get_bool("sorbet.is_semantically_empty"), + }) + } +} diff --git a/crates/store/re_sorbet/src/index_column_schema.rs b/crates/store/re_sorbet/src/index_column_schema.rs new file mode 100644 index 0000000000000..255ea88578659 --- /dev/null +++ b/crates/store/re_sorbet/src/index_column_schema.rs @@ -0,0 +1,118 @@ +use arrow::datatypes::{DataType as ArrowDatatype, Field as ArrowField}; +use re_log_types::{Timeline, TimelineName}; + +#[derive(thiserror::Error, Debug)] +#[error("Unsupported time type: {datatype:?}")] +pub struct UnsupportedTimeType { + pub datatype: ArrowDatatype, +} + +/// Describes a time column, such as `log_time`. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TimeColumnDescriptor { + /// The timeline this column is associated with. + pub timeline: Timeline, + + /// The Arrow datatype of the column. + pub datatype: ArrowDatatype, +} + +impl PartialOrd for TimeColumnDescriptor { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for TimeColumnDescriptor { + #[inline] + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + let Self { + timeline, + datatype: _, + } = self; + timeline.cmp(&other.timeline) + } +} + +impl TimeColumnDescriptor { + /// Used when returning a null column, i.e. when a lookup failed. + #[inline] + pub fn new_null(name: TimelineName) -> Self { + Self { + // TODO(cmc): I picked a sequence here because I have to pick something. + // It doesn't matter, only the name will remain in the Arrow schema anyhow. + timeline: Timeline::new_sequence(name), + datatype: ArrowDatatype::Null, + } + } + + #[inline] + pub fn timeline(&self) -> Timeline { + self.timeline + } + + #[inline] + pub fn name(&self) -> &TimelineName { + self.timeline.name() + } + + #[inline] + pub fn typ(&self) -> re_log_types::TimeType { + self.timeline.typ() + } + + #[inline] + pub fn datatype(&self) -> &ArrowDatatype { + &self.datatype + } + + #[inline] + pub fn to_arrow_field(&self) -> ArrowField { + let Self { timeline, datatype } = self; + + let nullable = true; // Time column must be nullable since static data doesn't have a time. + + let metadata = std::iter::once(Some(( + "sorbet.index_name".to_owned(), + timeline.name().to_string(), + ))) + .flatten() + .collect(); + + ArrowField::new(timeline.name().to_string(), datatype.clone(), nullable) + .with_metadata(metadata) + } +} + +impl From for TimeColumnDescriptor { + fn from(timeline: Timeline) -> Self { + Self { + timeline, + datatype: timeline.datatype(), + } + } +} + +impl TryFrom<&ArrowField> for TimeColumnDescriptor { + type Error = UnsupportedTimeType; + + fn try_from(field: &ArrowField) -> Result { + let name = if let Some(name) = field.metadata().get("sorbet.index_name") { + name.to_owned() + } else { + re_log::warn_once!("Timeline '{}' is missing 'sorbet.index_name' metadata. Falling back on field/column name", field.name()); + field.name().to_owned() + }; + + let datatype = field.data_type().clone(); + + let Some(time_type) = re_log_types::TimeType::from_arrow_datatype(&datatype) else { + return Err(UnsupportedTimeType { datatype }); + }; + + let timeline = Timeline::new(name, time_type); + + Ok(Self { timeline, datatype }) + } +} diff --git a/crates/store/re_sorbet/src/lib.rs b/crates/store/re_sorbet/src/lib.rs new file mode 100644 index 0000000000000..4d2495dbb5152 --- /dev/null +++ b/crates/store/re_sorbet/src/lib.rs @@ -0,0 +1,16 @@ +//! Rerun arrow metadata and record batch definitions. +//! +//! Handles the structure of arrow record batches and their meta data for different use cases for Rerun. + +mod data_column_schema; +mod index_column_schema; +mod metadata; + +pub use self::{ + data_column_schema::ComponentColumnDescriptor, + index_column_schema::TimeColumnDescriptor, + metadata::{ + ArrowBatchMetadata, ArrowFieldMetadata, MetadataExt, MissingFieldMetadata, + MissingMetadataKey, + }, +}; diff --git a/crates/store/re_sorbet/src/metadata.rs b/crates/store/re_sorbet/src/metadata.rs new file mode 100644 index 0000000000000..fe21a0df7ea65 --- /dev/null +++ b/crates/store/re_sorbet/src/metadata.rs @@ -0,0 +1,69 @@ +use std::collections::HashMap; + +use arrow::datatypes::Field as ArrowField; + +/// Arrow metadata for an arrow record batch. +pub type ArrowBatchMetadata = HashMap; + +/// Arrow metadata for a column/field. +pub type ArrowFieldMetadata = HashMap; + +#[derive(thiserror::Error, Debug)] +#[error("Missing metadata {key:?}")] +pub struct MissingMetadataKey { + pub key: String, +} + +#[derive(thiserror::Error, Debug)] +#[error("Field {field_name:?} is missing metadata {metadata_key:?}")] +pub struct MissingFieldMetadata { + pub field_name: String, + pub metadata_key: String, +} + +/// Make it more ergonomic to work with arrow metadata. +pub trait MetadataExt { + type Error; + + fn missing_key_error(&self, key: &str) -> Self::Error; + fn get_opt(&self, key: &str) -> Option<&str>; + + fn get_or_err(&self, key: &str) -> Result<&str, Self::Error> { + self.get_opt(key).ok_or_else(|| self.missing_key_error(key)) + } + + fn get_bool(&self, key: &str) -> bool { + self.get_opt(key) + .map(|value| !matches!(value.to_lowercase().as_str(), "false" | "no")) + .unwrap_or(false) + } +} + +impl MetadataExt for HashMap { + type Error = MissingMetadataKey; + + fn missing_key_error(&self, key: &str) -> Self::Error { + MissingMetadataKey { + key: key.to_owned(), + } + } + + fn get_opt(&self, key: &str) -> Option<&str> { + self.get(key).map(|value| value.as_str()) + } +} + +impl MetadataExt for ArrowField { + type Error = MissingFieldMetadata; + + fn missing_key_error(&self, key: &str) -> Self::Error { + MissingFieldMetadata { + field_name: self.name().clone(), + metadata_key: key.to_owned(), + } + } + + fn get_opt(&self, key: &str) -> Option<&str> { + self.metadata().get(key).map(|v| v.as_str()) + } +} diff --git a/rerun_py/src/arrow.rs b/rerun_py/src/arrow.rs index 9ffaad4c54d9e..271beda23cec1 100644 --- a/rerun_py/src/arrow.rs +++ b/rerun_py/src/arrow.rs @@ -107,15 +107,11 @@ pub fn build_chunk_from_components( .into_iter() .zip(timeline_names) .map(|(array, timeline_name)| { - let timeline = match array.data_type() { - arrow::datatypes::DataType::Int64 => Ok(Timeline::new_sequence(timeline_name)), - arrow::datatypes::DataType::Timestamp(_, _) => { - Ok(Timeline::new_temporal(timeline_name)) - } - _ => Err(ChunkError::Malformed { + let time_type = re_log_types::TimeType::from_arrow_datatype(array.data_type()) + .ok_or_else(|| ChunkError::Malformed { reason: format!("Invalid data_type for timeline: {timeline_name}"), - }), - }?; + })?; + let timeline = Timeline::new(timeline_name, time_type); let timeline_data = TimeColumn::read_array(&ArrowArrayRef::from(array)).map_err(|err| { ChunkError::Malformed { From 8f5cbe1959be05d613555d4541a553ffdd7d69e7 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 27 Jan 2025 10:29:01 +0100 Subject: [PATCH 03/43] Rust: remove legacy `send_columns` and update everything left (#8804) Title. --- .../re_types/src/archetypes/asset_video.rs | 9 ++-- .../store/re_types/src/archetypes/points3d.rs | 2 +- .../store/re_types/src/archetypes/scalar.rs | 2 +- .../src/archetypes/video_frame_reference.rs | 9 ++-- crates/top/re_sdk/src/recording_stream.rs | 49 +------------------ .../all/archetypes/image_send_columns.rs | 37 ++++++-------- .../all/archetypes/points3d_send_columns.rs | 2 +- .../all/archetypes/scalar_send_columns.rs | 2 +- .../all/archetypes/video_auto_frames.rs | 9 ++-- .../all/howto/any_batch_value_send_columns.rs | 2 +- .../all/howto/any_values_send_columns.rs | 2 +- examples/rust/incremental_logging/src/main.rs | 34 ++++++++----- tests/rust/plot_dashboard_stress/src/main.rs | 8 ++- tests/rust/test_temporal_batch/src/main.rs | 22 ++++----- 14 files changed, 68 insertions(+), 121 deletions(-) diff --git a/crates/store/re_types/src/archetypes/asset_video.rs b/crates/store/re_types/src/archetypes/asset_video.rs index 500c337ea1991..af28237a56632 100644 --- a/crates/store/re_types/src/archetypes/asset_video.rs +++ b/crates/store/re_types/src/archetypes/asset_video.rs @@ -59,14 +59,13 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// // Note timeline values don't have to be the same as the video timestamps. /// frame_timestamps_ns, /// ); -/// let frame_reference_indicators = -/// ::Indicator::new_array( -/// time_column.num_rows(), -/// ); +/// /// rec.send_columns( /// "video", /// [time_column], -/// [&frame_reference_indicators as _, &video_timestamps_ns as _], +/// rerun::VideoFrameReference::update_fields() +/// .with_many_timestamp(video_timestamps_ns) +/// .columns_of_unit_batches()?, /// )?; /// /// Ok(()) diff --git a/crates/store/re_types/src/archetypes/points3d.rs b/crates/store/re_types/src/archetypes/points3d.rs index f69d4dca5cd78..57f9fd59cb7a0 100644 --- a/crates/store/re_types/src/archetypes/points3d.rs +++ b/crates/store/re_types/src/archetypes/points3d.rs @@ -127,7 +127,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .with_radii(radii) /// .columns_of_unit_batches()?; /// -/// rec.send_columns_v2("points", [times], position.chain(color_and_radius))?; +/// rec.send_columns("points", [times], position.chain(color_and_radius))?; /// /// Ok(()) /// } diff --git a/crates/store/re_types/src/archetypes/scalar.rs b/crates/store/re_types/src/archetypes/scalar.rs index 352e73ba8dd11..cbcb1ad1f00d5 100644 --- a/crates/store/re_types/src/archetypes/scalar.rs +++ b/crates/store/re_types/src/archetypes/scalar.rs @@ -66,7 +66,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// let times = TimeColumn::new_sequence("step", 0..STEPS); /// let scalars = (0..STEPS).map(|step| (step as f64 / 10.0).sin()); /// -/// rec.send_columns_v2( +/// rec.send_columns( /// "scalars", /// [times], /// rerun::Scalar::update_fields() diff --git a/crates/store/re_types/src/archetypes/video_frame_reference.rs b/crates/store/re_types/src/archetypes/video_frame_reference.rs index da3a72e2c507c..ba333b4b89d9b 100644 --- a/crates/store/re_types/src/archetypes/video_frame_reference.rs +++ b/crates/store/re_types/src/archetypes/video_frame_reference.rs @@ -57,14 +57,13 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// // Note timeline values don't have to be the same as the video timestamps. /// frame_timestamps_ns, /// ); -/// let frame_reference_indicators = -/// ::Indicator::new_array( -/// time_column.num_rows(), -/// ); +/// /// rec.send_columns( /// "video", /// [time_column], -/// [&frame_reference_indicators as _, &video_timestamps_ns as _], +/// rerun::VideoFrameReference::update_fields() +/// .with_many_timestamp(video_timestamps_ns) +/// .columns_of_unit_batches()?, /// )?; /// /// Ok(()) diff --git a/crates/top/re_sdk/src/recording_stream.rs b/crates/top/re_sdk/src/recording_stream.rs index fef81b467d02f..1b63d51d6e82d 100644 --- a/crates/top/re_sdk/src/recording_stream.rs +++ b/crates/top/re_sdk/src/recording_stream.rs @@ -983,53 +983,6 @@ impl RecordingStream { self.log_with_static(ent_path, false, as_components) } - /// Lower-level logging API to provide data spanning multiple timepoints. - /// - /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data - /// in a columnar form. The lengths of all of the [`TimeColumn`] and the component batches - /// must match. All data that occurs at the same index across the different time and components - /// arrays will act as a single logical row. - /// - /// Note that this API ignores any stateful time set on the log stream via the - /// [`Self::set_timepoint`]/[`Self::set_time_nanos`]/etc. APIs. - /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. - /// - /// TODO(#7167): Unlike Python and C++, this API does not yet support arbitrary partitions of the incoming - /// component arrays. Each component will be individually associated with a single timepoint, rather - /// than offering how big the component arrays are that are associated with each timepoint. - #[inline] - pub fn send_columns<'a>( - &self, - ent_path: impl Into, - timelines: impl IntoIterator, - components: impl IntoIterator, - ) -> RecordingStreamResult<()> { - let id = ChunkId::new(); - - let timelines = timelines - .into_iter() - .map(|timeline| (*timeline.timeline(), timeline)) - .collect::>(); - - let components: Result, ChunkError> = components - .into_iter() - .map(|batch| { - Ok(( - batch.descriptor().into_owned(), - batch.to_arrow_list_array()?, - )) - }) - .collect(); - - let components: ChunkComponents = components?.into_iter().collect(); - - let chunk = Chunk::from_auto_row_ids(id, ent_path.into(), timelines, components)?; - - self.send_chunk(chunk); - - Ok(()) - } - /// Lower-level logging API to provide data spanning multiple timepoints. /// /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data @@ -1040,7 +993,7 @@ impl RecordingStream { /// Note that this API ignores any stateful time set on the log stream via the /// [`Self::set_timepoint`]/[`Self::set_time_nanos`]/etc. APIs. /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. - pub fn send_columns_v2( + pub fn send_columns( &self, ent_path: impl Into, indexes: impl IntoIterator, diff --git a/docs/snippets/all/archetypes/image_send_columns.rs b/docs/snippets/all/archetypes/image_send_columns.rs index 73ed177259fd1..a157ced265629 100644 --- a/docs/snippets/all/archetypes/image_send_columns.rs +++ b/docs/snippets/all/archetypes/image_send_columns.rs @@ -1,5 +1,4 @@ use ndarray::{s, Array, ShapeBuilder}; -use rerun::Archetype as _; fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_image_send_columns").spawn()?; @@ -21,33 +20,27 @@ fn main() -> Result<(), Box> { .fill(255); } - // Log the ImageFormat and indicator once, as static. + // Send the ImageFormat and indicator once, as static. let format = rerun::components::ImageFormat::rgb8([width as _, height as _]); - rec.log_static( + rec.send_columns( "images", - &[ - &format as &dyn rerun::ComponentBatch, - &rerun::Image::indicator(), - ], + [], + rerun::Image::update_fields() + .with_format(format) + .columns_of_unit_batches()?, )?; // Split up the image data into several components referencing the underlying data. let image_size_in_bytes = width * height * 3; - let blob = rerun::datatypes::Blob::from(images.into_raw_vec_and_offset().0); - let image_column = times - .iter() - .map(|&t| { - let byte_offset = image_size_in_bytes * (t as usize); - rerun::components::ImageBuffer::from( - blob.clone() // Clone is only a reference count increase, not a full copy. - .sliced(byte_offset..(byte_offset + image_size_in_bytes)), - ) - }) - .collect::>(); - - // Send all images at once. - let timeline_values = rerun::TimeColumn::new_sequence("step", times); - rec.send_columns("images", [timeline_values], [&image_column as _])?; + let timeline_values = rerun::TimeColumn::new_sequence("step", times.clone()); + let buffer = images.into_raw_vec_and_offset().0; + rec.send_columns( + "images", + [timeline_values], + rerun::Image::update_fields() + .with_many_buffer(buffer.chunks(image_size_in_bytes)) + .columns_of_unit_batches()?, + )?; Ok(()) } diff --git a/docs/snippets/all/archetypes/points3d_send_columns.rs b/docs/snippets/all/archetypes/points3d_send_columns.rs index c842ee3bd45d9..3e7a1521bc9e8 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.rs +++ b/docs/snippets/all/archetypes/points3d_send_columns.rs @@ -30,7 +30,7 @@ fn main() -> Result<(), Box> { .with_radii(radii) .columns_of_unit_batches()?; - rec.send_columns_v2("points", [times], position.chain(color_and_radius))?; + rec.send_columns("points", [times], position.chain(color_and_radius))?; Ok(()) } diff --git a/docs/snippets/all/archetypes/scalar_send_columns.rs b/docs/snippets/all/archetypes/scalar_send_columns.rs index 1e830e7d2d9c1..1898f8b33fac1 100644 --- a/docs/snippets/all/archetypes/scalar_send_columns.rs +++ b/docs/snippets/all/archetypes/scalar_send_columns.rs @@ -10,7 +10,7 @@ fn main() -> Result<(), Box> { let times = TimeColumn::new_sequence("step", 0..STEPS); let scalars = (0..STEPS).map(|step| (step as f64 / 10.0).sin()); - rec.send_columns_v2( + rec.send_columns( "scalars", [times], rerun::Scalar::update_fields() diff --git a/docs/snippets/all/archetypes/video_auto_frames.rs b/docs/snippets/all/archetypes/video_auto_frames.rs index df52ccda0ef29..35867e80f93b8 100644 --- a/docs/snippets/all/archetypes/video_auto_frames.rs +++ b/docs/snippets/all/archetypes/video_auto_frames.rs @@ -29,14 +29,13 @@ fn main() -> anyhow::Result<()> { // Note timeline values don't have to be the same as the video timestamps. frame_timestamps_ns, ); - let frame_reference_indicators = - ::Indicator::new_array( - time_column.num_rows(), - ); + rec.send_columns( "video", [time_column], - [&frame_reference_indicators as _, &video_timestamps_ns as _], + rerun::VideoFrameReference::update_fields() + .with_many_timestamp(video_timestamps_ns) + .columns_of_unit_batches()?, )?; Ok(()) diff --git a/docs/snippets/all/howto/any_batch_value_send_columns.rs b/docs/snippets/all/howto/any_batch_value_send_columns.rs index 7bf2962083455..51f53353fe6ea 100644 --- a/docs/snippets/all/howto/any_batch_value_send_columns.rs +++ b/docs/snippets/all/howto/any_batch_value_send_columns.rs @@ -28,7 +28,7 @@ fn main() -> Result<(), Box> { rerun::ComponentDescriptor::new("custom_component_multi"), ); - rec.send_columns_v2( + rec.send_columns( "/", [times], [ diff --git a/docs/snippets/all/howto/any_values_send_columns.rs b/docs/snippets/all/howto/any_values_send_columns.rs index f824409081e1e..22c8db3794e17 100644 --- a/docs/snippets/all/howto/any_values_send_columns.rs +++ b/docs/snippets/all/howto/any_values_send_columns.rs @@ -28,7 +28,7 @@ fn main() -> Result<(), Box> { rerun::ComponentDescriptor::new("cos"), ); - rec.send_columns_v2( + rec.send_columns( "/", [times], [ diff --git a/examples/rust/incremental_logging/src/main.rs b/examples/rust/incremental_logging/src/main.rs index c3eddb675dae8..6d74d300b0f05 100644 --- a/examples/rust/incremental_logging/src/main.rs +++ b/examples/rust/incremental_logging/src/main.rs @@ -33,12 +33,15 @@ This example showcases how to incrementally log data belonging to the same arche It was logged with the following code: ```rust -let colors = [rerun::Color::from_rgb(255, 0, 0); 10]; -let radii = [rerun::Radius(0.1); 10]; - // Only log colors and radii once. +// Logging statically would also work (i.e. `log_static`). rec.set_time_sequence("frame_nr", 0); -rec.log("points", &[&colors as &dyn rerun::ComponentBatch, &radii])?; +rec.log( + "points", + &rerun::Points3D::update_fields() + .with_colors([(255, 0, 0)]) + .with_radii([0.1]), +)?; let mut rng = rand::thread_rng(); let dist = Uniform::new(-5., 5.); @@ -48,7 +51,13 @@ let dist = Uniform::new(-5., 5.); // They will automatically re-use the colors and radii logged at the beginning. for i in 0..10 { rec.set_time_sequence("frame_nr", i); - rec.log("points", &rerun::Points3D::new((0..10).map(|_| (rng.sample(dist), rng.sample(dist), rng.sample(dist)))))?; + + rec.log( + "points", + &rerun::Points3D::update_fields().with_positions( + (0..10).map(|_| (rng.sample(dist), rng.sample(dist), rng.sample(dist))), + ), + )?; } ``` @@ -58,14 +67,15 @@ Move the time cursor around, and notice how the colors and radii from frame 0 ar fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { rec.log_static("readme", &rerun::TextDocument::from_markdown(README))?; - let colors = [rerun::Color::from_rgb(255, 0, 0)]; - let radii = [rerun::Radius::from(0.1)]; - // Only log colors and radii once. + // Logging statically would also work (i.e. `log_static`). rec.set_time_sequence("frame_nr", 0); - rec.log("points", &[&colors as &dyn rerun::ComponentBatch, &radii])?; - // Logging statically would also work. - // rec.log_static("points", &[&colors as &dyn rerun::ComponentBatch, &radii])?; + rec.log( + "points", + &rerun::Points3D::update_fields() + .with_colors([(255, 0, 0)]) + .with_radii([0.1]), + )?; let mut rng = rand::thread_rng(); let dist = Uniform::new(-5., 5.); @@ -78,7 +88,7 @@ fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { rec.log( "points", - &rerun::Points3D::new( + &rerun::Points3D::update_fields().with_positions( (0..10).map(|_| (rng.sample(dist), rng.sample(dist), rng.sample(dist))), ), )?; diff --git a/tests/rust/plot_dashboard_stress/src/main.rs b/tests/rust/plot_dashboard_stress/src/main.rs index e7ef626c1564b..6cee6c8abcb0f 100644 --- a/tests/rust/plot_dashboard_stress/src/main.rs +++ b/tests/rust/plot_dashboard_stress/src/main.rs @@ -153,11 +153,9 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { rec.send_columns( path, [rerun::TimeColumn::new_seconds("sim_time", seconds.copied())], - [&values - .copied() - .map(Into::into) - .collect::>() - as _], + rerun::Scalar::update_fields() + .with_many_scalar(values.copied()) + .columns_of_unit_batches()?, )?; } else { rec.log(path, &rerun::Scalar::new(series_values[offset]))?; diff --git a/tests/rust/test_temporal_batch/src/main.rs b/tests/rust/test_temporal_batch/src/main.rs index 5d10364c3cdbf..513f657c0897e 100644 --- a/tests/rust/test_temporal_batch/src/main.rs +++ b/tests/rust/test_temporal_batch/src/main.rs @@ -1,24 +1,20 @@ //! Very minimal test of using the send columns APIs. use re_chunk::TimeColumn; -use rerun::components::Scalar; fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_send_columns").spawn()?; - // Native time / scalars - let timeline_values = (0..64).collect::>(); + let timeline_values = TimeColumn::new_sequence("step", 0..64); + let scalar_data = (0..64).map(|step| (step as f64 / 10.0).sin()); - let scalar_data: Vec = timeline_values - .iter() - .map(|step| (*step as f64 / 10.0).sin()) - .collect(); - - // Convert to rerun time / scalars - let timeline_values = TimeColumn::new_sequence("step", timeline_values); - let scalar_data: Vec = scalar_data.into_iter().map(Into::into).collect(); - - rec.send_columns("scalar", [timeline_values], [&scalar_data as _])?; + rec.send_columns( + "scalar", + [timeline_values], + rerun::Scalar::update_fields() + .with_many_scalar(scalar_data) + .columns_of_unit_batches()?, + )?; Ok(()) } From 84405e75f03c5b0d2387fb59e4791f652acb659a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 27 Jan 2025 10:35:45 +0100 Subject: [PATCH 04/43] Tagged columnar updates: Python (#8792) Implements everything needed for the new tagged `send_columns` in Python. This includes taking care of interactions with indicators, mono-components, etc. ```py def send_columns_v2( entity_path: str, indexes: Iterable[TimeColumnLike], columns: Iterable[ComponentColumn], recording: RecordingStream | None = None, strict: bool | None = None, ) -> None: ``` Points (multi-component): ```py # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off positions = [ [1.0, 0.0, 1.0], [0.5, 0.5, 2.0], [1.5, -0.5, 1.5], [1.0, 1.0, 2.5], [-0.5, 1.5, 1.0], [-1.5, 0.0, 2.0], [2.0, 0.0, 2.0], [1.5, -1.5, 3.0], [0.0, -2.0, 2.5], [1.0, -1.0, 3.5], [-2.0, 0.0, 2.0], [-1.5, 1.5, 3.0], [-1.0, 1.0, 3.5], [1.0, -1.0, 1.0], [2.0, -2.0, 2.0], [3.0, -1.0, 3.0], [2.0, 0.0, 4.0], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] rr.send_columns_v2( "points", indexes=[rr.TimeSecondsColumn("time", times)], columns=[ *rr.Points3D.columns(positions=positions).partition(lengths=[2, 4, 4, 3, 4]), *rr.Points3D.columns(colors=colors, radii=radii), ], ) ``` Scalar (mono-component): ```py times = np.arange(0, 64) scalars = np.sin(times / 10.0) rr.send_columns_v2( "scalars", indexes=[rr.TimeSequenceColumn("step", times)], columns=rr.Scalar.columns(scalar=scalars), ) ``` Custom data: ```py timestamps = np.arange(0, 64) # Log two component columns, named "sin" and "cos", with the corresponding values rr.send_columns_v2( "/", indexes=[rr.TimeSequenceColumn("step", timestamps)], columns=rr.AnyValues.columns(sin=np.sin(timestamps / 10.0), cos=np.cos(timestamps / 10.0)), ) ``` * Fixes #8752 --------- Co-authored-by: Antoine Beyeler --- .../src/codegen/python/mod.rs | 122 ++++++++++++++-- crates/build/re_types_builder/src/objects.rs | 62 ++++++++ docs/snippets/INDEX.md | 3 - .../all/archetypes/points3d_send_columns.py | 14 +- .../all/archetypes/scalar_send_columns.py | 6 +- .../all/howto/any_batch_value_send_columns.py | 10 +- .../all/howto/any_values_send_columns.py | 13 +- docs/snippets/snippets.toml | 2 - rerun_py/rerun_sdk/rerun/__init__.py | 2 + rerun_py/rerun_sdk/rerun/_baseclasses.py | 137 ++++++++++++++++-- rerun_py/rerun_sdk/rerun/_send_columns.py | 87 ++++++++++- rerun_py/rerun_sdk/rerun/any_value.py | 114 +++++++++++++-- .../rerun/archetypes/annotation_context.py | 42 ++++++ .../rerun_sdk/rerun/archetypes/arrows2d.py | 82 +++++++++++ .../rerun_sdk/rerun/archetypes/arrows3d.py | 76 ++++++++++ .../rerun_sdk/rerun/archetypes/asset3d.py | 62 ++++++++ .../rerun_sdk/rerun/archetypes/asset_video.py | 52 +++++++ .../rerun_sdk/rerun/archetypes/bar_chart.py | 46 ++++++ .../rerun_sdk/rerun/archetypes/boxes2d.py | 79 ++++++++++ .../rerun_sdk/rerun/archetypes/boxes3d.py | 92 ++++++++++++ .../rerun_sdk/rerun/archetypes/capsules3d.py | 85 +++++++++++ rerun_py/rerun_sdk/rerun/archetypes/clear.py | 36 +++++ .../rerun_sdk/rerun/archetypes/depth_image.py | 92 ++++++++++++ .../rerun/archetypes/ellipsoids3d.py | 91 ++++++++++++ .../rerun/archetypes/encoded_image.py | 65 +++++++++ .../rerun/archetypes/geo_line_strings.py | 56 +++++++ .../rerun_sdk/rerun/archetypes/geo_points.py | 61 ++++++++ .../rerun_sdk/rerun/archetypes/graph_edges.py | 48 ++++++ .../rerun_sdk/rerun/archetypes/graph_nodes.py | 62 ++++++++ rerun_py/rerun_sdk/rerun/archetypes/image.py | 58 ++++++++ .../rerun/archetypes/instance_poses3d.py | 58 ++++++++ .../rerun/archetypes/line_strips2d.py | 73 ++++++++++ .../rerun/archetypes/line_strips3d.py | 67 +++++++++ rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py | 83 +++++++++++ .../rerun_sdk/rerun/archetypes/pinhole.py | 89 ++++++++++++ .../rerun_sdk/rerun/archetypes/points2d.py | 87 +++++++++++ .../rerun_sdk/rerun/archetypes/points3d.py | 95 ++++++++++-- rerun_py/rerun_sdk/rerun/archetypes/scalar.py | 45 +++++- .../rerun/archetypes/segmentation_image.py | 58 ++++++++ .../rerun_sdk/rerun/archetypes/series_line.py | 60 ++++++++ .../rerun/archetypes/series_point.py | 56 +++++++ rerun_py/rerun_sdk/rerun/archetypes/tensor.py | 56 +++++++ .../rerun/archetypes/text_document.py | 52 +++++++ .../rerun_sdk/rerun/archetypes/text_log.py | 52 +++++++ .../rerun_sdk/rerun/archetypes/transform3d.py | 69 +++++++++ .../rerun/archetypes/video_frame_reference.py | 61 ++++++++ .../rerun/archetypes/view_coordinates.py | 42 ++++++ .../test_types/archetypes/affix_fuzzer1.py | 78 ++++++++++ .../test_types/archetypes/affix_fuzzer2.py | 72 +++++++++ .../test_types/archetypes/affix_fuzzer3.py | 70 +++++++++ .../test_types/archetypes/affix_fuzzer4.py | 70 +++++++++ 51 files changed, 3056 insertions(+), 94 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/python/mod.rs b/crates/build/re_types_builder/src/codegen/python/mod.rs index f4a1a30d2f4fd..c1b855ab6b411 100644 --- a/crates/build/re_types_builder/src/codegen/python/mod.rs +++ b/crates/build/re_types_builder/src/codegen/python/mod.rs @@ -408,8 +408,11 @@ impl PythonCodeGenerator { Archetype, BaseBatch, ComponentBatchMixin, + ComponentColumn, + ComponentColumnList, ComponentDescriptor, ComponentMixin, + DescribedComponentBatch, ) from {rerun_path}_converters import ( int_or_none, @@ -695,6 +698,9 @@ fn code_for_struct( if obj.kind == ObjectKind::Archetype { code.push_indented(1, quote_clear_methods(obj), 2); code.push_indented(1, quote_partial_update_methods(reporter, obj, objects), 2); + if obj.scope().is_none() { + code.push_indented(1, quote_columnar_methods(reporter, obj, objects), 2); + } } if obj.is_delegating_component() { @@ -2511,7 +2517,8 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj quote_init_parameter_from_field(&field, objects, &obj.fqname) }) .collect_vec() - .join(", "); + .join(",\n"); + let parameters = indent::indent_by(8, parameters); let kwargs = obj .fields @@ -2521,7 +2528,8 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj format!("'{field_name}': {field_name}") }) .collect_vec() - .join(", "); + .join(",\n"); + let kwargs = indent::indent_by(12, kwargs); let parameter_docs = compute_init_parameter_docs(reporter, obj, objects); let mut doc_string_lines = vec![format!("Update only some specific fields of a `{name}`.")]; @@ -2536,11 +2544,7 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj doc_string_lines.push(doc); } }; - let doc_block = quote_doc_lines(doc_string_lines) - .lines() - .map(|line| format!(" {line}")) - .collect_vec() - .join("\n"); + let doc_block = indent::indent_by(12, quote_doc_lines(doc_string_lines)); let field_clears = obj .fields @@ -2550,8 +2554,8 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj format!("{field_name}=[],") }) .collect_vec() - .join("\n "); - let field_clears = indent::indent_by(4, field_clears); + .join("\n"); + let field_clears = indent::indent_by(12, field_clears); unindent(&format!( r#" @@ -2562,20 +2566,19 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj clear: bool = False, {parameters}, ) -> {name}: - -{doc_block} + {doc_block} inst = cls.__new__(cls) with catch_and_log_exceptions(context=cls.__name__): kwargs = {{ {kwargs}, }} - + if clear: kwargs = {{k: v if v is not None else [] for k, v in kwargs.items()}} # type: ignore[misc] - + inst.__attrs_init__(**kwargs) return inst - + inst.__attrs_clear__() return inst @@ -2591,6 +2594,97 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj )) } +fn quote_columnar_methods(reporter: &Reporter, obj: &Object, objects: &Objects) -> String { + let parameters = obj + .fields + .iter() + .filter_map(|field| { + let mut field = field.make_plural()?; + field.is_nullable = true; + Some(quote_init_parameter_from_field( + &field, + objects, + &obj.fqname, + )) + }) + .collect_vec() + .join(",\n"); + let parameters = indent::indent_by(8, parameters); + + let init_args = obj + .fields + .iter() + .map(|field| { + let field_name = field.snake_case_name(); + format!("{field_name}={field_name}") + }) + .collect_vec() + .join(",\n"); + let init_args = indent::indent_by(12, init_args); + + let parameter_docs = compute_init_parameter_docs(reporter, obj, objects); + let doc = unindent( + "\ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + ", + ); + let mut doc_string_lines = doc.lines().map(|s| s.to_owned()).collect_vec(); + if !parameter_docs.is_empty() { + doc_string_lines.push("Parameters".to_owned()); + doc_string_lines.push("----------".to_owned()); + for doc in parameter_docs { + doc_string_lines.push(doc); + } + }; + let doc_block = indent::indent_by(12, quote_doc_lines(doc_string_lines)); + + // NOTE(#8768): Scalar indicators are extremely wasteful, and not actually used for anything. + let has_indicator = obj.fqname.as_str() != "rerun.archetypes.Scalar"; + let pack_and_return = if has_indicator { + indent::indent_by(12, unindent("\ + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + ")) + } else { + "return ComponentColumnList(columns)".to_owned() + }; + + // NOTE: Calling `update_fields` is not an option: we need to be able to pass + // plural data, even to singular fields (mono-components). + unindent(&format!( + r#" + @classmethod + def columns( + cls, + *, + {parameters}, + ) -> ComponentColumnList: + {doc_block} + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + {init_args}, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + {pack_and_return} + "# + )) +} + // --- Arrow registry code generators --- use arrow2::datatypes::{DataType, Field, UnionMode}; diff --git a/crates/build/re_types_builder/src/objects.rs b/crates/build/re_types_builder/src/objects.rs index f2b89db7260a9..6bb3b2eafb829 100644 --- a/crates/build/re_types_builder/src/objects.rs +++ b/crates/build/re_types_builder/src/objects.rs @@ -947,6 +947,13 @@ impl ObjectField { None } } + + pub fn make_plural(&self) -> Option { + self.typ.make_plural().map(|typ| Self { + typ, + ..self.clone() + }) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -1113,6 +1120,61 @@ impl Type { } } + pub fn make_plural(&self) -> Option { + match self { + Self::Vector { elem_type: _ } + | Self::Array { + elem_type: _, + length: _, + } => Some(self.clone()), + + Self::UInt8 => Some(Self::Vector { + elem_type: ElementType::UInt8, + }), + Self::UInt16 => Some(Self::Vector { + elem_type: ElementType::UInt16, + }), + Self::UInt32 => Some(Self::Vector { + elem_type: ElementType::UInt32, + }), + Self::UInt64 => Some(Self::Vector { + elem_type: ElementType::UInt64, + }), + Self::Int8 => Some(Self::Vector { + elem_type: ElementType::Int8, + }), + Self::Int16 => Some(Self::Vector { + elem_type: ElementType::Int16, + }), + Self::Int32 => Some(Self::Vector { + elem_type: ElementType::Int32, + }), + Self::Int64 => Some(Self::Vector { + elem_type: ElementType::Int64, + }), + Self::Bool => Some(Self::Vector { + elem_type: ElementType::Bool, + }), + Self::Float16 => Some(Self::Vector { + elem_type: ElementType::Float16, + }), + Self::Float32 => Some(Self::Vector { + elem_type: ElementType::Float32, + }), + Self::Float64 => Some(Self::Vector { + elem_type: ElementType::Float64, + }), + Self::String => Some(Self::Vector { + elem_type: ElementType::String, + }), + Self::Object(obj) => Some(Self::Vector { + elem_type: ElementType::Object(obj.clone()), + }), + + Self::Unit => None, + } + } + /// True if this is some kind of array/vector. pub fn is_plural(&self) -> bool { self.plural_inner().is_some() diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index cb57647e7f304..73583a94719c1 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -211,7 +211,6 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes⁠/⁠segmentation_image_simple` | Create and log a segmentation image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.cpp) | | **[`ClassId`](https://rerun.io/docs/reference/types/components/class_id)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `archetypes⁠/⁠points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠viscomp-component-default` | Add a component default | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-component-default.py) | | | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠viscomp-component-override` | Override a component | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-component-override.py) | | | @@ -234,7 +233,6 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`Plane3D`](https://rerun.io/docs/reference/types/components/plane3d)** | `views⁠/⁠spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes⁠/⁠mesh3d_partial_updates` | Log a simple colored triangle, then update its vertices' positions each frame | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes⁠/⁠points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors⁠/⁠descr_builtin_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors⁠/⁠descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors⁠/⁠descr_custom_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.cpp) | @@ -245,7 +243,6 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠geo_line_strings_simple` | Log a simple geospatial line string | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠geo_points_simple` | Log some very simple geospatial point | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `concepts⁠/⁠different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `views⁠/⁠map` | Use a blueprint to customize a map view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/map.py) | | | | **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠capsules3d_batch` | Log a batch of capsules | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.cpp) | diff --git a/docs/snippets/all/archetypes/points3d_send_columns.py b/docs/snippets/all/archetypes/points3d_send_columns.py index 2117c22c2e2df..5d4d90c793792 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.py +++ b/docs/snippets/all/archetypes/points3d_send_columns.py @@ -18,20 +18,16 @@ [1.0, -1.0, 1.0], [2.0, -2.0, 2.0], [3.0, -1.0, 3.0], [2.0, 0.0, 4.0], ] # fmt: on -positions_arr = np.concatenate(positions) # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] -# TODO(#8752): use tagged columnar APIs -rr.send_columns( +rr.send_columns_v2( "points", - times=[rr.TimeSecondsColumn("time", times)], - components=[ - rr.Points3D.indicator(), - rr.components.Position3DBatch(positions_arr).partition([2, 4, 4, 3, 4]), - rr.components.ColorBatch(colors), - rr.components.RadiusBatch(radii), + indexes=[rr.TimeSecondsColumn("time", times)], + columns=[ + *rr.Points3D.columns(positions=positions).partition(lengths=[2, 4, 4, 3, 4]), + *rr.Points3D.columns(colors=colors, radii=radii), ], ) diff --git a/docs/snippets/all/archetypes/scalar_send_columns.py b/docs/snippets/all/archetypes/scalar_send_columns.py index ec2f51e9e0f08..0f1e789fe9eba 100644 --- a/docs/snippets/all/archetypes/scalar_send_columns.py +++ b/docs/snippets/all/archetypes/scalar_send_columns.py @@ -10,8 +10,8 @@ times = np.arange(0, 64) scalars = np.sin(times / 10.0) -rr.send_columns( +rr.send_columns_v2( "scalars", - times=[rr.TimeSequenceColumn("step", times)], - components=[rr.components.ScalarBatch(scalars)], + indexes=[rr.TimeSequenceColumn("step", times)], + columns=rr.Scalar.columns(scalar=scalars), ) diff --git a/docs/snippets/all/howto/any_batch_value_send_columns.py b/docs/snippets/all/howto/any_batch_value_send_columns.py index 5719eac824064..640cc2b03c3a3 100644 --- a/docs/snippets/all/howto/any_batch_value_send_columns.py +++ b/docs/snippets/all/howto/any_batch_value_send_columns.py @@ -12,13 +12,13 @@ one_per_timestamp = np.sin(timestamps / 10.0) ten_per_timestamp = np.cos(np.arange(0, N * 10) / 100.0) -rr.send_columns( +rr.send_columns_v2( "/", - times=[rr.TimeSequenceColumn("step", timestamps)], - components=[ + indexes=[rr.TimeSequenceColumn("step", timestamps)], + columns=[ # log one value per timestamp - rr.AnyBatchValue("custom_component_single", one_per_timestamp), + rr.AnyBatchValue.column("custom_component_single", one_per_timestamp), # log ten values per timestamp - rr.AnyBatchValue("custom_component_multi", ten_per_timestamp).partition([10] * N), + rr.AnyBatchValue.column("custom_component_multi", ten_per_timestamp).partition([10] * N), ], ) diff --git a/docs/snippets/all/howto/any_values_send_columns.py b/docs/snippets/all/howto/any_values_send_columns.py index 5be47bc1ae82b..369b7ef2d25b3 100644 --- a/docs/snippets/all/howto/any_values_send_columns.py +++ b/docs/snippets/all/howto/any_values_send_columns.py @@ -9,14 +9,9 @@ timestamps = np.arange(0, 64) -# Log two components, named "sin" and "cos", with the corresponding values -values = rr.AnyValues( - sin=np.sin(timestamps / 10.0), - cos=np.cos(timestamps / 10.0), -) - -rr.send_columns( +# Log two component columns, named "sin" and "cos", with the corresponding values +rr.send_columns_v2( "/", - times=[rr.TimeSequenceColumn("step", timestamps)], - components=values.as_component_batches(), + indexes=[rr.TimeSequenceColumn("step", timestamps)], + columns=rr.AnyValues.columns(sin=np.sin(timestamps / 10.0), cos=np.cos(timestamps / 10.0)), ) diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 996d778e0a93a..542c7683794a6 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -237,7 +237,6 @@ quick_start = [ # These examples don't have exactly the same implementation. "rust", ] "archetypes/points3d_send_columns" = [ - "py", # TODO(#8752): needs tagged columnar APIs "cpp", # TODO(#8754): needs tagged columnar APIs ] "archetypes/points3d_random" = [ # TODO(#3206): examples use different RNGs @@ -249,7 +248,6 @@ quick_start = [ # These examples don't have exactly the same implementation. "cpp", ] "archetypes/scalar_send_columns" = [ - "py", # TODO(#8752): needs tagged columnar APIs "cpp", # TODO(#8754): needs tagged columnar APIs ] "archetypes/tensor_simple" = [ # TODO(#3206): examples use different RNGs diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 94e514fa637b7..ad113ae3e63d1 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -35,6 +35,7 @@ from ._baseclasses import ( ComponentBatchMixin as ComponentBatchMixin, ComponentColumn as ComponentColumn, + ComponentColumnList as ComponentColumnList, ComponentDescriptor as ComponentDescriptor, DescribedComponentBatch as DescribedComponentBatch, ) @@ -58,6 +59,7 @@ TimeSecondsColumn as TimeSecondsColumn, TimeSequenceColumn as TimeSequenceColumn, send_columns as send_columns, + send_columns_v2 as send_columns_v2, ) from .any_value import ( AnyBatchValue as AnyBatchValue, diff --git a/rerun_py/rerun_sdk/rerun/_baseclasses.py b/rerun_py/rerun_sdk/rerun/_baseclasses.py index 1528c85e76993..e07e4853ab0de 100644 --- a/rerun_py/rerun_sdk/rerun/_baseclasses.py +++ b/rerun_py/rerun_sdk/rerun/_baseclasses.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Generic, Iterable, Protocol, TypeVar +from typing import Generic, Iterable, Iterator, Protocol, TypeVar import numpy as np import numpy.typing as npt @@ -133,6 +133,29 @@ def as_arrow_array(self) -> pa.Array: """ return self._batch.as_arrow_array() + def partition(self, lengths: npt.ArrayLike | None = None) -> ComponentColumn: + """ + Partitions the component batch into multiple sub-batches, forming a column. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumn.partition` to repartition the data as needed. + + Parameters + ---------- + lengths: + The offsets to partition the component at. + If specified, `lengths` must sum to the total length of the component batch. + If left unspecified, it will default to unit-length batches. + + Returns + ------- + The partitioned component batch as a column. + + """ + return ComponentColumn(self, lengths=lengths) + class ComponentBatchLike(Protocol): """Describes interface for objects that can be converted to batch of rerun Components.""" @@ -332,25 +355,47 @@ class ComponentColumn: """ A column of components that can be sent using `send_columns`. - This is represented by a ComponentBatch array that has been repartitioned into multiple segments. + This is represented by a ComponentBatch array that has been partitioned into multiple segments. This is useful for reinterpreting a single contiguous batch as multiple sub-batches to use with the [`send_columns`][rerun.send_columns] API. """ - def __init__(self, component_batch: ComponentBatchLike, lengths: npt.ArrayLike): + def __init__(self, component_batch: ComponentBatchLike, *, lengths: npt.ArrayLike | None = None): """ Construct a new component column. + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned column will be partitioned into unit-length sub-batches by default. + Use `ComponentColumn.partition` to repartition the data as needed. + Parameters ---------- - component_batch : ComponentBatchLike + component_batch: The component batch to partition into a column. - lengths : npt.ArrayLike - The lengths of the partitions. + + lengths: + The offsets to partition the component at. + If specified, `lengths` must sum to the total length of the component batch. + If left unspecified, it will default to unit-length batches. """ self.component_batch = component_batch - self.lengths = lengths + + if "Indicator" in component_batch.component_descriptor().component_name: + if lengths is None: + # Indicator component, no lengths -> zero-sized batches by default + self.lengths = np.zeros(len(component_batch.as_arrow_array())) + else: + # Normal component, lengths specified -> respect outer length, but enforce zero-sized batches still + self.lengths = np.zeros(len(np.array(lengths))) + else: + if lengths is None: + # Normal component, no lengths -> unit-sized batches by default + self.lengths = np.ones(len(component_batch.as_arrow_array())) + else: + # Normal component, lengths specified -> follow instructions + self.lengths = np.array(lengths) def component_descriptor(self) -> ComponentDescriptor: """ @@ -370,6 +415,64 @@ def as_arrow_array(self) -> pa.Array: offsets = np.concatenate((np.array([0], dtype="int32"), np.cumsum(self.lengths, dtype="int32"))) return pa.ListArray.from_arrays(offsets, array) + def partition(self, lengths: npt.ArrayLike) -> ComponentColumn: + """ + (Re)Partitions the column. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumn.partition` to repartition the data as needed. + + Parameters + ---------- + lengths: + The offsets to partition the component at. + + Returns + ------- + The (re)partitioned column. + + """ + return ComponentColumn(self.component_batch, lengths=lengths) + + +class ComponentColumnList(Iterable[ComponentColumn]): + """ + A collection of [ComponentColumn][]s. + + Useful to partition and log multiple columns at once. + """ + + def __init__(self, columns: Iterable[ComponentColumn]): + self._columns = list(columns) + + def __iter__(self) -> Iterator[ComponentColumn]: + return iter(self._columns) + + def partition(self, lengths: npt.ArrayLike) -> ComponentColumnList: + """ + (Re)Partitions the columns. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumn.partition` to repartition the data as needed. + + Parameters + ---------- + lengths: + The offsets to partition the component at. + If specified, `lengths` must sum to the total length of the component batch. + If left unspecified, it will default to unit-length batches. + + Returns + ------- + The partitioned component batch as a column. + + """ + return ComponentColumnList([col.partition(lengths) for col in self._columns]) + class ComponentBatchMixin(ComponentBatchLike): def component_descriptor(self) -> ComponentDescriptor: @@ -418,24 +521,28 @@ def or_with_descriptor_overrides( ), ) - def partition(self, lengths: npt.ArrayLike) -> ComponentColumn: + def partition(self, lengths: npt.ArrayLike | None = None) -> ComponentColumn: """ - Partitions the component into multiple sub-batches. This wraps the inner arrow - array in a `pyarrow.ListArray` where the different lists have the lengths specified. + Partitions the component batch into multiple sub-batches, forming a column. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. - Lengths must sum to the total length of the component batch. + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumn.partition` to repartition the data as needed. Parameters ---------- - lengths : npt.ArrayLike + lengths: The offsets to partition the component at. + If specified, `lengths` must sum to the total length of the component batch. + If left unspecified, it will default to unit-length batches. Returns ------- - The partitioned component. + The partitioned component batch as a column. - """ # noqa: D205 - return ComponentColumn(self, lengths) + """ + return ComponentColumn(self, lengths=lengths) class ComponentMixin(ComponentBatchLike): diff --git a/rerun_py/rerun_sdk/rerun/_send_columns.py b/rerun_py/rerun_sdk/rerun/_send_columns.py index 1639a8ded6334..24ad6e7fb3045 100644 --- a/rerun_py/rerun_sdk/rerun/_send_columns.py +++ b/rerun_py/rerun_sdk/rerun/_send_columns.py @@ -7,7 +7,6 @@ from ._baseclasses import Archetype, ComponentBatchLike, ComponentBatchMixin, ComponentColumn, ComponentDescriptor from ._log import IndicatorComponentBatch -from .any_value import AnyBatchValue from .error_utils import catch_and_log_exceptions from .recording_stream import RecordingStream @@ -228,11 +227,6 @@ def send_columns( component_column = c elif isinstance(c, ComponentBatchMixin): component_column = c.partition([1] * len(c)) # type: ignore[arg-type] - elif isinstance(c, AnyBatchValue): - array = c.as_arrow_array() - if array is None: - raise ValueError(f"Expected a non-null value for component: {component_descr}") - component_column = c.partition([1] * len(c.as_arrow_array())) # type: ignore[arg-type] else: raise TypeError( f"Expected either a type that implements the `ComponentMixin` or a `ComponentColumn`, got: {type(c)}" @@ -260,3 +254,84 @@ def send_columns( components=components_args, recording=recording.to_native() if recording is not None else None, ) + + +@catch_and_log_exceptions() +def send_columns_v2( + entity_path: str, + indexes: Iterable[TimeColumnLike], + columns: Iterable[ComponentColumn], + recording: RecordingStream | None = None, + strict: bool | None = None, +) -> None: + r""" + Send columnar data to Rerun. + + Unlike the regular `log` API, which is row-oriented, this API lets you submit the data + in a columnar form. Each `TimeColumnLike` and `ComponentColumn` object represents a column + of data that will be sent to Rerun. The lengths of all these columns must match, and all + data that shares the same index across the different columns will act as a single logical row, + equivalent to a single call to `rr.log()`. + + Note that this API ignores any stateful time set on the log stream via the `rerun.set_time_*` APIs. + Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. + + Parameters + ---------- + entity_path: + Path to the entity in the space hierarchy. + + See for more on entity paths. + indexes: + The time values of this batch of data. Each `TimeColumnLike` object represents a single column + of timestamps. Generally, you should use one of the provided classes: [`TimeSequenceColumn`][rerun.TimeSequenceColumn], + [`TimeSecondsColumn`][rerun.TimeSecondsColumn], or [`TimeNanosColumn`][rerun.TimeNanosColumn]. + columns: + The columns of components to log. Each object represents a single column of data. + + In order to send multiple components per time value, explicitly create a [`ComponentColumn`][rerun.ComponentColumn] + either by constructing it directly, or by calling the `.columns()` method on an `Archetype` type. + recording: + Specifies the [`rerun.RecordingStream`][] to use. + If left unspecified, defaults to the current active data recording, if there is one. + See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + strict: + If True, raise exceptions on non-loggable data. + If False, warn on non-loggable data. + If None, use the global default from `rerun.strict_mode()` + + """ + expected_length = None + + timelines_args = {} + for t in indexes: + timeline_name = t.timeline_name() + time_column = t.as_arrow_array() + if expected_length is None: + expected_length = len(time_column) + elif len(time_column) != expected_length: + raise ValueError( + f"All times and components in a column must have the same length. Expected length: {expected_length} but got: {len(time_column)} for timeline: {timeline_name}" + ) + + timelines_args[timeline_name] = time_column + + columns_args: dict[ComponentDescriptor, pa.Array] = {} + for component_column in columns: + component_descr = component_column.component_descriptor() + arrow_list_array = component_column.as_arrow_array() + if expected_length is None: + expected_length = len(arrow_list_array) + elif len(arrow_list_array) != expected_length: + raise ValueError( + f"All times and components in a column must have the same length. Expected length: {expected_length} but got: {len(arrow_list_array)} for component: {component_descr}" + ) + + columns_args[component_descr] = arrow_list_array + + bindings.send_arrow_chunk( + entity_path, + timelines={t.timeline_name(): t.as_arrow_array() for t in indexes}, + components=columns_args, + recording=recording.to_native() if recording is not None else None, + ) diff --git a/rerun_py/rerun_sdk/rerun/any_value.py b/rerun_py/rerun_sdk/rerun/any_value.py index 699441856f8c9..699e1f4cbb643 100644 --- a/rerun_py/rerun_sdk/rerun/any_value.py +++ b/rerun_py/rerun_sdk/rerun/any_value.py @@ -3,12 +3,11 @@ from typing import Any, Iterable import numpy as np -import numpy.typing as npt import pyarrow as pa from rerun._baseclasses import ComponentDescriptor -from ._baseclasses import ComponentColumn +from ._baseclasses import ComponentColumn, ComponentColumnList from ._log import AsComponents, ComponentBatchLike from .error_utils import catch_and_log_exceptions @@ -17,7 +16,7 @@ class AnyBatchValue(ComponentBatchLike): """ - Helper to log arbitrary data as a component batch. + Helper to log arbitrary data as a component batch or column. This is a very simple helper that implements the `ComponentBatchLike` interface on top of the `pyarrow` library array conversion functions. @@ -101,24 +100,53 @@ def component_descriptor(self) -> ComponentDescriptor: def as_arrow_array(self) -> pa.Array | None: return self.pa_array - def partition(self, lengths: npt.ArrayLike) -> ComponentColumn: + @classmethod + def column( + cls, descriptor: str | ComponentDescriptor, value: Any, drop_untyped_nones: bool = True + ) -> ComponentColumn: """ - Partitions the component into multiple sub-batches. This wraps the inner arrow - array in a `pyarrow.ListArray` where the different lists have the lengths specified. + Construct a new column-oriented AnyBatchValue. - Lengths must sum to the total length of the component batch. + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumn.partition` to repartition the data as needed. + + The value will be attempted to be converted into an arrow array by first calling + the `as_arrow_array()` method if it's defined. All Rerun Batch datatypes implement + this function so it's possible to pass them directly to AnyValues. + + If the object doesn't implement `as_arrow_array()`, it will be passed as an argument + to [pyarrow.array][] . + + Note: rerun requires that a given component only take on a single type. + The first type logged will be the type that is used for all future logs + of that component. The API will make a best effort to do type conversion + if supported by numpy and arrow. Any components that can't be converted + will be dropped, and a warning will be sent to the log. + + If you want to inspect how your component will be converted to the + underlying arrow code, the following snippet is what is happening + internally: + + ``` + np_value = np.atleast_1d(np.array(value, copy=False)) + pa_value = pa.array(value) + ``` Parameters ---------- - lengths : npt.ArrayLike - The offsets to partition the component at. - - Returns - ------- - The partitioned component. + descriptor: + Either the name or the full descriptor of the component. + value: + The data to be logged as a component. + drop_untyped_nones: + If True, any components that are None will be dropped unless they have been + previously logged with a type. - """ # noqa: D205 - return ComponentColumn(self, lengths) + """ + inst = cls(descriptor, value, drop_untyped_nones) + return ComponentColumn(inst) class AnyValues(AsComponents): @@ -142,7 +170,7 @@ def __init__(self, drop_untyped_nones: bool = True, **kwargs: Any) -> None: """ Construct a new AnyValues bundle. - Each kwarg will be logged as a separate component using the provided data. + Each kwarg will be logged as a separate component batch using the provided data. - The key will be used as the name of the component - The value must be able to be converted to an array of arrow types. In general, if you can pass it to [pyarrow.array][] you can log it as a @@ -195,3 +223,57 @@ def __init__(self, drop_untyped_nones: bool = True, **kwargs: Any) -> None: def as_component_batches(self) -> Iterable[ComponentBatchLike]: return self.component_batches + + @classmethod + def columns(cls, drop_untyped_nones: bool = True, **kwargs: Any) -> ComponentColumnList: + """ + Construct a new column-oriented AnyValues bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Each kwarg will be logged as a separate component column using the provided data. + - The key will be used as the name of the component + - The value must be able to be converted to an array of arrow types. In + general, if you can pass it to [pyarrow.array][] you can log it as a + extension component. + + Note: rerun requires that a given component only take on a single type. + The first type logged will be the type that is used for all future logs + of that component. The API will make a best effort to do type conversion + if supported by numpy and arrow. Any components that can't be converted + will result in a warning (or an exception in strict mode). + + `None` values provide a particular challenge as they have no type + information until after the component has been logged with a particular + type. By default, these values are dropped. This should generally be + fine as logging `None` to clear the value before it has been logged is + meaningless unless you are logging out-of-order data. In such cases, + consider introducing your own typed component via + [rerun.ComponentBatchLike][]. + + You can change this behavior by setting `drop_untyped_nones` to `False`, + but be aware that this will result in potential warnings (or exceptions + in strict mode). + + If you are want to inspect how your component will be converted to the + underlying arrow code, the following snippet is what is happening + internally: + ``` + np_value = np.atleast_1d(np.array(value, copy=False)) + pa_value = pa.array(value) + ``` + + Parameters + ---------- + drop_untyped_nones: + If True, any components that are None will be dropped unless they + have been previously logged with a type. + kwargs: + The components to be logged. + + """ + inst = cls(drop_untyped_nones, **kwargs) + return ComponentColumnList([ComponentColumn(batch) for batch in inst.component_batches]) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py index 8aa27d7a7a020..3a009614ed8a0 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -135,6 +138,45 @@ def clear_fields(cls) -> AnnotationContext: ) return inst + @classmethod + def columns( + cls, + *, + context: components.AnnotationContextArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + context: + List of class descriptions, mapping class indices to class names, colors etc. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + context=context, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + context: components.AnnotationContextBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py index cfd1323ef72c3..7091a03863e0e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .arrows2d_ext import Arrows2DExt @@ -165,6 +168,85 @@ def clear_fields(cls) -> Arrows2D: ) return inst + @classmethod + def columns( + cls, + *, + vectors: datatypes.Vec2DArrayLike | None = None, + origins: datatypes.Vec2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + vectors: + All the vectors for each arrow in the batch. + origins: + All the origin (base) positions for each arrow in the batch. + + If no origins are set, (0, 0) is used as the origin for each arrow. + radii: + Optional radii for the arrows. + + The shaft is rendered as a line with `radius = 0.5 * radius`. + The tip is rendered with `height = 2.0 * radius` and `radius = 1.0 * radius`. + colors: + Optional colors for the points. + labels: + Optional text labels for the arrows. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + vectors=vectors, + origins=origins, + radii=radii, + colors=colors, + labels=labels, + show_labels=show_labels, + draw_order=draw_order, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + vectors: components.Vector2DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py index 576a461e992ec..dd32eb582cc68 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .arrows3d_ext import Arrows3DExt @@ -157,6 +160,79 @@ def clear_fields(cls) -> Arrows3D: ) return inst + @classmethod + def columns( + cls, + *, + vectors: datatypes.Vec3DArrayLike | None = None, + origins: datatypes.Vec3DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + vectors: + All the vectors for each arrow in the batch. + origins: + All the origin (base) positions for each arrow in the batch. + + If no origins are set, (0, 0, 0) is used as the origin for each arrow. + radii: + Optional radii for the arrows. + + The shaft is rendered as a line with `radius = 0.5 * radius`. + The tip is rendered with `height = 2.0 * radius` and `radius = 1.0 * radius`. + colors: + Optional colors for the points. + labels: + Optional text labels for the arrows. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + vectors=vectors, + origins=origins, + radii=radii, + colors=colors, + labels=labels, + show_labels=show_labels, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + vectors: components.Vector3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py index eecdd926d70b6..b97a91e6b3149 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .asset3d_ext import Asset3DExt @@ -138,6 +141,65 @@ def clear_fields(cls) -> Asset3D: ) return inst + @classmethod + def columns( + cls, + *, + blob: datatypes.BlobArrayLike | None = None, + media_type: datatypes.Utf8ArrayLike | None = None, + albedo_factor: datatypes.Rgba32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + blob: + The asset's bytes. + media_type: + The Media Type of the asset. + + Supported values: + * `model/gltf-binary` + * `model/gltf+json` + * `model/obj` (.mtl material files are not supported yet, references are silently ignored) + * `model/stl` + + If omitted, the viewer will try to guess from the data blob. + If it cannot guess, it won't be able to render the asset. + albedo_factor: + A color multiplier applied to the whole asset. + + For mesh who already have `albedo_factor` in materials, + it will be overwritten by actual `albedo_factor` of [`archetypes.Asset3D`][rerun.archetypes.Asset3D] (if specified). + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + blob=blob, + media_type=media_type, + albedo_factor=albedo_factor, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + blob: components.BlobBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index 23b4c55968e29..4d022fedb5c2a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .asset_video_ext import AssetVideoExt @@ -183,6 +186,55 @@ def clear_fields(cls) -> AssetVideo: ) return inst + @classmethod + def columns( + cls, + *, + blob: datatypes.BlobArrayLike | None = None, + media_type: datatypes.Utf8ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + blob: + The asset's bytes. + media_type: + The Media Type of the asset. + + Supported values: + * `video/mp4` + + If omitted, the viewer will try to guess from the data blob. + If it cannot guess, it won't be able to render the asset. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + blob=blob, + media_type=media_type, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + blob: components.BlobBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py index d6f211e046c4e..a5967dcb63d6c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .bar_chart_ext import BarChartExt @@ -128,6 +131,49 @@ def clear_fields(cls) -> BarChart: ) return inst + @classmethod + def columns( + cls, + *, + values: datatypes.TensorDataArrayLike | None = None, + color: datatypes.Rgba32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + values: + The values. Should always be a 1-dimensional tensor (i.e. a vector). + color: + The color of the bar chart + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + values=values, + color=color, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + values: components.TensorDataBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index 651f1bb797258..f4d1c2f42aab1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .boxes2d_ext import Boxes2DExt @@ -153,6 +156,82 @@ def clear_fields(cls) -> Boxes2D: ) return inst + @classmethod + def columns( + cls, + *, + half_sizes: datatypes.Vec2DArrayLike | None = None, + centers: datatypes.Vec2DArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + half_sizes: + All half-extents that make up the batch of boxes. + centers: + Optional center positions of the boxes. + colors: + Optional colors for the boxes. + radii: + Optional radii for the lines that make up the boxes. + labels: + Optional text labels for the boxes. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + The default for 2D boxes is 10.0. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the boxes. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + half_sizes=half_sizes, + centers=centers, + colors=colors, + radii=radii, + labels=labels, + show_labels=show_labels, + draw_order=draw_order, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + half_sizes: components.HalfSize2DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py index a600bbcad191f..8c87e43d4366c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .boxes3d_ext import Boxes3DExt @@ -188,6 +191,95 @@ def clear_fields(cls) -> Boxes3D: ) return inst + @classmethod + def columns( + cls, + *, + half_sizes: datatypes.Vec3DArrayLike | None = None, + centers: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + fill_mode: components.FillModeArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + half_sizes: + All half-extents that make up the batch of boxes. + centers: + Optional center positions of the boxes. + + If not specified, the centers will be at (0, 0, 0). + Note that this uses a [`components.PoseTranslation3D`][rerun.components.PoseTranslation3D] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + rotation_axis_angles: + Rotations via axis + angle. + + If no rotation is specified, the axes of the boxes align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationAxisAngle`][rerun.components.PoseRotationAxisAngle] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + quaternions: + Rotations via quaternion. + + If no rotation is specified, the axes of the boxes align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationQuat`][rerun.components.PoseRotationQuat] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + colors: + Optional colors for the boxes. + radii: + Optional radii for the lines that make up the boxes. + fill_mode: + Optionally choose whether the boxes are drawn with lines or solid. + labels: + Optional text labels for the boxes. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the boxes. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + half_sizes=half_sizes, + centers=centers, + rotation_axis_angles=rotation_axis_angles, + quaternions=quaternions, + colors=colors, + radii=radii, + fill_mode=fill_mode, + labels=labels, + show_labels=show_labels, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + half_sizes: components.HalfSize3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py index 798ea93dd7512..6ccebaf4cfbb2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .capsules3d_ext import Capsules3DExt @@ -193,6 +196,88 @@ def clear_fields(cls) -> Capsules3D: ) return inst + @classmethod + def columns( + cls, + *, + lengths: datatypes.Float32ArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + translations: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + lengths: + Lengths of the capsules, defined as the distance between the centers of the endcaps. + radii: + Radii of the capsules. + translations: + Optional translations of the capsules. + + If not specified, one end of each capsule will be at (0, 0, 0). + Note that this uses a [`components.PoseTranslation3D`][rerun.components.PoseTranslation3D] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + rotation_axis_angles: + Rotations via axis + angle. + + If no rotation is specified, the capsules align with the +Z axis of the local coordinate system. + Note that this uses a [`components.PoseRotationAxisAngle`][rerun.components.PoseRotationAxisAngle] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + quaternions: + Rotations via quaternion. + + If no rotation is specified, the capsules align with the +Z axis of the local coordinate system. + Note that this uses a [`components.PoseRotationQuat`][rerun.components.PoseRotationQuat] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + colors: + Optional colors for the capsules. + labels: + Optional text labels for the capsules, which will be located at their centers. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class ID for the ellipsoids. + + The class ID provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + lengths=lengths, + radii=radii, + translations=translations, + rotation_axis_angles=rotation_axis_angles, + quaternions=quaternions, + colors=colors, + labels=labels, + show_labels=show_labels, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + lengths: components.LengthBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/clear.py b/rerun_py/rerun_sdk/rerun/archetypes/clear.py index 24f9d45ab5942..4adc9f758a22b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/clear.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/clear.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .clear_ext import ClearExt @@ -112,6 +115,39 @@ def clear_fields(cls) -> Clear: ) return inst + @classmethod + def columns( + cls, + *, + is_recursive: datatypes.BoolArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + is_recursive=is_recursive, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + is_recursive: components.ClearIsRecursiveBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py index a357abff9aa15..d31440c57ce9f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .depth_image_ext import DepthImageExt @@ -182,6 +185,95 @@ def clear_fields(cls) -> DepthImage: ) return inst + @classmethod + def columns( + cls, + *, + buffer: datatypes.BlobArrayLike | None = None, + format: datatypes.ImageFormatArrayLike | None = None, + meter: datatypes.Float32ArrayLike | None = None, + colormap: components.ColormapArrayLike | None = None, + depth_range: datatypes.Range1DArrayLike | None = None, + point_fill_ratio: datatypes.Float32ArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + buffer: + The raw depth image data. + format: + The format of the image. + meter: + An optional floating point value that specifies how long a meter is in the native depth units. + + For instance: with uint16, perhaps meter=1000 which would mean you have millimeter precision + and a range of up to ~65 meters (2^16 / 1000). + + Note that the only effect on 2D views is the physical depth values shown when hovering the image. + In 3D views on the other hand, this affects where the points of the point cloud are placed. + colormap: + Colormap to use for rendering the depth image. + + If not set, the depth image will be rendered using the Turbo colormap. + depth_range: + The expected range of depth values. + + This is typically the expected range of valid values. + Everything outside of the range is clamped to the range for the purpose of colormpaping. + Note that point clouds generated from this image will still display all points, regardless of this range. + + If not specified, the range will be automatically estimated from the data. + Note that the Viewer may try to guess a wider range than the minimum/maximum of values + in the contents of the depth image. + E.g. if all values are positive, some bigger than 1.0 and all smaller than 255.0, + the Viewer will guess that the data likely came from an 8bit image, thus assuming a range of 0-255. + point_fill_ratio: + Scale the radii of the points in the point cloud generated from this image. + + A fill ratio of 1.0 (the default) means that each point is as big as to touch the center of its neighbor + if it is at the same depth, leaving no gaps. + A fill ratio of 0.5 means that each point touches the edge of its neighbor if it has the same depth. + + TODO(#6744): This applies only to 3D views! + draw_order: + An optional floating point value that specifies the 2D drawing order, used only if the depth image is shown as a 2D image. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + buffer=buffer, + format=format, + meter=meter, + colormap=colormap, + depth_range=depth_range, + point_fill_ratio=point_fill_ratio, + draw_order=draw_order, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + buffer: components.ImageBufferBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py index fa001fc3f9200..dc06213618fb8 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .ellipsoids3d_ext import Ellipsoids3DExt @@ -190,6 +193,94 @@ def clear_fields(cls) -> Ellipsoids3D: ) return inst + @classmethod + def columns( + cls, + *, + half_sizes: datatypes.Vec3DArrayLike | None = None, + centers: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + line_radii: datatypes.Float32ArrayLike | None = None, + fill_mode: components.FillModeArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + half_sizes: + For each ellipsoid, half of its size on its three axes. + + If all components are equal, then it is a sphere with that radius. + centers: + Optional center positions of the ellipsoids. + + If not specified, the centers will be at (0, 0, 0). + Note that this uses a [`components.PoseTranslation3D`][rerun.components.PoseTranslation3D] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + rotation_axis_angles: + Rotations via axis + angle. + + If no rotation is specified, the axes of the ellipsoid align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationAxisAngle`][rerun.components.PoseRotationAxisAngle] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + quaternions: + Rotations via quaternion. + + If no rotation is specified, the axes of the ellipsoid align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationQuat`][rerun.components.PoseRotationQuat] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + colors: + Optional colors for the ellipsoids. + line_radii: + Optional radii for the lines used when the ellipsoid is rendered as a wireframe. + fill_mode: + Optionally choose whether the ellipsoids are drawn with lines or solid. + labels: + Optional text labels for the ellipsoids. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class ID for the ellipsoids. + + The class ID provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + half_sizes=half_sizes, + centers=centers, + rotation_axis_angles=rotation_axis_angles, + quaternions=quaternions, + colors=colors, + line_radii=line_radii, + fill_mode=fill_mode, + labels=labels, + show_labels=show_labels, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + half_sizes: components.HalfSize3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py index 2900255165029..89e54fac1c13f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .encoded_image_ext import EncodedImageExt @@ -131,6 +134,68 @@ def clear_fields(cls) -> EncodedImage: ) return inst + @classmethod + def columns( + cls, + *, + blob: datatypes.BlobArrayLike | None = None, + media_type: datatypes.Utf8ArrayLike | None = None, + opacity: datatypes.Float32ArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + blob: + The encoded content of some image file, e.g. a PNG or JPEG. + media_type: + The Media Type of the asset. + + Supported values: + * `image/jpeg` + * `image/png` + + If omitted, the viewer will try to guess from the data blob. + If it cannot guess, it won't be able to render the asset. + opacity: + Opacity of the image, useful for layering several images. + + Defaults to 1.0 (fully opaque). + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + blob=blob, + media_type=media_type, + opacity=opacity, + draw_order=draw_order, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + blob: components.BlobBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py index 56a9c1d78513f..f6197a784b449 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .geo_line_strings_ext import GeoLineStringsExt @@ -135,6 +138,59 @@ def clear_fields(cls) -> GeoLineStrings: ) return inst + @classmethod + def columns( + cls, + *, + line_strings: components.GeoLineStringArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + line_strings: + The line strings, expressed in [EPSG:4326](https://epsg.io/4326) coordinates (North/East-positive degrees). + radii: + Optional radii for the line strings. + + *Note*: scene units radiii are interpreted as meters. Currently, the display scale only considers the latitude of + the first vertex of each line string (see [this issue](https://github.com/rerun-io/rerun/issues/8013)). + colors: + Optional colors for the line strings. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + line_strings=line_strings, + radii=radii, + colors=colors, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + line_strings: components.GeoLineStringBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py index 024a8332c32e5..64e455edafd4c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .geo_points_ext import GeoPointsExt @@ -134,6 +137,64 @@ def clear_fields(cls) -> GeoPoints: ) return inst + @classmethod + def columns( + cls, + *, + positions: datatypes.DVec2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + positions: + The [EPSG:4326](https://epsg.io/4326) coordinates for the points (North/East-positive degrees). + radii: + Optional radii for the points, effectively turning them into circles. + + *Note*: scene units radiii are interpreted as meters. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + positions=positions, + radii=radii, + colors=colors, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + positions: components.LatLonBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py index fd89ff88fa56f..30449bb1b0eb5 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -138,6 +141,51 @@ def clear_fields(cls) -> GraphEdges: ) return inst + @classmethod + def columns( + cls, + *, + edges: datatypes.Utf8PairArrayLike | None = None, + graph_type: components.GraphTypeArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + edges: + A list of node tuples. + graph_type: + Specifies if the graph is directed or undirected. + + If no [`components.GraphType`][rerun.components.GraphType] is provided, the graph is assumed to be undirected. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + edges=edges, + graph_type=graph_type, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + edges: components.GraphEdgeBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py index 9e3f77b690651..c69317e5e3eac 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -180,6 +183,65 @@ def clear_fields(cls) -> GraphNodes: ) return inst + @classmethod + def columns( + cls, + *, + node_ids: datatypes.Utf8ArrayLike | None = None, + positions: datatypes.Vec2DArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + node_ids: + A list of node IDs. + positions: + Optional center positions of the nodes. + colors: + Optional colors for the boxes. + labels: + Optional text labels for the node. + show_labels: + Optional choice of whether the text labels should be shown by default. + radii: + Optional radii for nodes. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + node_ids=node_ids, + positions=positions, + colors=colors, + labels=labels, + show_labels=show_labels, + radii=radii, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + node_ids: components.GraphNodeBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py index de908e7840ea4..bb34b368324fc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .image_ext import ImageExt @@ -168,6 +171,61 @@ def clear_fields(cls) -> Image: ) return inst + @classmethod + def columns( + cls, + *, + buffer: datatypes.BlobArrayLike | None = None, + format: datatypes.ImageFormatArrayLike | None = None, + opacity: datatypes.Float32ArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + buffer: + The raw image data. + format: + The format of the image. + opacity: + Opacity of the image, useful for layering several images. + + Defaults to 1.0 (fully opaque). + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + buffer=buffer, + format=format, + opacity=opacity, + draw_order=draw_order, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + buffer: components.ImageBufferBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py index 146e397d8b9b1..d6a65ff127cf1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -191,6 +194,61 @@ def clear_fields(cls) -> InstancePoses3D: ) return inst + @classmethod + def columns( + cls, + *, + translations: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + scales: datatypes.Vec3DArrayLike | None = None, + mat3x3: datatypes.Mat3x3ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + translations: + Translation vectors. + rotation_axis_angles: + Rotations via axis + angle. + quaternions: + Rotations via quaternion. + scales: + Scaling factors. + mat3x3: + 3x3 transformation matrices. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + translations=translations, + rotation_axis_angles=rotation_axis_angles, + quaternions=quaternions, + scales=scales, + mat3x3=mat3x3, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + translations: components.PoseTranslation3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index 6f48d660b8c51..f9298fc3bf283 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -250,6 +253,76 @@ def clear_fields(cls) -> LineStrips2D: ) return inst + @classmethod + def columns( + cls, + *, + strips: components.LineStrip2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + strips: + All the actual 2D line strips that make up the batch. + radii: + Optional radii for the line strips. + colors: + Optional colors for the line strips. + labels: + Optional text labels for the line strips. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order of each line strip. + + Objects with higher values are drawn on top of those with lower values. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the lines. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + strips=strips, + radii=radii, + colors=colors, + labels=labels, + show_labels=show_labels, + draw_order=draw_order, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + strips: components.LineStrip2DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py index 0ed372d2c377e..886f397ae6880 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -246,6 +249,70 @@ def clear_fields(cls) -> LineStrips3D: ) return inst + @classmethod + def columns( + cls, + *, + strips: components.LineStrip3DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + strips: + All the actual 3D line strips that make up the batch. + radii: + Optional radii for the line strips. + colors: + Optional colors for the line strips. + labels: + Optional text labels for the line strips. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the lines. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + strips=strips, + radii=radii, + colors=colors, + labels=labels, + show_labels=show_labels, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + strips: components.LineStrip3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py index 5b58a8239e24d..51d644bb3920f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .mesh3d_ext import Mesh3DExt @@ -213,6 +216,86 @@ def clear_fields(cls) -> Mesh3D: ) return inst + @classmethod + def columns( + cls, + *, + vertex_positions: datatypes.Vec3DArrayLike | None = None, + triangle_indices: datatypes.UVec3DArrayLike | None = None, + vertex_normals: datatypes.Vec3DArrayLike | None = None, + vertex_colors: datatypes.Rgba32ArrayLike | None = None, + vertex_texcoords: datatypes.Vec2DArrayLike | None = None, + albedo_factor: datatypes.Rgba32ArrayLike | None = None, + albedo_texture_buffer: datatypes.BlobArrayLike | None = None, + albedo_texture_format: datatypes.ImageFormatArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + vertex_positions: + The positions of each vertex. + + If no `triangle_indices` are specified, then each triplet of positions is interpreted as a triangle. + triangle_indices: + Optional indices for the triangles that make up the mesh. + vertex_normals: + An optional normal for each vertex. + vertex_colors: + An optional color for each vertex. + vertex_texcoords: + An optional uv texture coordinate for each vertex. + albedo_factor: + A color multiplier applied to the whole mesh. + albedo_texture_buffer: + Optional albedo texture. + + Used with the [`components.Texcoord2D`][rerun.components.Texcoord2D] of the mesh. + + Currently supports only sRGB(A) textures, ignoring alpha. + (meaning that the tensor must have 3 or 4 channels and use the `u8` format) + albedo_texture_format: + The format of the `albedo_texture_buffer`, if any. + class_ids: + Optional class Ids for the vertices. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + vertex_positions=vertex_positions, + triangle_indices=triangle_indices, + vertex_normals=vertex_normals, + vertex_colors=vertex_colors, + vertex_texcoords=vertex_texcoords, + albedo_factor=albedo_factor, + albedo_texture_buffer=albedo_texture_buffer, + albedo_texture_format=albedo_texture_format, + class_ids=class_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + vertex_positions: components.Position3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py index b175a4173cc46..1ee90beb91e1c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .pinhole_ext import PinholeExt @@ -182,6 +185,92 @@ def clear_fields(cls) -> Pinhole: ) return inst + @classmethod + def columns( + cls, + *, + image_from_camera: datatypes.Mat3x3ArrayLike | None = None, + resolution: datatypes.Vec2DArrayLike | None = None, + camera_xyz: datatypes.ViewCoordinatesArrayLike | None = None, + image_plane_distance: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + image_from_camera: + Camera projection, from image coordinates to view coordinates. + resolution: + Pixel resolution (usually integers) of child image space. Width and height. + + Example: + ```text + [1920.0, 1440.0] + ``` + + `image_from_camera` project onto the space spanned by `(0,0)` and `resolution - 1`. + camera_xyz: + Sets the view coordinates for the camera. + + All common values are available as constants on the [`components.ViewCoordinates`][rerun.components.ViewCoordinates] class. + + The default is `ViewCoordinates::RDF`, i.e. X=Right, Y=Down, Z=Forward, and this is also the recommended setting. + This means that the camera frustum will point along the positive Z axis of the parent space, + and the cameras "up" direction will be along the negative Y axis of the parent space. + + The camera frustum will point whichever axis is set to `F` (or the opposite of `B`). + When logging a depth image under this entity, this is the direction the point cloud will be projected. + With `RDF`, the default forward is +Z. + + The frustum's "up" direction will be whichever axis is set to `U` (or the opposite of `D`). + This will match the negative Y direction of pixel space (all images are assumed to have xyz=RDF). + With `RDF`, the default is up is -Y. + + The frustum's "right" direction will be whichever axis is set to `R` (or the opposite of `L`). + This will match the positive X direction of pixel space (all images are assumed to have xyz=RDF). + With `RDF`, the default right is +x. + + Other common formats are `RUB` (X=Right, Y=Up, Z=Back) and `FLU` (X=Forward, Y=Left, Z=Up). + + NOTE: setting this to something else than `RDF` (the default) will change the orientation of the camera frustum, + and make the pinhole matrix not match up with the coordinate system of the pinhole entity. + + The pinhole matrix (the `image_from_camera` argument) always project along the third (Z) axis, + but will be re-oriented to project along the forward axis of the `camera_xyz` argument. + image_plane_distance: + The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. + + This is only used for visualization purposes, and does not affect the projection itself. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + image_from_camera=image_from_camera, + resolution=resolution, + camera_xyz=camera_xyz, + image_plane_distance=image_plane_distance, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + image_from_camera: components.PinholeProjectionBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index 2a4c8f88b8d12..2af4801c7e3bb 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .points2d_ext import Points2DExt @@ -215,6 +218,90 @@ def clear_fields(cls) -> Points2D: ) return inst + @classmethod + def columns( + cls, + *, + positions: datatypes.Vec2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + keypoint_ids: datatypes.KeypointIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + positions: + All the 2D positions at which the point cloud shows points. + radii: + Optional radii for the points, effectively turning them into circles. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + labels: + Optional text labels for the points. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + keypoint_ids: + Optional keypoint IDs for the points, identifying them within a class. + + If keypoint IDs are passed in but no [`components.ClassId`][rerun.components.ClassId]s were specified, the [`components.ClassId`][rerun.components.ClassId] will + default to 0. + This is useful to identify points within a single classification (which is identified + with `class_id`). + E.g. the classification might be 'Person' and the keypoints refer to joints on a + detected skeleton. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + positions=positions, + radii=radii, + colors=colors, + labels=labels, + show_labels=show_labels, + draw_order=draw_order, + class_ids=class_ids, + keypoint_ids=keypoint_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + positions: components.Position2DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index da0ba3e6ae8b2..04ec5bd6f5378 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .points3d_ext import Points3DExt @@ -108,21 +111,17 @@ class Points3D(Points3DExt, Archetype): [1.0, -1.0, 1.0], [2.0, -2.0, 2.0], [3.0, -1.0, 3.0], [2.0, 0.0, 4.0], ] # fmt: on - positions_arr = np.concatenate(positions) # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] - # TODO(#8752): use tagged columnar APIs - rr.send_columns( + rr.send_columns_v2( "points", - times=[rr.TimeSecondsColumn("time", times)], - components=[ - rr.Points3D.indicator(), - rr.components.Position3DBatch(positions_arr).partition([2, 4, 4, 3, 4]), - rr.components.ColorBatch(colors), - rr.components.RadiusBatch(radii), + indexes=[rr.TimeSecondsColumn("time", times)], + columns=[ + *rr.Points3D.columns(positions=positions).partition(lengths=[2, 4, 4, 3, 4]), + *rr.Points3D.columns(colors=colors, radii=radii), ], ) ``` @@ -247,6 +246,84 @@ def clear_fields(cls) -> Points3D: ) return inst + @classmethod + def columns( + cls, + *, + positions: datatypes.Vec3DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + keypoint_ids: datatypes.KeypointIdArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + positions: + All the 3D positions at which the point cloud shows points. + radii: + Optional radii for the points, effectively turning them into circles. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + labels: + Optional text labels for the points. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + keypoint_ids: + Optional keypoint IDs for the points, identifying them within a class. + + If keypoint IDs are passed in but no [`components.ClassId`][rerun.components.ClassId]s were specified, the [`components.ClassId`][rerun.components.ClassId] will + default to 0. + This is useful to identify points within a single classification (which is identified + with `class_id`). + E.g. the classification might be 'Person' and the keypoints refer to joints on a + detected skeleton. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + positions=positions, + radii=radii, + colors=colors, + labels=labels, + show_labels=show_labels, + class_ids=class_ids, + keypoint_ids=keypoint_ids, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + positions: components.Position3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index 379bc6d5daf36..0f680395b34b6 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -68,10 +71,10 @@ class Scalar(Archetype): times = np.arange(0, 64) scalars = np.sin(times / 10.0) - rr.send_columns( + rr.send_columns_v2( "scalars", - times=[rr.TimeSequenceColumn("step", times)], - components=[rr.components.ScalarBatch(scalars)], + indexes=[rr.TimeSequenceColumn("step", times)], + columns=rr.Scalar.columns(scalar=scalars), ) ```
@@ -159,6 +162,42 @@ def clear_fields(cls) -> Scalar: ) return inst + @classmethod + def columns( + cls, + *, + scalar: datatypes.Float64ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + scalar: + The scalar value to log. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + scalar=scalar, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + return ComponentColumnList(columns) + scalar: components.ScalarBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py index 31daaff195973..1a15736d377f9 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .segmentation_image_ext import SegmentationImageExt @@ -140,6 +143,61 @@ def clear_fields(cls) -> SegmentationImage: ) return inst + @classmethod + def columns( + cls, + *, + buffer: datatypes.BlobArrayLike | None = None, + format: datatypes.ImageFormatArrayLike | None = None, + opacity: datatypes.Float32ArrayLike | None = None, + draw_order: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + buffer: + The raw image data. + format: + The format of the image. + opacity: + Opacity of the image, useful for layering the segmentation image on top of another image. + + Defaults to 0.5 if there's any other images in the scene, otherwise 1.0. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + buffer=buffer, + format=format, + opacity=opacity, + draw_order=draw_order, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + buffer: components.ImageBufferBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 54b907139ec3e..c2d8a4cc3c170 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -178,6 +181,63 @@ def clear_fields(cls) -> SeriesLine: ) return inst + @classmethod + def columns( + cls, + *, + color: datatypes.Rgba32ArrayLike | None = None, + width: datatypes.Float32ArrayLike | None = None, + name: datatypes.Utf8ArrayLike | None = None, + aggregation_policy: components.AggregationPolicyArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + color: + Color for the corresponding series. + width: + Stroke width for the corresponding series. + name: + Display name of the series. + + Used in the legend. + aggregation_policy: + Configures the zoom-dependent scalar aggregation. + + This is done only if steps on the X axis go below a single pixel, + i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + (and readability) in such situations as it prevents overdraw. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + color=color, + width=width, + name=name, + aggregation_policy=aggregation_policy, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + color: components.ColorBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index 01347718ffc42..ccfd7d809ea4c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -188,6 +191,59 @@ def clear_fields(cls) -> SeriesPoint: ) return inst + @classmethod + def columns( + cls, + *, + color: datatypes.Rgba32ArrayLike | None = None, + marker: components.MarkerShapeArrayLike | None = None, + name: datatypes.Utf8ArrayLike | None = None, + marker_size: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + color: + Color for the corresponding series. + marker: + What shape to use to represent the point + name: + Display name of the series. + + Used in the legend. + marker_size: + Size of the marker. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + color=color, + marker=marker, + name=name, + marker_size=marker_size, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + color: components.ColorBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py index b497dcd445442..2e30eee8337c8 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .tensor_ext import TensorExt @@ -126,6 +129,59 @@ def clear_fields(cls) -> Tensor: ) return inst + @classmethod + def columns( + cls, + *, + data: datatypes.TensorDataArrayLike | None = None, + value_range: datatypes.Range1DArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + data: + The tensor data + value_range: + The expected range of values. + + This is typically the expected range of valid values. + Everything outside of the range is clamped to the range for the purpose of colormpaping. + Any colormap applied for display, will map this range. + + If not specified, the range will be automatically estimated from the data. + Note that the Viewer may try to guess a wider range than the minimum/maximum of values + in the contents of the tensor. + E.g. if all values are positive, some bigger than 1.0 and all smaller than 255.0, + the Viewer will guess that the data likely came from an 8bit image, thus assuming a range of 0-255. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + data=data, + value_range=value_range, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + data: components.TensorDataBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py index 1c7b001c386bc..24c93d2a0e0a1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -182,6 +185,55 @@ def clear_fields(cls) -> TextDocument: ) return inst + @classmethod + def columns( + cls, + *, + text: datatypes.Utf8ArrayLike | None = None, + media_type: datatypes.Utf8ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + text: + Contents of the text document. + media_type: + The Media Type of the text. + + For instance: + * `text/plain` + * `text/markdown` + + If omitted, `text/plain` is assumed. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + text=text, + media_type=media_type, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + text: components.TextBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py index 99dc521f3d521..099999bc45a99 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -152,6 +155,55 @@ def clear_fields(cls) -> TextLog: ) return inst + @classmethod + def columns( + cls, + *, + text: datatypes.Utf8ArrayLike | None = None, + level: datatypes.Utf8ArrayLike | None = None, + color: datatypes.Rgba32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + text: + The body of the message. + level: + The verbosity level of the message. + + This can be used to filter the log messages in the Rerun Viewer. + color: + Optional color to use for the log line in the Rerun Viewer. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + text=text, + level=level, + color=color, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + text: components.TextBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index caf4ede5d3b2d..638f69854b81a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .transform3d_ext import Transform3DExt @@ -233,6 +236,72 @@ def clear_fields(cls) -> Transform3D: ) return inst + @classmethod + def columns( + cls, + *, + translation: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angle: datatypes.RotationAxisAngleArrayLike | None = None, + quaternion: datatypes.QuaternionArrayLike | None = None, + scale: datatypes.Vec3DArrayLike | None = None, + mat3x3: datatypes.Mat3x3ArrayLike | None = None, + relation: components.TransformRelationArrayLike | None = None, + axis_length: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + translation: + Translation vector. + rotation_axis_angle: + Rotation via axis + angle. + quaternion: + Rotation via quaternion. + scale: + Scaling factor. + mat3x3: + 3x3 transformation matrix. + relation: + Specifies the relation this transform establishes between this entity and its parent. + axis_length: + Visual length of the 3 axes. + + The length is interpreted in the local coordinate system of the transform. + If the transform is scaled, the axes will be scaled accordingly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + translation=translation, + rotation_axis_angle=rotation_axis_angle, + quaternion=quaternion, + scale=scale, + mat3x3=mat3x3, + relation=relation, + axis_length=axis_length, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + translation: components.Translation3DBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index 6ecc7ddac2ff9..7bb69322323f0 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -5,11 +5,14 @@ from __future__ import annotations +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .video_frame_reference_ext import VideoFrameReferenceExt @@ -190,6 +193,64 @@ def clear_fields(cls) -> VideoFrameReference: ) return inst + @classmethod + def columns( + cls, + *, + timestamp: datatypes.VideoTimestampArrayLike | None = None, + video_reference: datatypes.EntityPathArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + timestamp: + References the closest video frame to this timestamp. + + Note that this uses the closest video frame instead of the latest at this timestamp + in order to be more forgiving of rounding errors for inprecise timestamp types. + + Timestamps are relative to the start of the video, i.e. a timestamp of 0 always corresponds to the first frame. + This is oftentimes equivalent to presentation timestamps (known as PTS), but in the presence of B-frames + (bidirectionally predicted frames) there may be an offset on the first presentation timestamp in the video. + video_reference: + Optional reference to an entity with a [`archetypes.AssetVideo`][rerun.archetypes.AssetVideo]. + + If none is specified, the video is assumed to be at the same entity. + Note that blueprint overrides on the referenced video will be ignored regardless, + as this is always interpreted as a reference to the data store. + + For a series of video frame references, it is recommended to specify this path only once + at the beginning of the series and then rely on latest-at query semantics to + keep the video reference active. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + timestamp=timestamp, + video_reference=video_reference, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + timestamp: components.VideoTimestampBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 413bc403160d4..4627eb8bb1037 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -7,11 +7,14 @@ from typing import Any +import numpy as np from attrs import define, field from .. import components, datatypes from .._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .view_coordinates_ext import ViewCoordinatesExt @@ -137,6 +140,45 @@ def clear_fields(cls) -> ViewCoordinates: ) return inst + @classmethod + def columns( + cls, + *, + xyz: datatypes.ViewCoordinatesArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + xyz: + The directions of the [x, y, z] axes. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + xyz=xyz, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + xyz: components.ViewCoordinatesBatch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py index 2b53b09669244..4fc7517a9d9b6 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py @@ -7,9 +7,12 @@ from typing import Any +import numpy as np from attrs import define, field from rerun._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -206,6 +209,81 @@ def clear_fields(cls) -> AffixFuzzer1: ) return inst + @classmethod + def columns( + cls, + *, + fuzz1001: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1002: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1003: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1004: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1005: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1006: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1007: components.AffixFuzzer7ArrayLike | None = None, + fuzz1008: components.AffixFuzzer8ArrayLike | None = None, + fuzz1009: components.AffixFuzzer9ArrayLike | None = None, + fuzz1010: components.AffixFuzzer10ArrayLike | None = None, + fuzz1011: components.AffixFuzzer11ArrayLike | None = None, + fuzz1012: components.AffixFuzzer12ArrayLike | None = None, + fuzz1013: components.AffixFuzzer13ArrayLike | None = None, + fuzz1014: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz1015: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz1016: components.AffixFuzzer16ArrayLike | None = None, + fuzz1017: components.AffixFuzzer17ArrayLike | None = None, + fuzz1018: components.AffixFuzzer18ArrayLike | None = None, + fuzz1019: datatypes.AffixFuzzer5ArrayLike | None = None, + fuzz1020: datatypes.AffixFuzzer20ArrayLike | None = None, + fuzz1021: datatypes.AffixFuzzer21ArrayLike | None = None, + fuzz1022: datatypes.AffixFuzzer22ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + fuzz1001=fuzz1001, + fuzz1002=fuzz1002, + fuzz1003=fuzz1003, + fuzz1004=fuzz1004, + fuzz1005=fuzz1005, + fuzz1006=fuzz1006, + fuzz1007=fuzz1007, + fuzz1008=fuzz1008, + fuzz1009=fuzz1009, + fuzz1010=fuzz1010, + fuzz1011=fuzz1011, + fuzz1012=fuzz1012, + fuzz1013=fuzz1013, + fuzz1014=fuzz1014, + fuzz1015=fuzz1015, + fuzz1016=fuzz1016, + fuzz1017=fuzz1017, + fuzz1018=fuzz1018, + fuzz1019=fuzz1019, + fuzz1020=fuzz1020, + fuzz1021=fuzz1021, + fuzz1022=fuzz1022, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + fuzz1001: components.AffixFuzzer1Batch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py index 6d1c623d2ec2f..6d26d193206af 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py @@ -7,9 +7,12 @@ from typing import Any +import numpy as np from attrs import define, field from rerun._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -188,6 +191,75 @@ def clear_fields(cls) -> AffixFuzzer2: ) return inst + @classmethod + def columns( + cls, + *, + fuzz1101: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1102: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1103: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1104: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1105: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1106: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1107: components.AffixFuzzer7ArrayLike | None = None, + fuzz1108: components.AffixFuzzer8ArrayLike | None = None, + fuzz1109: components.AffixFuzzer9ArrayLike | None = None, + fuzz1110: components.AffixFuzzer10ArrayLike | None = None, + fuzz1111: components.AffixFuzzer11ArrayLike | None = None, + fuzz1112: components.AffixFuzzer12ArrayLike | None = None, + fuzz1113: components.AffixFuzzer13ArrayLike | None = None, + fuzz1114: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz1115: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz1116: components.AffixFuzzer16ArrayLike | None = None, + fuzz1117: components.AffixFuzzer17ArrayLike | None = None, + fuzz1118: components.AffixFuzzer18ArrayLike | None = None, + fuzz1122: datatypes.AffixFuzzer22ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + fuzz1101=fuzz1101, + fuzz1102=fuzz1102, + fuzz1103=fuzz1103, + fuzz1104=fuzz1104, + fuzz1105=fuzz1105, + fuzz1106=fuzz1106, + fuzz1107=fuzz1107, + fuzz1108=fuzz1108, + fuzz1109=fuzz1109, + fuzz1110=fuzz1110, + fuzz1111=fuzz1111, + fuzz1112=fuzz1112, + fuzz1113=fuzz1113, + fuzz1114=fuzz1114, + fuzz1115=fuzz1115, + fuzz1116=fuzz1116, + fuzz1117=fuzz1117, + fuzz1118=fuzz1118, + fuzz1122=fuzz1122, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + fuzz1101: components.AffixFuzzer1Batch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py index a78d6215b1445..4498bfa257672 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py @@ -7,9 +7,12 @@ from typing import Any +import numpy as np from attrs import define, field from rerun._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -183,6 +186,73 @@ def clear_fields(cls) -> AffixFuzzer3: ) return inst + @classmethod + def columns( + cls, + *, + fuzz2001: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2002: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2003: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2004: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2005: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2006: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2007: components.AffixFuzzer7ArrayLike | None = None, + fuzz2008: components.AffixFuzzer8ArrayLike | None = None, + fuzz2009: components.AffixFuzzer9ArrayLike | None = None, + fuzz2010: components.AffixFuzzer10ArrayLike | None = None, + fuzz2011: components.AffixFuzzer11ArrayLike | None = None, + fuzz2012: components.AffixFuzzer12ArrayLike | None = None, + fuzz2013: components.AffixFuzzer13ArrayLike | None = None, + fuzz2014: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz2015: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz2016: components.AffixFuzzer16ArrayLike | None = None, + fuzz2017: components.AffixFuzzer17ArrayLike | None = None, + fuzz2018: components.AffixFuzzer18ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + fuzz2001=fuzz2001, + fuzz2002=fuzz2002, + fuzz2003=fuzz2003, + fuzz2004=fuzz2004, + fuzz2005=fuzz2005, + fuzz2006=fuzz2006, + fuzz2007=fuzz2007, + fuzz2008=fuzz2008, + fuzz2009=fuzz2009, + fuzz2010=fuzz2010, + fuzz2011=fuzz2011, + fuzz2012=fuzz2012, + fuzz2013=fuzz2013, + fuzz2014=fuzz2014, + fuzz2015=fuzz2015, + fuzz2016=fuzz2016, + fuzz2017=fuzz2017, + fuzz2018=fuzz2018, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + fuzz2001: components.AffixFuzzer1Batch | None = field( metadata={"component": True}, default=None, diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py index 0dd2c12241f0a..57f86b92ba500 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py @@ -7,9 +7,12 @@ from typing import Any +import numpy as np from attrs import define, field from rerun._baseclasses import ( Archetype, + ComponentColumnList, + DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -183,6 +186,73 @@ def clear_fields(cls) -> AffixFuzzer4: ) return inst + @classmethod + def columns( + cls, + *, + fuzz2101: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2102: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2103: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2104: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2105: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2106: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2107: components.AffixFuzzer7ArrayLike | None = None, + fuzz2108: components.AffixFuzzer8ArrayLike | None = None, + fuzz2109: components.AffixFuzzer9ArrayLike | None = None, + fuzz2110: components.AffixFuzzer10ArrayLike | None = None, + fuzz2111: components.AffixFuzzer11ArrayLike | None = None, + fuzz2112: components.AffixFuzzer12ArrayLike | None = None, + fuzz2113: components.AffixFuzzer13ArrayLike | None = None, + fuzz2114: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz2115: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz2116: components.AffixFuzzer16ArrayLike | None = None, + fuzz2117: components.AffixFuzzer17ArrayLike | None = None, + fuzz2118: components.AffixFuzzer18ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + fuzz2101=fuzz2101, + fuzz2102=fuzz2102, + fuzz2103=fuzz2103, + fuzz2104=fuzz2104, + fuzz2105=fuzz2105, + fuzz2106=fuzz2106, + fuzz2107=fuzz2107, + fuzz2108=fuzz2108, + fuzz2109=fuzz2109, + fuzz2110=fuzz2110, + fuzz2111=fuzz2111, + fuzz2112=fuzz2112, + fuzz2113=fuzz2113, + fuzz2114=fuzz2114, + fuzz2115=fuzz2115, + fuzz2116=fuzz2116, + fuzz2117=fuzz2117, + fuzz2118=fuzz2118, + ) + + batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + if len(batches) == 0: + return ComponentColumnList([]) + + lengths = np.ones(len(batches[0]._batch.as_arrow_array())) + columns = [batch.partition(lengths) for batch in batches] + + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) + fuzz2101: components.AffixFuzzer1Batch | None = field( metadata={"component": True}, default=None, From 3fb2ac500f307226161fadb0b2250f26ef03ee7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ktu=C4=9F=20Karaka=C5=9Fl=C4=B1?= <20567087+goktug97@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:08:49 +0000 Subject: [PATCH 05/43] Fix CPU spike caused by hanging connection after socket closure (#8806) (#8810) --- .../utils/re_smart_channel/src/receive_set.rs | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/crates/utils/re_smart_channel/src/receive_set.rs b/crates/utils/re_smart_channel/src/receive_set.rs index 91123cdc17a4d..21b21c2dbc7fb 100644 --- a/crates/utils/re_smart_channel/src/receive_set.rs +++ b/crates/utils/re_smart_channel/src/receive_set.rs @@ -118,23 +118,15 @@ impl ReceiveSet { let mut rx = self.receivers.lock(); - loop { - rx.retain(|r| r.is_connected()); - if rx.is_empty() { - return Err(RecvError); - } - - let mut sel = Select::new(); - for r in rx.iter() { - sel.recv(&r.rx); - } - - let oper = sel.select(); - let index = oper.index(); - if let Ok(msg) = oper.recv(&rx[index].rx) { - return Ok(msg); - } + rx.retain(|r| r.is_connected()); + let mut sel = Select::new(); + for r in rx.iter() { + sel.recv(&r.rx); } + + let oper = sel.select(); + let index = oper.index(); + oper.recv(&rx[index].rx).map_err(|_err| RecvError) } /// Returns immediately if there is nothing to receive. From 8bb8e29055723df15f82c1c67e756757c1b02f79 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 27 Jan 2025 13:01:44 +0100 Subject: [PATCH 06/43] Remove `manual_indicator` snippet (#8817) This now goes against everything we're trying to teach users. --- .../all/archetypes/manual_indicator.cpp | 33 ------------------- .../all/archetypes/manual_indicator.py | 18 ---------- .../all/archetypes/manual_indicator.rs | 23 ------------- 3 files changed, 74 deletions(-) delete mode 100644 docs/snippets/all/archetypes/manual_indicator.cpp delete mode 100644 docs/snippets/all/archetypes/manual_indicator.py delete mode 100644 docs/snippets/all/archetypes/manual_indicator.rs diff --git a/docs/snippets/all/archetypes/manual_indicator.cpp b/docs/snippets/all/archetypes/manual_indicator.cpp deleted file mode 100644 index dd052a4dcd9f5..0000000000000 --- a/docs/snippets/all/archetypes/manual_indicator.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Shows how to manually associate one or more indicator components with arbitrary data. - -#include - -#include - -int main() { - const auto rec = rerun::RecordingStream("rerun_example_manual_indicator"); - rec.spawn().exit_on_failure(); - - std::vector positions = { - {0.0, 0.0, 0.0}, - {10.0, 0.0, 0.0}, - {0.0, 10.0, 0.0}, - }; - std::vector colors = { - {255, 0, 0}, - {0, 255, 0}, - {0, 0, 255}, - }; - std::vector radii = {1.0}; - - // Specify both a Mesh3D and a Points3D indicator component so that the data is shown as both a - // 3D mesh _and_ a point cloud by default. - rec.log( - "points_and_mesh", - rerun::Points3D::IndicatorComponent(), - rerun::Mesh3D::IndicatorComponent(), - positions, - colors, - radii - ); -} diff --git a/docs/snippets/all/archetypes/manual_indicator.py b/docs/snippets/all/archetypes/manual_indicator.py deleted file mode 100644 index 86e4970e8dea5..0000000000000 --- a/docs/snippets/all/archetypes/manual_indicator.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Shows how to manually associate one or more indicator components with arbitrary data.""" - -import rerun as rr - -rr.init("rerun_example_manual_indicator", spawn=True) - -# Specify both a Mesh3D and a Points3D indicator component so that the data is shown as both a -# 3D mesh _and_ a point cloud by default. -rr.log( - "points_and_mesh", - [ - rr.Points3D.indicator(), - rr.Mesh3D.indicator(), - rr.components.Position3DBatch([[0.0, 0.0, 0.0], [10.0, 0.0, 0.0], [0.0, 10.0, 0.0]]), - rr.components.ColorBatch([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), - rr.components.RadiusBatch([1.0]), - ], -) diff --git a/docs/snippets/all/archetypes/manual_indicator.rs b/docs/snippets/all/archetypes/manual_indicator.rs deleted file mode 100644 index c5c66ce393133..0000000000000 --- a/docs/snippets/all/archetypes/manual_indicator.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Shows how to manually associate one or more indicator components with arbitrary data. - -use rerun::Archetype as _; - -fn main() -> Result<(), Box> { - let rec = rerun::RecordingStreamBuilder::new("rerun_example_manual_indicator").spawn()?; - - // Specify both a Mesh3D and a Points3D indicator component so that the data is shown as both a - // 3D mesh _and_ a point cloud by default. - rec.log( - "points_and_mesh", - &[ - &rerun::Points3D::indicator() as &dyn rerun::ComponentBatch, - &rerun::Mesh3D::indicator() as _, - &[[0.0, 0.0, 0.0], [10.0, 0.0, 0.0], [0.0, 10.0, 0.0]].map(rerun::Position3D::from), - &[[255, 0, 0], [0, 255, 0], [0, 0, 255]] - .map(|[r, g, b]| rerun::Color::from_rgb(r, g, b)), - &[1.0].map(rerun::Radius::from), - ], - )?; - - Ok(()) -} From 4dfe62b3e5bdb7055b611c76b482fdd887e2e055 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 27 Jan 2025 13:02:00 +0100 Subject: [PATCH 07/43] Remove component-driven sections from snippet index (#8818) We're trying to get users away from raw components now, so this is counter-productive. --- .../src/codegen/docs/snippets_ref.rs | 36 +----- docs/snippets/INDEX.md | 120 +----------------- 2 files changed, 2 insertions(+), 154 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs b/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs index ba043dc4caa1a..f00996a70106e 100644 --- a/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs +++ b/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs @@ -63,9 +63,7 @@ struct Snippet<'o> { struct Snippets<'o> { per_feature: BTreeMap>>, per_archetype: BTreeMap<&'o Object, Vec>>, - per_component: BTreeMap<&'o Object, Vec>>, per_archetype_blueprint: BTreeMap<&'o Object, Vec>>, - per_component_blueprint: BTreeMap<&'o Object, Vec>>, per_view: BTreeMap<&'o Object, Vec>>, } @@ -74,9 +72,7 @@ impl<'o> Snippets<'o> { let Self { per_feature, per_archetype, - per_component, per_archetype_blueprint, - per_component_blueprint, per_view, } = self; @@ -94,10 +90,8 @@ impl<'o> Snippets<'o> { }; merge_extend(per_archetype, rhs.per_archetype); - merge_extend(per_component, rhs.per_component); merge_extend(per_view, rhs.per_view); merge_extend(per_archetype_blueprint, rhs.per_archetype_blueprint); - merge_extend(per_component_blueprint, rhs.per_component_blueprint); } } @@ -329,9 +323,7 @@ impl SnippetsRefCodeGenerator { .join("\n"); let per_archetype_table = snippets_table(&snippets.per_archetype)?; - let per_component_table = snippets_table(&snippets.per_component)?; let per_archetype_blueprint_table = snippets_table(&snippets.per_archetype_blueprint)?; - let per_component_blueprint_table = snippets_table(&snippets.per_component_blueprint)?; let per_view_table = snippets_table(&snippets.per_view)?; let autogen_warning = format!( @@ -349,7 +341,7 @@ impl SnippetsRefCodeGenerator { This file acts as an index reference for all of our [snippets](./README.md). -Use it to quickly find copy-pastable snippets of code for any Rerun feature you're interested in (API, Archetypes, Components, etc). +Use it to quickly find copy-pastable snippets of code for any Rerun feature you're interested in (APIs, Archetypes, Blueprint, etc). --- @@ -357,10 +349,8 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' * [Features](#features) * [Types](#types) * [Archetypes](#archetypes) - * [Components](#components) * [Views](#views-blueprint) * [Archetypes (blueprint)](#archetypes-blueprint) - * [Components (blueprint)](#components-blueprint) ## Features @@ -370,7 +360,6 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' {per_feature_table} - ## Types @@ -383,15 +372,6 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty {per_archetype_table} -### Components - -_All snippets, organized by the [`Component`](https://rerun.io/docs/reference/types/components)(s) they use._ - -| Component | Snippet | Description | Python | Rust | C+⁠+ | -| --------- | ------- | ----------- | ------ | ---- | --- | -{per_component_table} - - ### Views (blueprint) _All snippets, organized by the [`View`](https://rerun.io/docs/reference/types/views)(s) they use._ @@ -408,15 +388,6 @@ _All snippets, organized by the blueprint-related [`Archetype`](https://rerun.io | Archetype | Snippet | Description | Python | Rust | C+⁠+ | | --------- | ------- | ----------- | ------ | ---- | --- | {per_archetype_blueprint_table} - - -### Components (blueprint) - -_All snippets, organized by the blueprint-related [`Component`](https://rerun.io/docs/reference/types/components)(s) they use._ - -| Component | Snippet | Description | Python | Rust | C+⁠+ | -| --------- | ------- | ----------- | ------ | ---- | --- | -{per_component_blueprint_table} " ); @@ -535,16 +506,11 @@ fn collect_snippets_recursively<'o>( } for (objs, index) in [ (&snippet.archetypes, &mut snippets.per_archetype), - (&snippet.components, &mut snippets.per_component), (&snippet.views, &mut snippets.per_view), ( &snippet.archetypes_blueprint, &mut snippets.per_archetype_blueprint, ), - ( - &snippet.components_blueprint, - &mut snippets.per_component_blueprint, - ), ] { for obj in objs { index.entry(obj).or_default().push(snippet.clone()); diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index 73583a94719c1..ba4ba24371559 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -4,7 +4,7 @@ This file acts as an index reference for all of our [snippets](./README.md). -Use it to quickly find copy-pastable snippets of code for any Rerun feature you're interested in (API, Archetypes, Components, etc). +Use it to quickly find copy-pastable snippets of code for any Rerun feature you're interested in (APIs, Archetypes, Blueprint, etc). --- @@ -12,10 +12,8 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' * [Features](#features) * [Types](#types) * [Archetypes](#archetypes) - * [Components](#components) * [Views](#views-blueprint) * [Archetypes (blueprint)](#archetypes-blueprint) - * [Components (blueprint)](#components-blueprint) ## Features @@ -37,7 +35,6 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' | **Send partial updates** | `transform3d_partial_updates` | Log different transforms with visualized coordinates axes | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.cpp) | - ## Types @@ -198,94 +195,6 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`ViewCoordinates`](https://rerun.io/docs/reference/types/archetypes/view_coordinates)** | `archetypes⁠/⁠transform3d_hierarchy` | Logs a transforms transform hierarchy | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.cpp) | -### Components - -_All snippets, organized by the [`Component`](https://rerun.io/docs/reference/types/components)(s) they use._ - -| Component | Snippet | Description | Python | Rust | C+⁠+ | -| --------- | ------- | ----------- | ------ | ---- | --- | -| **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `tutorials⁠/⁠annotation_context` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/annotation_context.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/annotation_context.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/annotation_context.cpp) | -| **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes⁠/⁠annotation_context_segmentation` | Log a segmentation image with annotations | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_segmentation.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_segmentation.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_segmentation.cpp) | -| **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes⁠/⁠annotation_context_rects` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_rects.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_rects.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_rects.cpp) | -| **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes⁠/⁠annotation_context_connections` | Log annotation context with connections between keypoints | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.cpp) | -| **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes⁠/⁠segmentation_image_simple` | Create and log a segmentation image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.cpp) | -| **[`ClassId`](https://rerun.io/docs/reference/types/components/class_id)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠viscomp-component-default` | Add a component default | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-component-default.py) | | | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠viscomp-component-override` | Override a component | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-component-override.py) | | | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠viscomp-visualizer-override` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override.py) | | | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts⁠/⁠viscomp-visualizer-override-multiple` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override-multiple.py) | | | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `descriptors⁠/⁠descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp) | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `views⁠/⁠spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | -| **[`FillMode`](https://rerun.io/docs/reference/types/components/fill_mode)** | `archetypes⁠/⁠transform3d_partial_updates` | Log different transforms with visualized coordinates axes | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.cpp) | -| **[`GeoLineString`](https://rerun.io/docs/reference/types/components/geo_line_string)** | `archetypes⁠/⁠geo_line_strings_simple` | Log a simple geospatial line string | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.cpp) | -| **[`GraphEdge`](https://rerun.io/docs/reference/types/components/graph_edge)** | `archetypes⁠/⁠graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp) | -| **[`GraphEdge`](https://rerun.io/docs/reference/types/components/graph_edge)** | `archetypes⁠/⁠graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp) | -| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `archetypes⁠/⁠graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp) | -| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `archetypes⁠/⁠graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp) | -| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `views⁠/⁠graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | -| **[`ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer)** | `archetypes⁠/⁠image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | -| **[`ImageFormat`](https://rerun.io/docs/reference/types/components/image_format)** | `archetypes⁠/⁠image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | -| **[`KeypointId`](https://rerun.io/docs/reference/types/components/keypoint_id)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`MediaType`](https://rerun.io/docs/reference/types/components/media_type)** | `archetypes⁠/⁠text_document` | Log a `TextDocument` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.cpp) | -| **[`MediaType`](https://rerun.io/docs/reference/types/components/media_type)** | `views⁠/⁠text_document` | Use a blueprint to show a text document | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_document.py) | | | -| **[`Plane3D`](https://rerun.io/docs/reference/types/components/plane3d)** | `views⁠/⁠spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes⁠/⁠mesh3d_partial_updates` | Log a simple colored triangle, then update its vertices' positions each frame | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors⁠/⁠descr_builtin_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors⁠/⁠descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors⁠/⁠descr_custom_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠points3d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_ui_radius.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠points2d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠line_strips3d_ui_radius` | Log lines with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips3d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips3d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips3d_ui_radius.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠line_strips2d_ui_radius` | Log lines with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠geo_line_strings_simple` | Log a simple geospatial line string | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠geo_points_simple` | Log some very simple geospatial point | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `concepts⁠/⁠different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `views⁠/⁠map` | Use a blueprint to customize a map view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/map.py) | | | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠capsules3d_batch` | Log a batch of capsules | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.cpp) | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠instance_poses3d_combined` | Log a simple 3D box with a regular & instance pose transform | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.cpp) | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠mesh3d_instancing` | Log a simple 3D mesh with several instance pose transforms which instantiate the mesh several times and will not affect its children (known as mesh instancing) | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_instancing.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_instancing.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_instancing.cpp) | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠transform3d_axes` | Log different transforms with visualized coordinates axes | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_axes.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_axes.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_axes.cpp) | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠transform3d_hierarchy` | Logs a transforms transform hierarchy | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.cpp) | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠transform3d_partial_updates` | Log different transforms with visualized coordinates axes | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.cpp) | -| **[`RotationAxisAngle`](https://rerun.io/docs/reference/types/components/rotation_axis_angle)** | `archetypes⁠/⁠transform3d_simple` | Log different transforms between three arrows | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_simple.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `archetypes⁠/⁠scalar_simple` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_simple.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `archetypes⁠/⁠scalar_send_columns` | Use the `send_columns` API to send scalars over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_send_columns.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `archetypes⁠/⁠scalar_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `archetypes⁠/⁠series_line_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `archetypes⁠/⁠series_point_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `tutorials⁠/⁠data_out` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/data_out.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `tutorials⁠/⁠fixed_window_plot` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/fixed_window_plot.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `tutorials⁠/⁠visualizer-overrides` | Log a scalar over time and override the visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualizer-overrides.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `views⁠/⁠dataframe` | Use a blueprint to customize a DataframeView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/dataframe.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `views⁠/⁠tensor` | Use a blueprint to show a tensor view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/tensor.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | -| **[`ShowLabels`](https://rerun.io/docs/reference/types/components/show_labels)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`TensorDimensionIndexSelection`](https://rerun.io/docs/reference/types/components/tensor_dimension_index_selection)** | `views⁠/⁠tensor` | Use a blueprint to show a tensor view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/tensor.py) | | | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `views⁠/⁠text_log` | Use a blueprint to show a text log | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_log.py) | | | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `views⁠/⁠text_document` | Use a blueprint to show a text document | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_document.py) | | | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes⁠/⁠text_log_integration` | Shows integration of Rerun's `TextLog` with the native logging interface | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log_integration.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log_integration.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log_integration.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes⁠/⁠text_log` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes⁠/⁠text_document` | Log a `TextDocument` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes⁠/⁠entity_path` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/entity_path.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/entity_path.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/entity_path.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `concepts⁠/⁠app-model⁠/⁠native-async` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-async.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-async.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-async.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `concepts⁠/⁠app-model⁠/⁠native-sync` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-sync.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-sync.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-sync.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `tutorials⁠/⁠data_out` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/data_out.py) | | | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `tutorials⁠/⁠visualization⁠/⁠save_blueprint` | Craft an example blueprint with the python API and save it to a file for future use | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualization/save_blueprint.py) | | | -| **[`TextLogLevel`](https://rerun.io/docs/reference/types/components/text_log_level)** | `archetypes⁠/⁠text_log` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.cpp) | -| **[`TextLogLevel`](https://rerun.io/docs/reference/types/components/text_log_level)** | `archetypes⁠/⁠text_log_integration` | Shows integration of Rerun's `TextLog` with the native logging interface | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log_integration.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log_integration.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log_integration.cpp) | -| **[`TextLogLevel`](https://rerun.io/docs/reference/types/components/text_log_level)** | `views⁠/⁠text_log` | Use a blueprint to show a text log | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_log.py) | | | -| **[`VideoTimestamp`](https://rerun.io/docs/reference/types/components/video_timestamp)** | `archetypes⁠/⁠video_auto_frames` | Log a video asset using automatically determined frame references | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/video_auto_frames.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/video_auto_frames.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/video_auto_frames.cpp) | -| **[`ViewCoordinates`](https://rerun.io/docs/reference/types/components/view_coordinates)** | `archetypes⁠/⁠view_coordinates_simple` | Change the view coordinates for the scene | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/view_coordinates_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/view_coordinates_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/view_coordinates_simple.cpp) | -| **[`ViewCoordinates`](https://rerun.io/docs/reference/types/components/view_coordinates)** | `archetypes⁠/⁠asset3d_simple` | Log a simple 3D asset | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/asset3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/asset3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/asset3d_simple.cpp) | -| **[`ViewCoordinates`](https://rerun.io/docs/reference/types/components/view_coordinates)** | `archetypes⁠/⁠pinhole_perspective` | Logs a point cloud and a perspective camera looking at it | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/pinhole_perspective.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/pinhole_perspective.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/pinhole_perspective.cpp) | -| **[`ViewCoordinates`](https://rerun.io/docs/reference/types/components/view_coordinates)** | `archetypes⁠/⁠transform3d_hierarchy` | Logs a transforms transform hierarchy | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.cpp) | - - ### Views (blueprint) _All snippets, organized by the [`View`](https://rerun.io/docs/reference/types/views)(s) they use._ @@ -352,30 +261,3 @@ _All snippets, organized by the blueprint-related [`Archetype`](https://rerun.io | **`VisualBounds2D`** | `tutorials⁠/⁠extra_values` | Log extra values with a `Points2D` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.rs) | | | **`VisualBounds2D`** | `views⁠/⁠graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **`VisualBounds2D`** | `views⁠/⁠spatial2d` | Use a blueprint to customize a Spatial2DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial2d.py) | | | - - -### Components (blueprint) - -_All snippets, organized by the blueprint-related [`Component`](https://rerun.io/docs/reference/types/components)(s) they use._ - -| Component | Snippet | Description | Python | Rust | C+⁠+ | -| --------- | ------- | ----------- | ------ | ---- | --- | -| **`MapProvider`** | `views⁠/⁠map` | Use a blueprint to customize a map view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/map.py) | | | -| **`Visible`** | `tutorials⁠/⁠fixed_window_plot` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/fixed_window_plot.py) | | | -| **`Visible`** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | -| **`VisibleTimeRange`** | `tutorials⁠/⁠fixed_window_plot` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/fixed_window_plot.py) | | | -| **`VisibleTimeRange`** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | -| **`VisualBounds2D`** | `archetypes⁠/⁠line_strips2d_batch` | Log a batch of 2D line strips | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_batch.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_batch.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_batch.cpp) | -| **`VisualBounds2D`** | `archetypes⁠/⁠line_strips2d_segments_simple` | Log a couple 2D line segments using 2D line strips | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_segments_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_segments_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_segments_simple.cpp) | -| **`VisualBounds2D`** | `archetypes⁠/⁠line_strips2d_simple` | Log a simple line strip | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_simple.cpp) | -| **`VisualBounds2D`** | `archetypes⁠/⁠line_strips2d_ui_radius` | Log lines with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.cpp) | -| **`VisualBounds2D`** | `archetypes⁠/⁠points2d_random` | Log some random points with color and radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_random.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_random.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_random.cpp) | -| **`VisualBounds2D`** | `archetypes⁠/⁠points2d_simple` | Log some very simple points | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_simple.cpp) | -| **`VisualBounds2D`** | `archetypes⁠/⁠points2d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.cpp) | -| **`VisualBounds2D`** | `concepts⁠/⁠different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | -| **`VisualBounds2D`** | `tutorials⁠/⁠extra_values` | Log extra values with a `Points2D` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.rs) | | -| **`VisualBounds2D`** | `views⁠/⁠graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | -| **`VisualBounds2D`** | `views⁠/⁠spatial2d` | Use a blueprint to customize a Spatial2DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial2d.py) | | | -| **`VisualizerOverrides`** | `concepts⁠/⁠viscomp-visualizer-override` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override.py) | | | -| **`VisualizerOverrides`** | `concepts⁠/⁠viscomp-visualizer-override-multiple` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override-multiple.py) | | | -| **`VisualizerOverrides`** | `tutorials⁠/⁠visualizer-overrides` | Log a scalar over time and override the visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualizer-overrides.py) | | | From 06976a36e808eae1c0879844269c7c92cc3d30d0 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Mon, 27 Jan 2025 08:49:10 -0500 Subject: [PATCH 08/43] Include a python API for routing time control commands to the notebook instance (#8809) ### Related - https://github.com/rerun-io/rerun/pull/8673 ### What The linked PR added support for using javascript to update the time controls. Routing this into python when working in the context of a notebook unlocks lots of interesting interactive behavior. This does not yet expose the reverse of generating python callback events based on rerun time cursor changes, but that would be an obvious next step. --- rerun_notebook/src/js/widget.ts | 29 ++++++++++++++ rerun_notebook/src/rerun_notebook/__init__.py | 10 +++++ rerun_py/rerun_sdk/rerun/notebook.py | 40 +++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/rerun_notebook/src/js/widget.ts b/rerun_notebook/src/js/widget.ts index f6333c00bcc32..795e755cf1667 100644 --- a/rerun_notebook/src/js/widget.ts +++ b/rerun_notebook/src/js/widget.ts @@ -43,6 +43,8 @@ class ViewerWidget { model.on("msg:custom", this.on_custom_message); + model.on("change:_time_ctrl", (_, [timeline, time, play]) => this.on_time_ctrl(null, timeline, time, play)); + this.viewer.on("ready", () => { this.channel = this.viewer.open_channel("temp"); @@ -122,6 +124,33 @@ class ViewerWidget { console.log("unknown message type", msg, buffers); } }; + + on_time_ctrl = (_: unknown, timeline: string | null, time: number | null, play: boolean) => { + let recording_id = this.viewer.get_active_recording_id(); + if (recording_id === null) { + return; + } + + let active_timeline = this.viewer.get_active_timeline(recording_id); + + if (timeline === null) { + timeline = active_timeline; + } + + if (timeline === null) { + return; + } + + if (timeline !== active_timeline) { + this.viewer.set_active_timeline(recording_id, timeline); + } + + this.viewer.set_playing(recording_id, play); + + if (time !== null) { + this.viewer.set_current_time(recording_id, timeline, time); + } + } } const render: Render = ({ model, el }) => { diff --git a/rerun_notebook/src/rerun_notebook/__init__.py b/rerun_notebook/src/rerun_notebook/__init__.py index 763c056ffa0b3..afb0996cdf625 100644 --- a/rerun_notebook/src/rerun_notebook/__init__.py +++ b/rerun_notebook/src/rerun_notebook/__init__.py @@ -68,6 +68,13 @@ class Viewer(anywidget.AnyWidget): _ready = False _data_queue: list[bytes] + _time_ctrl = traitlets.Tuple( + traitlets.Unicode(allow_none=True), + traitlets.Int(allow_none=True), + traitlets.Bool(), + allow_none=True, + ).tag(sync=True) + def __init__( self, *, @@ -122,3 +129,6 @@ def block_until_ready(self, timeout=5.0) -> None: return poll(1) time.sleep(0.1) + + def set_time_ctrl(self, timeline: str | None, time: int | None, play: bool) -> None: + self._time_ctrl = (timeline, time, play) diff --git a/rerun_py/rerun_sdk/rerun/notebook.py b/rerun_py/rerun_sdk/rerun/notebook.py index 0fc161ebe4d6b..1bc5d5a6e3981 100644 --- a/rerun_py/rerun_sdk/rerun/notebook.py +++ b/rerun_py/rerun_sdk/rerun/notebook.py @@ -151,6 +151,46 @@ def _repr_mimebundle_(self, **kwargs: dict) -> tuple[dict, dict] | None: # type def _repr_keys(self): # type: ignore[no-untyped-def] return self._viewer._repr_keys() + def set_time_ctrl( + self, + *, + sequence: int | None = None, + nanoseconds: int | None = None, + seconds: float | None = None, + timeline: str | None = None, + play: bool = False, + ) -> None: + """ + Set the time control for the viewer. + + Parameters + ---------- + sequence: int + The sequence number to set the viewer to. + seconds: float + The time in seconds to set the viewer to. + nanoseconds: int + The time in nanoseconds to set the viewer to. + play: bool + Whether to start playing from the specified time point. Defaults to paused. + timeline : str + The name of the timeline to switch to. If not provided, time will remain on the current timeline. + + """ + if sum([sequence is not None, nanoseconds is not None, seconds is not None]) > 1: + raise ValueError("At most one of sequence, nanoseconds, or seconds may be provided") + + if sequence is not None: + time = sequence + elif nanoseconds is not None: + time = nanoseconds + elif seconds is not None: + time = int(seconds * 1e9) + else: + time = None + + self._viewer.set_time_ctrl(timeline, time, play) + def notebook_show( *, From 627050114eefb00b5153dc8aaf00f94c725eb503 Mon Sep 17 00:00:00 2001 From: Gijs de Jong <14833076+oxkitsune@users.noreply.github.com> Date: Mon, 27 Jan 2025 18:24:59 +0100 Subject: [PATCH 09/43] Add hint for missing web viewer when building `re_web_viewer_server` (#8832) --- crates/viewer/re_web_viewer_server/build.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/viewer/re_web_viewer_server/build.rs b/crates/viewer/re_web_viewer_server/build.rs index 6eafd13368d17..7d38e17803d11 100644 --- a/crates/viewer/re_web_viewer_server/build.rs +++ b/crates/viewer/re_web_viewer_server/build.rs @@ -1,4 +1,14 @@ +use std::path::Path; + fn main() { // https://blog.rust-lang.org/2024/05/06/check-cfg.html println!("cargo::rustc-check-cfg=cfg(disable_web_viewer_server)"); + + let viewer_js_path = Path::new("./web_viewer/re_viewer.js"); + let viewer_wasm_path = Path::new("./web_viewer/re_viewer_bg.wasm"); + + assert!( + viewer_js_path.exists() && viewer_wasm_path.exists(), + "Web viewer not found, run `pixi run rerun-build-web` to build it!" + ); } From 7eb37355072c9af9a9fb19055f7f96f8abd58bbc Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 27 Jan 2025 19:53:05 +0100 Subject: [PATCH 10/43] Fix python Windows unicode issues (maybe) (#8830) --- .../viewer/re_viewer_context/src/typed_entity_collections.rs | 2 +- scripts/ci/rust_checks.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/viewer/re_viewer_context/src/typed_entity_collections.rs b/crates/viewer/re_viewer_context/src/typed_entity_collections.rs index 3f99b269c0986..fe5e33eebd40a 100644 --- a/crates/viewer/re_viewer_context/src/typed_entity_collections.rs +++ b/crates/viewer/re_viewer_context/src/typed_entity_collections.rs @@ -45,7 +45,7 @@ impl std::ops::Deref for IndicatedEntities { /// /// It gets invalidated whenever any properties of the respective view instance /// change, e.g. its origin. -/// TODO(andreas): Unclear if any of the view's configuring blueprint entities are included in this! +/// TODO(andreas): Unclear if any of the view's configuring blueprint entities are included in this. /// /// This is a subset of [`MaybeVisualizableEntities`] and may differs on a per view instance base! #[derive(Default, Clone, Debug)] diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py index 2f52a1b9c7ecb..5d103df3c49d7 100755 --- a/scripts/ci/rust_checks.py +++ b/scripts/ci/rust_checks.py @@ -92,6 +92,9 @@ def package_name_from_cargo_toml(cargo_toml_path: str) -> str: def main() -> None: + # Ensure we can print unicode characters. Has been historically an issue on Windows CI. + sys.stdout.reconfigure(encoding="utf-8") + checks = [ ("base_checks", base_checks), ("sdk_variations", sdk_variations), From fd69df369a0666e3d3a312200190a4fc89937107 Mon Sep 17 00:00:00 2001 From: Gijs de Jong <14833076+oxkitsune@users.noreply.github.com> Date: Mon, 27 Jan 2025 20:32:16 +0100 Subject: [PATCH 11/43] Disable web viewer file check in ci (#8834) --- crates/viewer/re_web_viewer_server/build.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/viewer/re_web_viewer_server/build.rs b/crates/viewer/re_web_viewer_server/build.rs index 7d38e17803d11..81baf5643200e 100644 --- a/crates/viewer/re_web_viewer_server/build.rs +++ b/crates/viewer/re_web_viewer_server/build.rs @@ -1,14 +1,16 @@ -use std::path::Path; - fn main() { // https://blog.rust-lang.org/2024/05/06/check-cfg.html println!("cargo::rustc-check-cfg=cfg(disable_web_viewer_server)"); - let viewer_js_path = Path::new("./web_viewer/re_viewer.js"); - let viewer_wasm_path = Path::new("./web_viewer/re_viewer_bg.wasm"); + // See `Cargo.toml` docs for the `__ci` feature for more information about the `disable_web_viewer_server` cfg. + #[cfg(not(feature = "__ci"))] + { + let viewer_js_path = std::path::Path::new("./web_viewer/re_viewer.js"); + let viewer_wasm_path = std::path::Path::new("./web_viewer/re_viewer_bg.wasm"); - assert!( - viewer_js_path.exists() && viewer_wasm_path.exists(), - "Web viewer not found, run `pixi run rerun-build-web` to build it!" - ); + assert!( + viewer_js_path.exists() && viewer_wasm_path.exists(), + "Web viewer not found, run `pixi run rerun-build-web` to build it!" + ); + } } From a2a0079bafbbc0c9d2240c38c6840df68e527ffa Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 28 Jan 2025 09:55:55 +0100 Subject: [PATCH 12/43] C++ `columns` method for convenient `send_columns` call through archetypes (#8828) --- .../src/codegen/cpp/includes.rs | 6 + .../src/codegen/cpp/method.rs | 7 +- .../re_types_builder/src/codegen/cpp/mod.rs | 119 ++++++++++--- .../all/archetypes/points3d_send_columns.cpp | 31 +--- docs/snippets/snippets.toml | 7 +- .../rerun/archetypes/annotation_context.cpp | 22 +++ .../rerun/archetypes/annotation_context.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/arrows2d.cpp | 77 ++++++++ rerun_cpp/src/rerun/archetypes/arrows2d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/arrows3d.cpp | 70 ++++++++ rerun_cpp/src/rerun/archetypes/arrows3d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/asset3d.cpp | 38 ++++ rerun_cpp/src/rerun/archetypes/asset3d.hpp | 17 ++ .../src/rerun/archetypes/asset_video.cpp | 29 +++ .../src/rerun/archetypes/asset_video.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/bar_chart.cpp | 30 ++++ rerun_cpp/src/rerun/archetypes/bar_chart.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/boxes2d.cpp | 76 ++++++++ rerun_cpp/src/rerun/archetypes/boxes2d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/boxes3d.cpp | 94 ++++++++++ rerun_cpp/src/rerun/archetypes/boxes3d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/capsules3d.cpp | 89 ++++++++++ rerun_cpp/src/rerun/archetypes/capsules3d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/clear.cpp | 23 +++ rerun_cpp/src/rerun/archetypes/clear.hpp | 17 ++ .../src/rerun/archetypes/depth_image.cpp | 70 ++++++++ .../src/rerun/archetypes/depth_image.hpp | 17 ++ .../src/rerun/archetypes/ellipsoids3d.cpp | 93 ++++++++++ .../src/rerun/archetypes/ellipsoids3d.hpp | 17 ++ .../src/rerun/archetypes/encoded_image.cpp | 44 +++++ .../src/rerun/archetypes/encoded_image.hpp | 17 ++ .../src/rerun/archetypes/geo_line_strings.cpp | 39 ++++ .../src/rerun/archetypes/geo_line_strings.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/geo_points.cpp | 44 +++++ rerun_cpp/src/rerun/archetypes/geo_points.hpp | 17 ++ .../src/rerun/archetypes/graph_edges.cpp | 29 +++ .../src/rerun/archetypes/graph_edges.hpp | 17 ++ .../src/rerun/archetypes/graph_nodes.cpp | 61 +++++++ .../src/rerun/archetypes/graph_nodes.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/image.cpp | 45 +++++ rerun_cpp/src/rerun/archetypes/image.hpp | 17 ++ .../src/rerun/archetypes/instance_poses3d.cpp | 57 ++++++ .../src/rerun/archetypes/instance_poses3d.hpp | 17 ++ .../src/rerun/archetypes/line_strips2d.cpp | 69 +++++++ .../src/rerun/archetypes/line_strips2d.hpp | 17 ++ .../src/rerun/archetypes/line_strips3d.cpp | 62 +++++++ .../src/rerun/archetypes/line_strips3d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/mesh3d.cpp | 93 ++++++++++ rerun_cpp/src/rerun/archetypes/mesh3d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/pinhole.cpp | 46 +++++ rerun_cpp/src/rerun/archetypes/pinhole.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/points2d.cpp | 77 ++++++++ rerun_cpp/src/rerun/archetypes/points2d.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/points3d.cpp | 70 ++++++++ rerun_cpp/src/rerun/archetypes/points3d.hpp | 46 ++--- rerun_cpp/src/rerun/archetypes/scalar.cpp | 22 +++ rerun_cpp/src/rerun/archetypes/scalar.hpp | 17 ++ .../rerun/archetypes/segmentation_image.cpp | 45 +++++ .../rerun/archetypes/segmentation_image.hpp | 17 ++ .../src/rerun/archetypes/series_line.cpp | 47 +++++ .../src/rerun/archetypes/series_line.hpp | 17 ++ .../src/rerun/archetypes/series_point.cpp | 47 +++++ .../src/rerun/archetypes/series_point.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/tensor.cpp | 31 ++++ rerun_cpp/src/rerun/archetypes/tensor.hpp | 17 ++ .../src/rerun/archetypes/text_document.cpp | 29 +++ .../src/rerun/archetypes/text_document.hpp | 17 ++ rerun_cpp/src/rerun/archetypes/text_log.cpp | 38 ++++ rerun_cpp/src/rerun/archetypes/text_log.hpp | 17 ++ .../src/rerun/archetypes/transform3d.cpp | 71 ++++++++ .../src/rerun/archetypes/transform3d.hpp | 17 ++ .../archetypes/video_frame_reference.cpp | 30 ++++ .../archetypes/video_frame_reference.hpp | 17 ++ .../src/rerun/archetypes/view_coordinates.cpp | 22 +++ .../src/rerun/archetypes/view_coordinates.hpp | 17 ++ .../rerun/blueprint/archetypes/background.cpp | 30 ++++ .../rerun/blueprint/archetypes/background.hpp | 17 ++ .../archetypes/container_blueprint.cpp | 77 ++++++++ .../archetypes/container_blueprint.hpp | 17 ++ .../blueprint/archetypes/dataframe_query.cpp | 56 ++++++ .../blueprint/archetypes/dataframe_query.hpp | 17 ++ .../blueprint/archetypes/force_center.cpp | 29 +++ .../blueprint/archetypes/force_center.hpp | 17 ++ .../archetypes/force_collision_radius.cpp | 37 ++++ .../archetypes/force_collision_radius.hpp | 17 ++ .../rerun/blueprint/archetypes/force_link.cpp | 36 ++++ .../rerun/blueprint/archetypes/force_link.hpp | 17 ++ .../blueprint/archetypes/force_many_body.cpp | 29 +++ .../blueprint/archetypes/force_many_body.hpp | 17 ++ .../blueprint/archetypes/force_position.cpp | 36 ++++ .../blueprint/archetypes/force_position.hpp | 17 ++ .../blueprint/archetypes/line_grid3d.cpp | 55 ++++++ .../blueprint/archetypes/line_grid3d.hpp | 17 ++ .../blueprint/archetypes/map_background.cpp | 21 +++ .../blueprint/archetypes/map_background.hpp | 17 ++ .../rerun/blueprint/archetypes/map_zoom.cpp | 22 +++ .../rerun/blueprint/archetypes/map_zoom.hpp | 17 ++ .../blueprint/archetypes/near_clip_plane.cpp | 23 +++ .../blueprint/archetypes/near_clip_plane.hpp | 17 ++ .../blueprint/archetypes/panel_blueprint.cpp | 22 +++ .../blueprint/archetypes/panel_blueprint.hpp | 17 ++ .../blueprint/archetypes/plot_legend.cpp | 30 ++++ .../blueprint/archetypes/plot_legend.hpp | 17 ++ .../blueprint/archetypes/scalar_axis.cpp | 29 +++ .../blueprint/archetypes/scalar_axis.hpp | 17 ++ .../archetypes/tensor_scalar_mapping.cpp | 36 ++++ .../archetypes/tensor_scalar_mapping.hpp | 17 ++ .../archetypes/tensor_slice_selection.cpp | 47 +++++ .../archetypes/tensor_slice_selection.hpp | 17 ++ .../blueprint/archetypes/tensor_view_fit.cpp | 22 +++ .../blueprint/archetypes/tensor_view_fit.hpp | 17 ++ .../blueprint/archetypes/view_blueprint.cpp | 49 +++++ .../blueprint/archetypes/view_blueprint.hpp | 17 ++ .../blueprint/archetypes/view_contents.cpp | 22 +++ .../blueprint/archetypes/view_contents.hpp | 17 ++ .../archetypes/viewport_blueprint.cpp | 56 ++++++ .../archetypes/viewport_blueprint.hpp | 17 ++ .../archetypes/visible_time_ranges.cpp | 22 +++ .../archetypes/visible_time_ranges.hpp | 17 ++ .../blueprint/archetypes/visual_bounds2d.cpp | 22 +++ .../blueprint/archetypes/visual_bounds2d.hpp | 17 ++ rerun_cpp/src/rerun/component_batch.cpp | 5 + rerun_cpp/src/rerun/component_batch.hpp | 3 + rerun_cpp/src/rerun/component_column.cpp | 16 +- rerun_cpp/src/rerun/component_column.hpp | 62 +++---- rerun_cpp/src/rerun/recording_stream.hpp | 84 +++++++++ .../generated/archetypes/affix_fuzzer1.cpp | 168 ++++++++++++++++++ .../generated/archetypes/affix_fuzzer1.hpp | 17 ++ .../generated/archetypes/affix_fuzzer2.cpp | 147 +++++++++++++++ .../generated/archetypes/affix_fuzzer2.hpp | 17 ++ .../generated/archetypes/affix_fuzzer3.cpp | 140 +++++++++++++++ .../generated/archetypes/affix_fuzzer3.hpp | 17 ++ .../generated/archetypes/affix_fuzzer4.cpp | 140 +++++++++++++++ .../generated/archetypes/affix_fuzzer4.hpp | 17 ++ 134 files changed, 4530 insertions(+), 125 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/cpp/includes.rs b/crates/build/re_types_builder/src/codegen/cpp/includes.rs index a3630364833de..e80ea83d35c65 100644 --- a/crates/build/re_types_builder/src/codegen/cpp/includes.rs +++ b/crates/build/re_types_builder/src/codegen/cpp/includes.rs @@ -89,6 +89,12 @@ impl Includes { self.insert_rerun(&format!("{path}/{typname}.hpp")); } } + + /// Remove all includes that are also in `other`. + pub fn remove_includes(&mut self, other: &Self) { + self.system.retain(|name| !other.system.contains(name)); + self.local.retain(|name| !other.local.contains(name)); + } } impl quote::ToTokens for Includes { diff --git a/crates/build/re_types_builder/src/codegen/cpp/method.rs b/crates/build/re_types_builder/src/codegen/cpp/method.rs index b54beb4196542..17b4a18036756 100644 --- a/crates/build/re_types_builder/src/codegen/cpp/method.rs +++ b/crates/build/re_types_builder/src/codegen/cpp/method.rs @@ -83,7 +83,12 @@ impl MethodDocumentation { Self::None => { quote!() } - Self::String(s) => quote_doc_comment(s), + Self::String(s) => { + let lines = s.lines().map(quote_doc_comment); + quote! { + #(#lines)* + } + } Self::Docs(docs) => { let lines = lines_from_docs(reporter, objects, docs); quote_doc_lines(&lines) diff --git a/crates/build/re_types_builder/src/codegen/cpp/mod.rs b/crates/build/re_types_builder/src/codegen/cpp/mod.rs index d8b85f7b371c3..ccb03882eb77e 100644 --- a/crates/build/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/build/re_types_builder/src/codegen/cpp/mod.rs @@ -449,7 +449,7 @@ impl QuotedObject { mut hpp_includes: Includes, hpp_type_extensions: &TokenStream, ) -> Self { - let type_ident = obj.ident(); + let archetype_type_ident = obj.ident(); let archetype_name = &obj.fqname; let quoted_docs = quote_obj_docs(reporter, objects, obj); @@ -503,7 +503,7 @@ impl QuotedObject { // Making the constructor explicit prevents all sort of strange errors. // (e.g. `Points3D({{0.0f, 0.0f, 0.0f}})` would previously be ambiguous with the move constructor?!) declaration: MethodDeclaration::constructor(quote! { - explicit #type_ident(#(#parameters),*) : #(#assignments),* + explicit #archetype_type_ident(#(#parameters),*) : #(#assignments),* }), ..Method::default() }); @@ -535,24 +535,24 @@ impl QuotedObject { // update_fields method - this is equivalent to the default constructor. methods.push(Method { - docs: format!("Update only some specific fields of a `{type_ident}`.").into(), + docs: format!("Update only some specific fields of a `{archetype_type_ident}`.").into(), declaration: MethodDeclaration { is_static: true, - return_type: quote!(#type_ident), + return_type: quote!(#archetype_type_ident), name_and_parameters: quote! { update_fields() }, }, definition_body: quote! { - return #type_ident(); + return #archetype_type_ident(); }, inline: true, }); // clear_fields method. methods.push(Method { - docs: format!("Clear all the fields of a `{type_ident}`.").into(), + docs: format!("Clear all the fields of a `{archetype_type_ident}`.").into(), declaration: MethodDeclaration { is_static: true, - return_type: quote!(#type_ident), + return_type: quote!(#archetype_type_ident), name_and_parameters: quote! { clear_fields() }, }, definition_body: { @@ -570,7 +570,7 @@ impl QuotedObject { }); quote! { - auto archetype = #type_ident(); + auto archetype = #archetype_type_ident(); #(#field_assignments)* return archetype; } @@ -591,7 +591,7 @@ impl QuotedObject { docs: obj_field.docs.clone().into(), declaration: MethodDeclaration { is_static: false, - return_type: quote!(#type_ident), + return_type: quote!(#archetype_type_ident), name_and_parameters: quote! { #method_ident(const #field_type& #parameter_ident) && }, @@ -605,6 +605,82 @@ impl QuotedObject { }); } + // columns method that allows partitioning into columns + hpp_includes.insert_rerun("component_column.hpp"); + methods.push(Method { + docs: unindent::unindent("\ + Partitions the component data into multiple sub-batches. + + Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + instead, via `ComponentColumn::from_batch_with_lengths`. + + This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + + The specified `lengths` must sum to the total length of the component batch. + ").into(), + declaration: MethodDeclaration { + is_static: false, + return_type: quote!(Collection), + name_and_parameters: quote! { columns(const Collection& lengths_) }, + }, + definition_body: { + // Plus 1 for the indicator column. + let num_fields = quote_integer(obj.fields.len() + 1); + let push_back_columns = obj.fields.iter().map(|field| { + let field_ident = field_name_ident(field); + quote! { + if (#field_ident.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths( + #field_ident.value(), lengths_ + ).value_or_throw()); + } + } + }); + + quote! { + std::vector columns; + columns.reserve(#num_fields); + #(#push_back_columns)* + columns.push_back( + ComponentColumn::from_indicators<#archetype_type_ident>(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + }, + inline: false, + }); + methods.push(Method { + docs: unindent::unindent( + "Partitions the component data into unit-length sub-batches. + + This is semantically similar to calling `columns` with `std::vector(n, 1)`, + where `n` is automatically guessed.", + ) + .into(), + declaration: MethodDeclaration { + is_static: false, + return_type: quote!(Collection), + name_and_parameters: quote! { columns() }, + }, + definition_body: { + let set_len = obj.fields.iter().map(|field| { + let field_ident = field_name_ident(field); + quote! { + if (#field_ident.has_value()) { + return columns(std::vector(#field_ident.value().length(), 1)); + } + } + }); + + quote! { + #(#set_len)* + return Collection(); + } + }, + inline: false, + }); + let quoted_namespace = if let Some(scope) = obj.scope() { let scope = format_ident!("{}", scope); quote! { #scope::archetypes } @@ -612,15 +688,15 @@ impl QuotedObject { quote! {archetypes} }; - let serialize_method = archetype_serialize(&type_ident, obj, &mut hpp_includes); + let serialize_method = archetype_serialize(&archetype_type_ident, obj, &mut hpp_includes); let serialize_hpp = serialize_method.to_hpp_tokens(reporter, objects); - let serialize_cpp = - serialize_method.to_cpp_tokens("e!(AsComponents<#quoted_namespace::#type_ident>)); + let serialize_cpp = serialize_method + .to_cpp_tokens("e!(AsComponents<#quoted_namespace::#archetype_type_ident>)); let methods_hpp = methods.iter().map(|m| m.to_hpp_tokens(reporter, objects)); let methods_cpp = methods .iter() - .map(|m| m.to_cpp_tokens("e!(#type_ident))); + .map(|m| m.to_cpp_tokens("e!(#archetype_type_ident))); let indicator_comment = quote_doc_comment("Indicator component, used to identify the archetype when converting to a list of components."); let indicator_component_fqname = @@ -648,9 +724,12 @@ impl QuotedObject { let default_ctor = if obj.is_attr_set(ATTR_CPP_NO_DEFAULT_CTOR) { quote! {} } else { - quote! { #type_ident() = default; } + quote! { #archetype_type_ident() = default; } }; + // Don't add any includes that are already in the hpp anyways. + cpp_includes.remove_includes(&hpp_includes); + // Note that we run into "rule of five": https://en.cppreference.com/w/cpp/language/rule_of_three // * we have to manually opt-in to default ctor because we (most of the time) have a user defined constructor // -> this means that there's no non-move constructors/assignments @@ -664,7 +743,7 @@ impl QuotedObject { namespace rerun::#quoted_namespace { #quoted_docs - struct #deprecation_notice #type_ident { + struct #deprecation_notice #archetype_type_ident { #(#field_declarations;)* public: @@ -685,10 +764,10 @@ impl QuotedObject { public: #default_ctor - #type_ident(#type_ident&& other) = default; - #type_ident(const #type_ident& other) = default; - #type_ident& operator=(const #type_ident& other) = default; - #type_ident& operator=(#type_ident&& other) = default; + #archetype_type_ident(#archetype_type_ident&& other) = default; + #archetype_type_ident(const #archetype_type_ident& other) = default; + #archetype_type_ident& operator=(const #archetype_type_ident& other) = default; + #archetype_type_ident& operator=(#archetype_type_ident&& other) = default; #NEWLINE_TOKEN #NEWLINE_TOKEN @@ -708,7 +787,7 @@ impl QuotedObject { #doc_hide_comment template<> - struct AsComponents<#quoted_namespace::#type_ident> { + struct AsComponents<#quoted_namespace::#archetype_type_ident> { #serialize_hpp }; } diff --git a/docs/snippets/all/archetypes/points3d_send_columns.cpp b/docs/snippets/all/archetypes/points3d_send_columns.cpp index 72b57ac72132f..bf5e73ca5d248 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.cpp +++ b/docs/snippets/all/archetypes/points3d_send_columns.cpp @@ -29,28 +29,11 @@ int main() { auto times = rerun::Collection{10s, 11s, 12s, 13s, 14s}; auto time_column = rerun::TimeColumn::from_times("time", std::move(times)); - // Interpret raw positions and color data as rerun components and partition them. - auto indicator_batch = rerun::ComponentColumn::from_indicators(5); - auto position_batch = rerun::ComponentColumn::from_loggable_with_lengths( - rerun::Collection(std::move(positions)), - {2, 4, 4, 3, 4} - ); - auto color_batch = rerun::ComponentColumn::from_loggable( - rerun::Collection(std::move(colors)) - ); - auto radius_batch = rerun::ComponentColumn::from_loggable( - rerun::Collection(std::move(radii)) - ); - - // TODO(#8754) : use tagged columnar APIs - rec.send_columns( - "points", - time_column, - { - indicator_batch.value_or_throw(), - position_batch.value_or_throw(), - color_batch.value_or_throw(), - radius_batch.value_or_throw(), - } - ); + // Partition our data as expected across the 5 timesteps. + auto position = + rerun::Points3D::update_fields().with_positions(positions).columns({2, 4, 4, 3, 4}); + auto color_and_radius = + rerun::Points3D::update_fields().with_colors(colors).with_radii(radii).columns(); + + rec.send_columns2("points", time_column, position, color_and_radius); } diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 542c7683794a6..e438c4a099dd1 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -102,10 +102,10 @@ "rust", # Missing examples ] "howto/any_batch_value_send_columns" = [ - "cpp", # Not implemented + "cpp", # Not implemented ] "howto/any_values_send_columns" = [ - "cpp", # Not implemented + "cpp", # Not implemented ] "migration/log_line" = [ # Not a complete example -- just a single log line "cpp", @@ -236,9 +236,6 @@ quick_start = [ # These examples don't have exactly the same implementation. "py", "rust", ] -"archetypes/points3d_send_columns" = [ - "cpp", # TODO(#8754): needs tagged columnar APIs -] "archetypes/points3d_random" = [ # TODO(#3206): examples use different RNGs "cpp", "py", diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.cpp b/rerun_cpp/src/rerun/archetypes/annotation_context.cpp index 2eedd044bdcae..1d6ac80242874 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.cpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.cpp @@ -13,6 +13,28 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection AnnotationContext::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (context.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(context.value(), lengths_).value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection AnnotationContext::columns() { + if (context.has_value()) { + return columns(std::vector(context.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp index 4d42cf673a6b7..1575cdb75ec2a 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/annotation_context.hpp" #include "../indicator_component.hpp" #include "../result.hpp" @@ -106,6 +107,22 @@ namespace rerun::archetypes { context = ComponentBatch::from_loggable(_context, Descriptor_context).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.cpp b/rerun_cpp/src/rerun/archetypes/arrows2d.cpp index bc6242122d37d..c38ea2e8f1eca 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.cpp @@ -29,6 +29,83 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Arrows2D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(9); + if (vectors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(vectors.value(), lengths_).value_or_throw() + ); + } + if (origins.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(origins.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Arrows2D::columns() { + if (vectors.has_value()) { + return columns(std::vector(vectors.value().length(), 1)); + } + if (origins.has_value()) { + return columns(std::vector(origins.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp index 1bf583ecdfe06..b4b24f0dac80b 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/draw_order.hpp" @@ -214,6 +215,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.cpp b/rerun_cpp/src/rerun/archetypes/arrows3d.cpp index dbf8999cef1d1..600136ee75dbe 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.cpp @@ -26,6 +26,76 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Arrows3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(8); + if (vectors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(vectors.value(), lengths_).value_or_throw() + ); + } + if (origins.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(origins.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Arrows3D::columns() { + if (vectors.has_value()) { + return columns(std::vector(vectors.value().length(), 1)); + } + if (origins.has_value()) { + return columns(std::vector(origins.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp index 046b078bc5d54..a3d8246bb6dac 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/position3d.hpp" @@ -211,6 +212,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.cpp b/rerun_cpp/src/rerun/archetypes/asset3d.cpp index d5eb049084c15..490da9ffb365d 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.cpp @@ -18,6 +18,44 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Asset3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(4); + if (blob.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(blob.value(), lengths_).value_or_throw() + ); + } + if (media_type.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(media_type.value(), lengths_) + .value_or_throw()); + } + if (albedo_factor.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(albedo_factor.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Asset3D::columns() { + if (blob.has_value()) { + return columns(std::vector(blob.value().length(), 1)); + } + if (media_type.has_value()) { + return columns(std::vector(media_type.value().length(), 1)); + } + if (albedo_factor.has_value()) { + return columns(std::vector(albedo_factor.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.hpp b/rerun_cpp/src/rerun/archetypes/asset3d.hpp index dd56ca28522fb..d8cde2391e27f 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/albedo_factor.hpp" #include "../components/blob.hpp" #include "../components/media_type.hpp" @@ -172,6 +173,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.cpp b/rerun_cpp/src/rerun/archetypes/asset_video.cpp index 41f646a1a4454..8f1f635099e5a 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.cpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.cpp @@ -15,6 +15,35 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection AssetVideo::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (blob.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(blob.value(), lengths_).value_or_throw() + ); + } + if (media_type.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(media_type.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection AssetVideo::columns() { + if (blob.has_value()) { + return columns(std::vector(blob.value().length(), 1)); + } + if (media_type.has_value()) { + return columns(std::vector(media_type.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.hpp b/rerun_cpp/src/rerun/archetypes/asset_video.hpp index d1dbc3725d075..bd62127702d36 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/blob.hpp" #include "../components/media_type.hpp" #include "../indicator_component.hpp" @@ -215,6 +216,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_media_type, Descriptor_media_type).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/bar_chart.cpp b/rerun_cpp/src/rerun/archetypes/bar_chart.cpp index 30de6ff7d6a47..d3a4df04c78e8 100644 --- a/rerun_cpp/src/rerun/archetypes/bar_chart.cpp +++ b/rerun_cpp/src/rerun/archetypes/bar_chart.cpp @@ -14,6 +14,36 @@ namespace rerun::archetypes { ComponentBatch::empty(Descriptor_color).value_or_throw(); return archetype; } + + Collection BarChart::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (values.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(values.value(), lengths_).value_or_throw() + ); + } + if (color.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(color.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection BarChart::columns() { + if (values.has_value()) { + return columns(std::vector(values.value().length(), 1)); + } + if (color.has_value()) { + return columns(std::vector(color.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp index 183769acb8f48..50eb559decc0c 100644 --- a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp +++ b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/color.hpp" #include "../components/tensor_data.hpp" #include "../indicator_component.hpp" @@ -208,6 +209,22 @@ namespace rerun::archetypes { color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.cpp b/rerun_cpp/src/rerun/archetypes/boxes2d.cpp index d5054d3ff2d67..5e1c9789d0753 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.cpp @@ -30,6 +30,82 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Boxes2D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(9); + if (half_sizes.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(half_sizes.value(), lengths_) + .value_or_throw()); + } + if (centers.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(centers.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Boxes2D::columns() { + if (half_sizes.has_value()) { + return columns(std::vector(half_sizes.value().length(), 1)); + } + if (centers.has_value()) { + return columns(std::vector(centers.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp index ced5cd2a00b6d..c2e48b460cfed 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/draw_order.hpp" @@ -238,6 +239,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.cpp b/rerun_cpp/src/rerun/archetypes/boxes3d.cpp index 74de853773a6a..77d527268152f 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.cpp @@ -39,6 +39,100 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Boxes3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(11); + if (half_sizes.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(half_sizes.value(), lengths_) + .value_or_throw()); + } + if (centers.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(centers.value(), lengths_).value_or_throw() + ); + } + if (rotation_axis_angles.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(rotation_axis_angles.value(), lengths_) + .value_or_throw() + ); + } + if (quaternions.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(quaternions.value(), lengths_) + .value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (fill_mode.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fill_mode.value(), lengths_) + .value_or_throw()); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Boxes3D::columns() { + if (half_sizes.has_value()) { + return columns(std::vector(half_sizes.value().length(), 1)); + } + if (centers.has_value()) { + return columns(std::vector(centers.value().length(), 1)); + } + if (rotation_axis_angles.has_value()) { + return columns(std::vector(rotation_axis_angles.value().length(), 1)); + } + if (quaternions.has_value()) { + return columns(std::vector(quaternions.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (fill_mode.has_value()) { + return columns(std::vector(fill_mode.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp index 5b46d4b1ee694..1d9ceca3f7b21 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/fill_mode.hpp" @@ -313,6 +314,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/capsules3d.cpp b/rerun_cpp/src/rerun/archetypes/capsules3d.cpp index 26f2e542fa11d..dfd56f22f0406 100644 --- a/rerun_cpp/src/rerun/archetypes/capsules3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/capsules3d.cpp @@ -35,6 +35,95 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Capsules3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(10); + if (lengths.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(lengths.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (translations.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(translations.value(), lengths_) + .value_or_throw() + ); + } + if (rotation_axis_angles.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(rotation_axis_angles.value(), lengths_) + .value_or_throw() + ); + } + if (quaternions.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(quaternions.value(), lengths_) + .value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Capsules3D::columns() { + if (lengths.has_value()) { + return columns(std::vector(lengths.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (translations.has_value()) { + return columns(std::vector(translations.value().length(), 1)); + } + if (rotation_axis_angles.has_value()) { + return columns(std::vector(rotation_axis_angles.value().length(), 1)); + } + if (quaternions.has_value()) { + return columns(std::vector(quaternions.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/capsules3d.hpp b/rerun_cpp/src/rerun/archetypes/capsules3d.hpp index 70864fd151883..3f9162203542f 100644 --- a/rerun_cpp/src/rerun/archetypes/capsules3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/capsules3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/length.hpp" @@ -285,6 +286,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/clear.cpp b/rerun_cpp/src/rerun/archetypes/clear.cpp index d707b4a62ff74..76748ed833ecb 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.cpp +++ b/rerun_cpp/src/rerun/archetypes/clear.cpp @@ -13,6 +13,29 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Clear::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (is_recursive.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(is_recursive.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Clear::columns() { + if (is_recursive.has_value()) { + return columns(std::vector(is_recursive.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/clear.hpp b/rerun_cpp/src/rerun/archetypes/clear.hpp index c11e5214e46e6..613e3f5f64d3d 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.hpp +++ b/rerun_cpp/src/rerun/archetypes/clear.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/clear_is_recursive.hpp" #include "../indicator_component.hpp" #include "../rerun_sdk_export.hpp" @@ -133,6 +134,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/depth_image.cpp b/rerun_cpp/src/rerun/archetypes/depth_image.cpp index 1335989a0ed2e..1819b3941737c 100644 --- a/rerun_cpp/src/rerun/archetypes/depth_image.cpp +++ b/rerun_cpp/src/rerun/archetypes/depth_image.cpp @@ -27,6 +27,76 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection DepthImage::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(8); + if (buffer.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(buffer.value(), lengths_).value_or_throw() + ); + } + if (format.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(format.value(), lengths_).value_or_throw() + ); + } + if (meter.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(meter.value(), lengths_).value_or_throw() + ); + } + if (colormap.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(colormap.value(), lengths_) + .value_or_throw()); + } + if (depth_range.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(depth_range.value(), lengths_) + .value_or_throw() + ); + } + if (point_fill_ratio.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(point_fill_ratio.value(), lengths_) + .value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection DepthImage::columns() { + if (buffer.has_value()) { + return columns(std::vector(buffer.value().length(), 1)); + } + if (format.has_value()) { + return columns(std::vector(format.value().length(), 1)); + } + if (meter.has_value()) { + return columns(std::vector(meter.value().length(), 1)); + } + if (colormap.has_value()) { + return columns(std::vector(colormap.value().length(), 1)); + } + if (depth_range.has_value()) { + return columns(std::vector(depth_range.value().length(), 1)); + } + if (point_fill_ratio.has_value()) { + return columns(std::vector(point_fill_ratio.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/depth_image.hpp b/rerun_cpp/src/rerun/archetypes/depth_image.hpp index 98d595c56ac09..f1505405d8c46 100644 --- a/rerun_cpp/src/rerun/archetypes/depth_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/depth_image.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/colormap.hpp" #include "../components/depth_meter.hpp" #include "../components/draw_order.hpp" @@ -314,6 +315,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp index 27b9988ba39c5..995881f410976 100644 --- a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp @@ -40,6 +40,99 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Ellipsoids3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(11); + if (half_sizes.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(half_sizes.value(), lengths_) + .value_or_throw()); + } + if (centers.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(centers.value(), lengths_).value_or_throw() + ); + } + if (rotation_axis_angles.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(rotation_axis_angles.value(), lengths_) + .value_or_throw() + ); + } + if (quaternions.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(quaternions.value(), lengths_) + .value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (line_radii.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(line_radii.value(), lengths_) + .value_or_throw()); + } + if (fill_mode.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fill_mode.value(), lengths_) + .value_or_throw()); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Ellipsoids3D::columns() { + if (half_sizes.has_value()) { + return columns(std::vector(half_sizes.value().length(), 1)); + } + if (centers.has_value()) { + return columns(std::vector(centers.value().length(), 1)); + } + if (rotation_axis_angles.has_value()) { + return columns(std::vector(rotation_axis_angles.value().length(), 1)); + } + if (quaternions.has_value()) { + return columns(std::vector(quaternions.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (line_radii.has_value()) { + return columns(std::vector(line_radii.value().length(), 1)); + } + if (fill_mode.has_value()) { + return columns(std::vector(fill_mode.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp index efc9c5f60e337..ba61754a59e57 100644 --- a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/fill_mode.hpp" @@ -324,6 +325,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/encoded_image.cpp b/rerun_cpp/src/rerun/archetypes/encoded_image.cpp index 262846403c87b..ee294035a5c71 100644 --- a/rerun_cpp/src/rerun/archetypes/encoded_image.cpp +++ b/rerun_cpp/src/rerun/archetypes/encoded_image.cpp @@ -20,6 +20,50 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection EncodedImage::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (blob.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(blob.value(), lengths_).value_or_throw() + ); + } + if (media_type.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(media_type.value(), lengths_) + .value_or_throw()); + } + if (opacity.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(opacity.value(), lengths_).value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection EncodedImage::columns() { + if (blob.has_value()) { + return columns(std::vector(blob.value().length(), 1)); + } + if (media_type.has_value()) { + return columns(std::vector(media_type.value().length(), 1)); + } + if (opacity.has_value()) { + return columns(std::vector(opacity.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/encoded_image.hpp b/rerun_cpp/src/rerun/archetypes/encoded_image.hpp index 7364c19679a98..d9a551a2a47d0 100644 --- a/rerun_cpp/src/rerun/archetypes/encoded_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/encoded_image.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/blob.hpp" #include "../components/draw_order.hpp" #include "../components/media_type.hpp" @@ -171,6 +172,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp b/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp index e53680d0176b2..dcb2cfc34a610 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp +++ b/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp @@ -17,6 +17,45 @@ namespace rerun::archetypes { ComponentBatch::empty(Descriptor_colors).value_or_throw(); return archetype; } + + Collection GeoLineStrings::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(4); + if (line_strings.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(line_strings.value(), lengths_) + .value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection GeoLineStrings::columns() { + if (line_strings.has_value()) { + return columns(std::vector(line_strings.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp b/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp index bd71dee6e1ad9..d7b6e1ab97cf6 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp +++ b/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/color.hpp" #include "../components/geo_line_string.hpp" #include "../components/radius.hpp" @@ -129,6 +130,22 @@ namespace rerun::archetypes { colors = ComponentBatch::from_loggable(_colors, Descriptor_colors).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/geo_points.cpp b/rerun_cpp/src/rerun/archetypes/geo_points.cpp index ae291d97758b5..e12e2a6bef587 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_points.cpp +++ b/rerun_cpp/src/rerun/archetypes/geo_points.cpp @@ -19,6 +19,50 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection GeoPoints::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (positions.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(positions.value(), lengths_) + .value_or_throw()); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection GeoPoints::columns() { + if (positions.has_value()) { + return columns(std::vector(positions.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/geo_points.hpp b/rerun_cpp/src/rerun/archetypes/geo_points.hpp index 432ce21c6d20a..4a14a05599bb2 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_points.hpp +++ b/rerun_cpp/src/rerun/archetypes/geo_points.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/lat_lon.hpp" @@ -141,6 +142,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/graph_edges.cpp b/rerun_cpp/src/rerun/archetypes/graph_edges.cpp index b4a17fd8d6645..81085ab365ebf 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_edges.cpp +++ b/rerun_cpp/src/rerun/archetypes/graph_edges.cpp @@ -15,6 +15,35 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection GraphEdges::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (edges.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(edges.value(), lengths_).value_or_throw() + ); + } + if (graph_type.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(graph_type.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection GraphEdges::columns() { + if (edges.has_value()) { + return columns(std::vector(edges.value().length(), 1)); + } + if (graph_type.has_value()) { + return columns(std::vector(graph_type.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp index 4e7c1a0daa704..c0fe9bab70a58 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/graph_edge.hpp" #include "../components/graph_type.hpp" #include "../indicator_component.hpp" @@ -105,6 +106,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_graph_type, Descriptor_graph_type).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp b/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp index 1cf06836371e3..b8da1b853aae4 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp +++ b/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp @@ -25,6 +25,67 @@ namespace rerun::archetypes { ComponentBatch::empty(Descriptor_radii).value_or_throw(); return archetype; } + + Collection GraphNodes::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(7); + if (node_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(node_ids.value(), lengths_) + .value_or_throw()); + } + if (positions.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(positions.value(), lengths_) + .value_or_throw()); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection GraphNodes::columns() { + if (node_ids.has_value()) { + return columns(std::vector(node_ids.value().length(), 1)); + } + if (positions.has_value()) { + return columns(std::vector(positions.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp index f154e8bf73377..0fefb168ca1b1 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/color.hpp" #include "../components/graph_node.hpp" #include "../components/position2d.hpp" @@ -158,6 +159,22 @@ namespace rerun::archetypes { radii = ComponentBatch::from_loggable(_radii, Descriptor_radii).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/image.cpp b/rerun_cpp/src/rerun/archetypes/image.cpp index 2c7e053bcf36f..b4a959e592cd4 100644 --- a/rerun_cpp/src/rerun/archetypes/image.cpp +++ b/rerun_cpp/src/rerun/archetypes/image.cpp @@ -19,6 +19,51 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Image::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (buffer.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(buffer.value(), lengths_).value_or_throw() + ); + } + if (format.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(format.value(), lengths_).value_or_throw() + ); + } + if (opacity.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(opacity.value(), lengths_).value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Image::columns() { + if (buffer.has_value()) { + return columns(std::vector(buffer.value().length(), 1)); + } + if (format.has_value()) { + return columns(std::vector(format.value().length(), 1)); + } + if (opacity.has_value()) { + return columns(std::vector(opacity.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/image.hpp b/rerun_cpp/src/rerun/archetypes/image.hpp index d36818c6f3cbd..3706095bc0b5c 100644 --- a/rerun_cpp/src/rerun/archetypes/image.hpp +++ b/rerun_cpp/src/rerun/archetypes/image.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/draw_order.hpp" #include "../components/image_buffer.hpp" #include "../components/image_format.hpp" @@ -360,6 +361,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp b/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp index 15d2205350ee7..49342877e5c5d 100644 --- a/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp @@ -26,6 +26,63 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection InstancePoses3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(6); + if (translations.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(translations.value(), lengths_) + .value_or_throw() + ); + } + if (rotation_axis_angles.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(rotation_axis_angles.value(), lengths_) + .value_or_throw() + ); + } + if (quaternions.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(quaternions.value(), lengths_) + .value_or_throw() + ); + } + if (scales.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(scales.value(), lengths_).value_or_throw() + ); + } + if (mat3x3.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(mat3x3.value(), lengths_).value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection InstancePoses3D::columns() { + if (translations.has_value()) { + return columns(std::vector(translations.value().length(), 1)); + } + if (rotation_axis_angles.has_value()) { + return columns(std::vector(rotation_axis_angles.value().length(), 1)); + } + if (quaternions.has_value()) { + return columns(std::vector(quaternions.value().length(), 1)); + } + if (scales.has_value()) { + return columns(std::vector(scales.value().length(), 1)); + } + if (mat3x3.has_value()) { + return columns(std::vector(mat3x3.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp b/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp index b7c7f1ef1999a..f0fb5605bfbd4 100644 --- a/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/pose_rotation_axis_angle.hpp" #include "../components/pose_rotation_quat.hpp" #include "../components/pose_scale3d.hpp" @@ -184,6 +185,22 @@ namespace rerun::archetypes { mat3x3 = ComponentBatch::from_loggable(_mat3x3, Descriptor_mat3x3).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp index ed4d0bfece826..28683ce8edbd2 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp @@ -27,6 +27,75 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection LineStrips2D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(8); + if (strips.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(strips.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection LineStrips2D::columns() { + if (strips.has_value()) { + return columns(std::vector(strips.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp index 4b0deedfdf963..4a0a7691dda96 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/draw_order.hpp" @@ -226,6 +227,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp b/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp index 946e2c34c61b8..c029f7b8d83c2 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp @@ -24,6 +24,68 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection LineStrips3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(7); + if (strips.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(strips.value(), lengths_).value_or_throw() + ); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection LineStrips3D::columns() { + if (strips.has_value()) { + return columns(std::vector(strips.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp index 7dfc0eb7b6596..dfd3c9f5f29ce 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/line_strip3d.hpp" @@ -221,6 +222,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/mesh3d.cpp b/rerun_cpp/src/rerun/archetypes/mesh3d.cpp index 9a5ddc3a68908..ef535ed5e41fe 100644 --- a/rerun_cpp/src/rerun/archetypes/mesh3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/mesh3d.cpp @@ -37,6 +37,99 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Mesh3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(10); + if (vertex_positions.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(vertex_positions.value(), lengths_) + .value_or_throw() + ); + } + if (triangle_indices.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(triangle_indices.value(), lengths_) + .value_or_throw() + ); + } + if (vertex_normals.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(vertex_normals.value(), lengths_) + .value_or_throw() + ); + } + if (vertex_colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(vertex_colors.value(), lengths_) + .value_or_throw() + ); + } + if (vertex_texcoords.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(vertex_texcoords.value(), lengths_) + .value_or_throw() + ); + } + if (albedo_factor.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(albedo_factor.value(), lengths_) + .value_or_throw() + ); + } + if (albedo_texture_buffer.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(albedo_texture_buffer.value(), lengths_) + .value_or_throw() + ); + } + if (albedo_texture_format.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(albedo_texture_format.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Mesh3D::columns() { + if (vertex_positions.has_value()) { + return columns(std::vector(vertex_positions.value().length(), 1)); + } + if (triangle_indices.has_value()) { + return columns(std::vector(triangle_indices.value().length(), 1)); + } + if (vertex_normals.has_value()) { + return columns(std::vector(vertex_normals.value().length(), 1)); + } + if (vertex_colors.has_value()) { + return columns(std::vector(vertex_colors.value().length(), 1)); + } + if (vertex_texcoords.has_value()) { + return columns(std::vector(vertex_texcoords.value().length(), 1)); + } + if (albedo_factor.has_value()) { + return columns(std::vector(albedo_factor.value().length(), 1)); + } + if (albedo_texture_buffer.has_value()) { + return columns(std::vector(albedo_texture_buffer.value().length(), 1)); + } + if (albedo_texture_format.has_value()) { + return columns(std::vector(albedo_texture_format.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp index 45f7f9d8a4e2f..5ee8cf58714a2 100644 --- a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/albedo_factor.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" @@ -310,6 +311,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.cpp b/rerun_cpp/src/rerun/archetypes/pinhole.cpp index bf574f9307df1..926abbeb79926 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.cpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.cpp @@ -25,6 +25,52 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Pinhole::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (image_from_camera.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(image_from_camera.value(), lengths_) + .value_or_throw() + ); + } + if (resolution.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(resolution.value(), lengths_) + .value_or_throw()); + } + if (camera_xyz.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(camera_xyz.value(), lengths_) + .value_or_throw()); + } + if (image_plane_distance.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(image_plane_distance.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Pinhole::columns() { + if (image_from_camera.has_value()) { + return columns(std::vector(image_from_camera.value().length(), 1)); + } + if (resolution.has_value()) { + return columns(std::vector(resolution.value().length(), 1)); + } + if (camera_xyz.has_value()) { + return columns(std::vector(camera_xyz.value().length(), 1)); + } + if (image_plane_distance.has_value()) { + return columns(std::vector(image_plane_distance.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.hpp b/rerun_cpp/src/rerun/archetypes/pinhole.hpp index ded7c0367a83b..f7468a6ab4ba0 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.hpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/image_plane_distance.hpp" #include "../components/pinhole_projection.hpp" #include "../components/resolution.hpp" @@ -296,6 +297,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/points2d.cpp b/rerun_cpp/src/rerun/archetypes/points2d.cpp index 23ffb2e60b82c..ba33eb2f6bd98 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.cpp @@ -31,6 +31,83 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Points2D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(9); + if (positions.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(positions.value(), lengths_) + .value_or_throw()); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + if (keypoint_ids.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(keypoint_ids.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Points2D::columns() { + if (positions.has_value()) { + return columns(std::vector(positions.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + if (keypoint_ids.has_value()) { + return columns(std::vector(keypoint_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/points2d.hpp b/rerun_cpp/src/rerun/archetypes/points2d.hpp index f4e327a725096..695c7955c8dec 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/draw_order.hpp" @@ -274,6 +275,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/points3d.cpp b/rerun_cpp/src/rerun/archetypes/points3d.cpp index ff12f08d9ccfa..ee364cc892b05 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.cpp @@ -28,6 +28,76 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Points3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(8); + if (positions.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(positions.value(), lengths_) + .value_or_throw()); + } + if (radii.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(radii.value(), lengths_).value_or_throw() + ); + } + if (colors.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(colors.value(), lengths_).value_or_throw() + ); + } + if (labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(labels.value(), lengths_).value_or_throw() + ); + } + if (show_labels.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(show_labels.value(), lengths_) + .value_or_throw() + ); + } + if (class_ids.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(class_ids.value(), lengths_) + .value_or_throw()); + } + if (keypoint_ids.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(keypoint_ids.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Points3D::columns() { + if (positions.has_value()) { + return columns(std::vector(positions.value().length(), 1)); + } + if (radii.has_value()) { + return columns(std::vector(radii.value().length(), 1)); + } + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (labels.has_value()) { + return columns(std::vector(labels.value().length(), 1)); + } + if (show_labels.has_value()) { + return columns(std::vector(show_labels.value().length(), 1)); + } + if (class_ids.has_value()) { + return columns(std::vector(class_ids.value().length(), 1)); + } + if (keypoint_ids.has_value()) { + return columns(std::vector(keypoint_ids.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/points3d.hpp b/rerun_cpp/src/rerun/archetypes/points3d.hpp index 7e9f409dd4bb7..39e2805a2c6a4 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/class_id.hpp" #include "../components/color.hpp" #include "../components/keypoint_id.hpp" @@ -132,30 +133,13 @@ namespace rerun::archetypes { /// auto times = rerun::Collection{10s, 11s, 12s, 13s, 14s}; /// auto time_column = rerun::TimeColumn::from_times("time", std::move(times)); /// - /// // Interpret raw positions and color data as rerun components and partition them. - /// auto indicator_batch = rerun::ComponentColumn::from_indicators(5); - /// auto position_batch = rerun::ComponentColumn::from_loggable_with_lengths( - /// rerun::Collection(std::move(positions)), - /// {2, 4, 4, 3, 4} - /// ); - /// auto color_batch = rerun::ComponentColumn::from_loggable( - /// rerun::Collection(std::move(colors)) - /// ); - /// auto radius_batch = rerun::ComponentColumn::from_loggable( - /// rerun::Collection(std::move(radii)) - /// ); + /// // Partition our data as expected across the 5 timesteps. + /// auto position = + /// rerun::Points3D::update_fields().with_positions(positions).columns({2, 4, 4, 3, 4}); + /// auto color_and_radius = + /// rerun::Points3D::update_fields().with_colors(colors).with_radii(radii).columns(); /// - /// // TODO(#8754) : use tagged columnar APIs - /// rec.send_columns( - /// "points", - /// time_column, - /// { - /// indicator_batch.value_or_throw(), - /// position_batch.value_or_throw(), - /// color_batch.value_or_throw(), - /// radius_batch.value_or_throw(), - /// } - /// ); + /// rec.send_columns2("points", time_column, position, color_and_radius); /// } /// ``` struct Points3D { @@ -310,6 +294,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/scalar.cpp b/rerun_cpp/src/rerun/archetypes/scalar.cpp index bad8c3634647c..773a19075edce 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.cpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.cpp @@ -12,6 +12,28 @@ namespace rerun::archetypes { ComponentBatch::empty(Descriptor_scalar).value_or_throw(); return archetype; } + + Collection Scalar::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (scalar.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(scalar.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Scalar::columns() { + if (scalar.has_value()) { + return columns(std::vector(scalar.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/scalar.hpp b/rerun_cpp/src/rerun/archetypes/scalar.hpp index 842b48e85f29a..0d042e46ea916 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.hpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/scalar.hpp" #include "../indicator_component.hpp" #include "../result.hpp" @@ -118,6 +119,22 @@ namespace rerun::archetypes { scalar = ComponentBatch::from_loggable(_scalar, Descriptor_scalar).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp index 1aa4aaacfb53a..43d2c9fdf7290 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp @@ -19,6 +19,51 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection SegmentationImage::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (buffer.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(buffer.value(), lengths_).value_or_throw() + ); + } + if (format.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(format.value(), lengths_).value_or_throw() + ); + } + if (opacity.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(opacity.value(), lengths_).value_or_throw() + ); + } + if (draw_order.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(draw_order.value(), lengths_) + .value_or_throw()); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection SegmentationImage::columns() { + if (buffer.has_value()) { + return columns(std::vector(buffer.value().length(), 1)); + } + if (format.has_value()) { + return columns(std::vector(format.value().length(), 1)); + } + if (opacity.has_value()) { + return columns(std::vector(opacity.value().length(), 1)); + } + if (draw_order.has_value()) { + return columns(std::vector(draw_order.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp index 1f7a418c82272..0f7bd33ad6840 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/draw_order.hpp" #include "../components/image_buffer.hpp" #include "../components/image_format.hpp" @@ -224,6 +225,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/series_line.cpp b/rerun_cpp/src/rerun/archetypes/series_line.cpp index bcab60a9ec1d0..c654d2df42a3b 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.cpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.cpp @@ -20,6 +20,53 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection SeriesLine::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (color.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(color.value(), lengths_).value_or_throw() + ); + } + if (width.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(width.value(), lengths_).value_or_throw() + ); + } + if (name.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(name.value(), lengths_).value_or_throw() + ); + } + if (aggregation_policy.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(aggregation_policy.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection SeriesLine::columns() { + if (color.has_value()) { + return columns(std::vector(color.value().length(), 1)); + } + if (width.has_value()) { + return columns(std::vector(width.value().length(), 1)); + } + if (name.has_value()) { + return columns(std::vector(name.value().length(), 1)); + } + if (aggregation_policy.has_value()) { + return columns(std::vector(aggregation_policy.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index a77969cf69e78..1f54fc0929aef 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/aggregation_policy.hpp" #include "../components/color.hpp" #include "../components/name.hpp" @@ -156,6 +157,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/series_point.cpp b/rerun_cpp/src/rerun/archetypes/series_point.cpp index ada0501dfb00d..b9f9283863b83 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.cpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.cpp @@ -19,6 +19,53 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection SeriesPoint::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (color.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(color.value(), lengths_).value_or_throw() + ); + } + if (marker.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(marker.value(), lengths_).value_or_throw() + ); + } + if (name.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(name.value(), lengths_).value_or_throw() + ); + } + if (marker_size.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(marker_size.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection SeriesPoint::columns() { + if (color.has_value()) { + return columns(std::vector(color.value().length(), 1)); + } + if (marker.has_value()) { + return columns(std::vector(marker.value().length(), 1)); + } + if (name.has_value()) { + return columns(std::vector(name.value().length(), 1)); + } + if (marker_size.has_value()) { + return columns(std::vector(marker_size.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index 68d37453cf004..4d7abb13a9647 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/color.hpp" #include "../components/marker_shape.hpp" #include "../components/marker_size.hpp" @@ -153,6 +154,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/tensor.cpp b/rerun_cpp/src/rerun/archetypes/tensor.cpp index 6058bb2704696..205f9a3b5c950 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.cpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.cpp @@ -15,6 +15,37 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Tensor::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (data.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(data.value(), lengths_).value_or_throw() + ); + } + if (value_range.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(value_range.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Tensor::columns() { + if (data.has_value()) { + return columns(std::vector(data.value().length(), 1)); + } + if (value_range.has_value()) { + return columns(std::vector(value_range.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/tensor.hpp b/rerun_cpp/src/rerun/archetypes/tensor.hpp index 0930e51cf0daf..97c1b2f0c4526 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.hpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/tensor_data.hpp" #include "../components/value_range.hpp" #include "../indicator_component.hpp" @@ -158,6 +159,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/text_document.cpp b/rerun_cpp/src/rerun/archetypes/text_document.cpp index 3d81a7a43295f..325eb45a592ab 100644 --- a/rerun_cpp/src/rerun/archetypes/text_document.cpp +++ b/rerun_cpp/src/rerun/archetypes/text_document.cpp @@ -15,6 +15,35 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection TextDocument::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (text.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(text.value(), lengths_).value_or_throw() + ); + } + if (media_type.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(media_type.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection TextDocument::columns() { + if (text.has_value()) { + return columns(std::vector(text.value().length(), 1)); + } + if (media_type.has_value()) { + return columns(std::vector(media_type.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/text_document.hpp b/rerun_cpp/src/rerun/archetypes/text_document.hpp index a3e51cde808e4..4db23a9dd6df3 100644 --- a/rerun_cpp/src/rerun/archetypes/text_document.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_document.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/media_type.hpp" #include "../components/text.hpp" #include "../indicator_component.hpp" @@ -142,6 +143,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_media_type, Descriptor_media_type).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/text_log.cpp b/rerun_cpp/src/rerun/archetypes/text_log.cpp index ef4f52c7fc58c..13e857555c556 100644 --- a/rerun_cpp/src/rerun/archetypes/text_log.cpp +++ b/rerun_cpp/src/rerun/archetypes/text_log.cpp @@ -16,6 +16,44 @@ namespace rerun::archetypes { ComponentBatch::empty(Descriptor_color).value_or_throw(); return archetype; } + + Collection TextLog::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(4); + if (text.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(text.value(), lengths_).value_or_throw() + ); + } + if (level.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(level.value(), lengths_).value_or_throw() + ); + } + if (color.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(color.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection TextLog::columns() { + if (text.has_value()) { + return columns(std::vector(text.value().length(), 1)); + } + if (level.has_value()) { + return columns(std::vector(level.value().length(), 1)); + } + if (color.has_value()) { + return columns(std::vector(color.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/text_log.hpp b/rerun_cpp/src/rerun/archetypes/text_log.hpp index f14cb443e808d..11d432261aeb3 100644 --- a/rerun_cpp/src/rerun/archetypes/text_log.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_log.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/color.hpp" #include "../components/text.hpp" #include "../components/text_log_level.hpp" @@ -149,6 +150,22 @@ namespace rerun::archetypes { color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.cpp b/rerun_cpp/src/rerun/archetypes/transform3d.cpp index 41a3722791213..67341326e4428 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.cpp @@ -31,6 +31,77 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection Transform3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(8); + if (translation.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(translation.value(), lengths_) + .value_or_throw() + ); + } + if (rotation_axis_angle.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(rotation_axis_angle.value(), lengths_) + .value_or_throw() + ); + } + if (quaternion.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(quaternion.value(), lengths_) + .value_or_throw()); + } + if (scale.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(scale.value(), lengths_).value_or_throw() + ); + } + if (mat3x3.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(mat3x3.value(), lengths_).value_or_throw() + ); + } + if (relation.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(relation.value(), lengths_) + .value_or_throw()); + } + if (axis_length.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(axis_length.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Transform3D::columns() { + if (translation.has_value()) { + return columns(std::vector(translation.value().length(), 1)); + } + if (rotation_axis_angle.has_value()) { + return columns(std::vector(rotation_axis_angle.value().length(), 1)); + } + if (quaternion.has_value()) { + return columns(std::vector(quaternion.value().length(), 1)); + } + if (scale.has_value()) { + return columns(std::vector(scale.value().length(), 1)); + } + if (mat3x3.has_value()) { + return columns(std::vector(mat3x3.value().length(), 1)); + } + if (relation.has_value()) { + return columns(std::vector(relation.value().length(), 1)); + } + if (axis_length.has_value()) { + return columns(std::vector(axis_length.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index a84dc338b0bf2..11a35cd92f5b3 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -6,6 +6,7 @@ #include "../collection.hpp" #include "../compiler_utils.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/axis_length.hpp" #include "../components/rotation_axis_angle.hpp" #include "../components/rotation_quat.hpp" @@ -659,6 +660,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp index d9ad6f47d77e3..23d0b90b174a2 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp @@ -16,6 +16,36 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection VideoFrameReference::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (timestamp.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(timestamp.value(), lengths_) + .value_or_throw()); + } + if (video_reference.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(video_reference.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection VideoFrameReference::columns() { + if (timestamp.has_value()) { + return columns(std::vector(timestamp.value().length(), 1)); + } + if (video_reference.has_value()) { + return columns(std::vector(video_reference.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp index 42be5978f8fad..299a9d6b5a658 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/entity_path.hpp" #include "../components/video_timestamp.hpp" #include "../indicator_component.hpp" @@ -202,6 +203,22 @@ namespace rerun::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp index 8a2bf44cce097..2e50be5812a22 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp @@ -12,6 +12,28 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection ViewCoordinates::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (xyz.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(xyz.value(), lengths_).value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection ViewCoordinates::columns() { + if (xyz.has_value()) { + return columns(std::vector(xyz.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index 9039d34d46edf..224f237a989a3 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -5,6 +5,7 @@ #include "../collection.hpp" #include "../component_batch.hpp" +#include "../component_column.hpp" #include "../components/view_coordinates.hpp" #include "../indicator_component.hpp" #include "../rerun_sdk_export.hpp" @@ -343,6 +344,22 @@ namespace rerun::archetypes { xyz = ComponentBatch::from_loggable(_xyz, Descriptor_xyz).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp index 5905601598458..36f96072f8de4 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp @@ -15,6 +15,36 @@ namespace rerun::blueprint::archetypes { ComponentBatch::empty(Descriptor_color).value_or_throw(); return archetype; } + + Collection Background::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (kind.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(kind.value(), lengths_).value_or_throw() + ); + } + if (color.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(color.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Background::columns() { + if (kind.has_value()) { + return columns(std::vector(kind.value().length(), 1)); + } + if (color.has_value()) { + return columns(std::vector(color.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp index 041e794fe38c5..c1714e0bcd0dd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/background_kind.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/color.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -73,6 +74,22 @@ namespace rerun::blueprint::archetypes { color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp index b607521b996cc..9a6e01623e949 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp @@ -38,6 +38,83 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ContainerBlueprint::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(9); + if (container_kind.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(container_kind.value(), lengths_) + .value_or_throw() + ); + } + if (display_name.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(display_name.value(), lengths_) + .value_or_throw() + ); + } + if (contents.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(contents.value(), lengths_) + .value_or_throw()); + } + if (col_shares.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(col_shares.value(), lengths_) + .value_or_throw()); + } + if (row_shares.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(row_shares.value(), lengths_) + .value_or_throw()); + } + if (active_tab.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(active_tab.value(), lengths_) + .value_or_throw()); + } + if (visible.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(visible.value(), lengths_).value_or_throw() + ); + } + if (grid_columns.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(grid_columns.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection ContainerBlueprint::columns() { + if (container_kind.has_value()) { + return columns(std::vector(container_kind.value().length(), 1)); + } + if (display_name.has_value()) { + return columns(std::vector(display_name.value().length(), 1)); + } + if (contents.has_value()) { + return columns(std::vector(contents.value().length(), 1)); + } + if (col_shares.has_value()) { + return columns(std::vector(col_shares.value().length(), 1)); + } + if (row_shares.has_value()) { + return columns(std::vector(row_shares.value().length(), 1)); + } + if (active_tab.has_value()) { + return columns(std::vector(active_tab.value().length(), 1)); + } + if (visible.has_value()) { + return columns(std::vector(visible.value().length(), 1)); + } + if (grid_columns.has_value()) { + return columns(std::vector(grid_columns.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp index 9cd08daedc65a..564eb2aa3db75 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp @@ -12,6 +12,7 @@ #include "../../blueprint/components/visible.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/name.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -219,6 +220,22 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp index a2e97aec62b0f..56239fc2fb1a0 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp @@ -31,6 +31,62 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection DataframeQuery::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(6); + if (timeline.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(timeline.value(), lengths_) + .value_or_throw()); + } + if (filter_by_range.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(filter_by_range.value(), lengths_) + .value_or_throw() + ); + } + if (filter_is_not_null.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(filter_is_not_null.value(), lengths_) + .value_or_throw() + ); + } + if (apply_latest_at.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(apply_latest_at.value(), lengths_) + .value_or_throw() + ); + } + if (select.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(select.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection DataframeQuery::columns() { + if (timeline.has_value()) { + return columns(std::vector(timeline.value().length(), 1)); + } + if (filter_by_range.has_value()) { + return columns(std::vector(filter_by_range.value().length(), 1)); + } + if (filter_is_not_null.has_value()) { + return columns(std::vector(filter_is_not_null.value().length(), 1)); + } + if (apply_latest_at.has_value()) { + return columns(std::vector(apply_latest_at.value().length(), 1)); + } + if (select.has_value()) { + return columns(std::vector(select.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp index 8918e7f6ce6bb..89b522c804b43 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp @@ -10,6 +10,7 @@ #include "../../blueprint/components/timeline_name.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -138,6 +139,22 @@ namespace rerun::blueprint::archetypes { select = ComponentBatch::from_loggable(_select, Descriptor_select).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp index 92f6f668f6714..efaa25a2fe777 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp @@ -16,6 +16,35 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ForceCenter::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (enabled.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(enabled.value(), lengths_).value_or_throw() + ); + } + if (strength.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(strength.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ForceCenter::columns() { + if (enabled.has_value()) { + return columns(std::vector(enabled.value().length(), 1)); + } + if (strength.has_value()) { + return columns(std::vector(strength.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp index 42899c9be4c0d..1887ab29c140f 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp @@ -7,6 +7,7 @@ #include "../../blueprint/components/force_strength.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -75,6 +76,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_strength, Descriptor_strength).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp index 447c1077bb0d4..2c6b8cb5fabd0 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp @@ -20,6 +20,43 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ForceCollisionRadius::columns(const Collection& lengths_ + ) { + std::vector columns; + columns.reserve(4); + if (enabled.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(enabled.value(), lengths_).value_or_throw() + ); + } + if (strength.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(strength.value(), lengths_) + .value_or_throw()); + } + if (iterations.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(iterations.value(), lengths_) + .value_or_throw()); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection ForceCollisionRadius::columns() { + if (enabled.has_value()) { + return columns(std::vector(enabled.value().length(), 1)); + } + if (strength.has_value()) { + return columns(std::vector(strength.value().length(), 1)); + } + if (iterations.has_value()) { + return columns(std::vector(iterations.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp index 9c1c4e20d2ea7..645e78d12983e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp @@ -8,6 +8,7 @@ #include "../../blueprint/components/force_strength.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -101,6 +102,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_iterations, Descriptor_iterations).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp index 59d086a65836c..5c8d9d753da1f 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp @@ -20,6 +20,42 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ForceLink::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(4); + if (enabled.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(enabled.value(), lengths_).value_or_throw() + ); + } + if (distance.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(distance.value(), lengths_) + .value_or_throw()); + } + if (iterations.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(iterations.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ForceLink::columns() { + if (enabled.has_value()) { + return columns(std::vector(enabled.value().length(), 1)); + } + if (distance.has_value()) { + return columns(std::vector(distance.value().length(), 1)); + } + if (iterations.has_value()) { + return columns(std::vector(iterations.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp index 19c4932d265ed..7241e1f588699 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp @@ -8,6 +8,7 @@ #include "../../blueprint/components/force_iterations.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -96,6 +97,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_iterations, Descriptor_iterations).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp index 757618c5c1f8b..40cdbf629973d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp @@ -16,6 +16,35 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ForceManyBody::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (enabled.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(enabled.value(), lengths_).value_or_throw() + ); + } + if (strength.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(strength.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ForceManyBody::columns() { + if (enabled.has_value()) { + return columns(std::vector(enabled.value().length(), 1)); + } + if (strength.has_value()) { + return columns(std::vector(strength.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp index 63701f68bcdc1..4bda598d56a8a 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp @@ -7,6 +7,7 @@ #include "../../blueprint/components/force_strength.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -84,6 +85,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_strength, Descriptor_strength).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp index 45d7a0913db0e..61d23a2af26c6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp @@ -19,6 +19,42 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ForcePosition::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(4); + if (enabled.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(enabled.value(), lengths_).value_or_throw() + ); + } + if (strength.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(strength.value(), lengths_) + .value_or_throw()); + } + if (position.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(position.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ForcePosition::columns() { + if (enabled.has_value()) { + return columns(std::vector(enabled.value().length(), 1)); + } + if (strength.has_value()) { + return columns(std::vector(strength.value().length(), 1)); + } + if (position.has_value()) { + return columns(std::vector(position.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp index 2af3226f584d4..cadcfa0968a6c 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp @@ -7,6 +7,7 @@ #include "../../blueprint/components/force_strength.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/position2d.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -92,6 +93,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_position, Descriptor_position).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp index 118023b1c9768..d63c0ee6f8f8e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp @@ -23,6 +23,61 @@ namespace rerun::blueprint::archetypes { ComponentBatch::empty(Descriptor_color).value_or_throw(); return archetype; } + + Collection LineGrid3D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(6); + if (visible.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(visible.value(), lengths_).value_or_throw() + ); + } + if (spacing.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(spacing.value(), lengths_).value_or_throw() + ); + } + if (plane.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(plane.value(), lengths_).value_or_throw() + ); + } + if (stroke_width.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(stroke_width.value(), lengths_) + .value_or_throw() + ); + } + if (color.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(color.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection LineGrid3D::columns() { + if (visible.has_value()) { + return columns(std::vector(visible.value().length(), 1)); + } + if (spacing.has_value()) { + return columns(std::vector(spacing.value().length(), 1)); + } + if (plane.has_value()) { + return columns(std::vector(plane.value().length(), 1)); + } + if (stroke_width.has_value()) { + return columns(std::vector(stroke_width.value().length(), 1)); + } + if (color.has_value()) { + return columns(std::vector(color.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp index d6f866f4bfaba..99fcfba17cb23 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp @@ -7,6 +7,7 @@ #include "../../blueprint/components/visible.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/color.hpp" #include "../../components/plane3d.hpp" #include "../../components/stroke_width.hpp" @@ -138,6 +139,22 @@ namespace rerun::blueprint::archetypes { color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp index ac30cb43f8325..395631961c44e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp @@ -13,6 +13,27 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection MapBackground::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (provider.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(provider.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection MapBackground::columns() { + if (provider.has_value()) { + return columns(std::vector(provider.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp index 6a1ce93640eb7..3faa72e8e7e56 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/map_provider.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -64,6 +65,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_provider, Descriptor_provider).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp index 66c72513058ee..22c6e86f12890 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp @@ -13,6 +13,28 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection MapZoom::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (zoom.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(zoom.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection MapZoom::columns() { + if (zoom.has_value()) { + return columns(std::vector(zoom.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp index a39c63e78045e..0538840142ddf 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/zoom_level.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -63,6 +64,22 @@ namespace rerun::blueprint::archetypes { zoom = ComponentBatch::from_loggable(_zoom, Descriptor_zoom).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp index 8957d6b381c26..9655cf7e8fa64 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp @@ -15,6 +15,29 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection NearClipPlane::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (near_clip_plane.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(near_clip_plane.value(), lengths_) + .value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection NearClipPlane::columns() { + if (near_clip_plane.has_value()) { + return columns(std::vector(near_clip_plane.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.hpp index 96c494f2463d5..c7d676d9619ed 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/near_clip_plane.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -69,6 +70,22 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp index fb44e43b22b7b..9119e5485a2df 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp @@ -13,6 +13,28 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection PanelBlueprint::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (state.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(state.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection PanelBlueprint::columns() { + if (state.has_value()) { + return columns(std::vector(state.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp index 1b5d644830a46..c40e4c4b174cb 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/panel_state.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -55,6 +56,22 @@ namespace rerun::blueprint::archetypes { state = ComponentBatch::from_loggable(_state, Descriptor_state).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp index 933e6549842fb..e86c994d4a775 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp @@ -16,6 +16,36 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection PlotLegend::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (corner.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(corner.value(), lengths_).value_or_throw() + ); + } + if (visible.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(visible.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection PlotLegend::columns() { + if (corner.has_value()) { + return columns(std::vector(corner.value().length(), 1)); + } + if (visible.has_value()) { + return columns(std::vector(visible.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp index 9fb02a3c4ed4e..dd0ccb3738460 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp @@ -7,6 +7,7 @@ #include "../../blueprint/components/visible.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -78,6 +79,22 @@ namespace rerun::blueprint::archetypes { visible = ComponentBatch::from_loggable(_visible, Descriptor_visible).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp index f7f54d449aa5a..fc089a96d4ff8 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp @@ -17,6 +17,35 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ScalarAxis::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(3); + if (range.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(range.value(), lengths_).value_or_throw() + ); + } + if (zoom_lock.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(zoom_lock.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ScalarAxis::columns() { + if (range.has_value()) { + return columns(std::vector(range.value().length(), 1)); + } + if (zoom_lock.has_value()) { + return columns(std::vector(zoom_lock.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp index 194ed309f5e91..fcd0dd47302fd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/lock_range_during_zoom.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/range1d.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -76,6 +77,22 @@ namespace rerun::blueprint::archetypes { ComponentBatch::from_loggable(_zoom_lock, Descriptor_zoom_lock).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp index 3ee67b908f17d..24d8c553a8658 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp @@ -18,6 +18,42 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection TensorScalarMapping::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(4); + if (mag_filter.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(mag_filter.value(), lengths_) + .value_or_throw()); + } + if (colormap.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(colormap.value(), lengths_) + .value_or_throw()); + } + if (gamma.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(gamma.value(), lengths_).value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection TensorScalarMapping::columns() { + if (mag_filter.has_value()) { + return columns(std::vector(mag_filter.value().length(), 1)); + } + if (colormap.has_value()) { + return columns(std::vector(colormap.value().length(), 1)); + } + if (gamma.has_value()) { + return columns(std::vector(gamma.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.hpp index 4773a49ccde56..d9709a3cc32aa 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.hpp @@ -5,6 +5,7 @@ #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/colormap.hpp" #include "../../components/gamma_correction.hpp" #include "../../components/magnification_filter.hpp" @@ -106,6 +107,22 @@ namespace rerun::blueprint::archetypes { gamma = ComponentBatch::from_loggable(_gamma, Descriptor_gamma).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp index 48bffb17840f3..b89e169e738fd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp @@ -25,6 +25,53 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection TensorSliceSelection::columns(const Collection& lengths_ + ) { + std::vector columns; + columns.reserve(5); + if (width.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(width.value(), lengths_).value_or_throw() + ); + } + if (height.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(height.value(), lengths_).value_or_throw() + ); + } + if (indices.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(indices.value(), lengths_).value_or_throw() + ); + } + if (slider.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(slider.value(), lengths_).value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection TensorSliceSelection::columns() { + if (width.has_value()) { + return columns(std::vector(width.value().length(), 1)); + } + if (height.has_value()) { + return columns(std::vector(height.value().length(), 1)); + } + if (indices.has_value()) { + return columns(std::vector(indices.value().length(), 1)); + } + if (slider.has_value()) { + return columns(std::vector(slider.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.hpp index 49d5678504d6b..4c341c7a5dcd3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/tensor_dimension_index_slider.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/tensor_dimension_index_selection.hpp" #include "../../components/tensor_height_dimension.hpp" #include "../../components/tensor_width_dimension.hpp" @@ -127,6 +128,22 @@ namespace rerun::blueprint::archetypes { slider = ComponentBatch::from_loggable(_slider, Descriptor_slider).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp index d9930607253ea..6669ddd484c67 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp @@ -13,6 +13,28 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection TensorViewFit::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (scaling.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(scaling.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection TensorViewFit::columns() { + if (scaling.has_value()) { + return columns(std::vector(scaling.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.hpp index 73ffcd63f67e5..abdeb5a14a545 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/view_fit.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -55,6 +56,22 @@ namespace rerun::blueprint::archetypes { scaling = ComponentBatch::from_loggable(_scaling, Descriptor_scaling).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp index 69f88044b52bf..2ece106212f1d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp @@ -23,6 +23,55 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ViewBlueprint::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(5); + if (class_identifier.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(class_identifier.value(), lengths_) + .value_or_throw() + ); + } + if (display_name.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(display_name.value(), lengths_) + .value_or_throw() + ); + } + if (space_origin.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(space_origin.value(), lengths_) + .value_or_throw() + ); + } + if (visible.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(visible.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ViewBlueprint::columns() { + if (class_identifier.has_value()) { + return columns(std::vector(class_identifier.value().length(), 1)); + } + if (display_name.has_value()) { + return columns(std::vector(display_name.value().length(), 1)); + } + if (space_origin.has_value()) { + return columns(std::vector(space_origin.value().length(), 1)); + } + if (visible.has_value()) { + return columns(std::vector(visible.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp index 2db0735288d23..721b6fbef1d70 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp @@ -8,6 +8,7 @@ #include "../../blueprint/components/visible.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../components/name.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -130,6 +131,22 @@ namespace rerun::blueprint::archetypes { visible = ComponentBatch::from_loggable(_visible, Descriptor_visible).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp index 1350503bbe04c..2140e17f60c15 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp @@ -13,6 +13,28 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ViewContents::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (query.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(query.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection ViewContents::columns() { + if (query.has_value()) { + return columns(std::vector(query.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp index 73a8e11bf97ac..5272ee6eb632d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/query_expression.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -102,6 +103,22 @@ namespace rerun::blueprint::archetypes { query = ComponentBatch::from_loggable(_query, Descriptor_query).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp index 547d9b7ddf229..adf36c90d1cd2 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp @@ -29,6 +29,62 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection ViewportBlueprint::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(6); + if (root_container.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(root_container.value(), lengths_) + .value_or_throw() + ); + } + if (maximized.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(maximized.value(), lengths_) + .value_or_throw()); + } + if (auto_layout.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(auto_layout.value(), lengths_) + .value_or_throw() + ); + } + if (auto_views.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(auto_views.value(), lengths_) + .value_or_throw()); + } + if (past_viewer_recommendations.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths( + past_viewer_recommendations.value(), + lengths_ + ) + .value_or_throw()); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection ViewportBlueprint::columns() { + if (root_container.has_value()) { + return columns(std::vector(root_container.value().length(), 1)); + } + if (maximized.has_value()) { + return columns(std::vector(maximized.value().length(), 1)); + } + if (auto_layout.has_value()) { + return columns(std::vector(auto_layout.value().length(), 1)); + } + if (auto_views.has_value()) { + return columns(std::vector(auto_views.value().length(), 1)); + } + if (past_viewer_recommendations.has_value()) { + return columns(std::vector(past_viewer_recommendations.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp index 8d5b48462fd75..e2ef5993680a6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp @@ -10,6 +10,7 @@ #include "../../blueprint/components/viewer_recommendation_hash.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -160,6 +161,22 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp index c6013adc6cb30..3e04ff3f10e94 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp @@ -13,6 +13,28 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection VisibleTimeRanges::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (ranges.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(ranges.value(), lengths_).value_or_throw() + ); + } + columns.push_back(ComponentColumn::from_indicators( + static_cast(lengths_.size()) + ) + .value_or_throw()); + return columns; + } + + Collection VisibleTimeRanges::columns() { + if (ranges.has_value()) { + return columns(std::vector(ranges.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.hpp index 4c1bf4cb200c9..593f611bc706b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/visible_time_range.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -76,6 +77,22 @@ namespace rerun::blueprint::archetypes { ranges = ComponentBatch::from_loggable(_ranges, Descriptor_ranges).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp index 5a5e5135abe10..cb45b44159293 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp @@ -13,6 +13,28 @@ namespace rerun::blueprint::archetypes { .value_or_throw(); return archetype; } + + Collection VisualBounds2D::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (range.has_value()) { + columns.push_back( + ComponentColumn::from_batch_with_lengths(range.value(), lengths_).value_or_throw() + ); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection VisualBounds2D::columns() { + if (range.has_value()) { + return columns(std::vector(range.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::blueprint::archetypes namespace rerun { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp index a12ffbe833360..72060e8ee9a3e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp @@ -6,6 +6,7 @@ #include "../../blueprint/components/visual_bounds2d.hpp" #include "../../collection.hpp" #include "../../component_batch.hpp" +#include "../../component_column.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -69,6 +70,22 @@ namespace rerun::blueprint::archetypes { range = ComponentBatch::from_loggable(_range, Descriptor_range).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/component_batch.cpp b/rerun_cpp/src/rerun/component_batch.cpp index ec65e74cdd07b..931946cf039b5 100644 --- a/rerun_cpp/src/rerun/component_batch.cpp +++ b/rerun_cpp/src/rerun/component_batch.cpp @@ -1,5 +1,6 @@ #include "component_batch.hpp" +#include #include #include "c/rerun.h" @@ -13,4 +14,8 @@ namespace rerun { out_component_batch.component_type = component_type; return arrow::ExportArray(*array, &out_component_batch.array, nullptr); } + + size_t ComponentBatch::length() const { + return static_cast(array->length()); + } } // namespace rerun diff --git a/rerun_cpp/src/rerun/component_batch.hpp b/rerun_cpp/src/rerun/component_batch.hpp index 3ada800330cc8..9047a405a18d9 100644 --- a/rerun_cpp/src/rerun/component_batch.hpp +++ b/rerun_cpp/src/rerun/component_batch.hpp @@ -180,6 +180,9 @@ namespace rerun { } } + /// Size in the number of elements the underlying arrow array contains. + size_t length() const; + /// To rerun C API component batch. /// /// The resulting `rr_component_batch` keeps the `arrow::Array` alive until it is released. diff --git a/rerun_cpp/src/rerun/component_column.cpp b/rerun_cpp/src/rerun/component_column.cpp index 9f3bcf7e9523b..d18ea0297542d 100644 --- a/rerun_cpp/src/rerun/component_column.cpp +++ b/rerun_cpp/src/rerun/component_column.cpp @@ -9,15 +9,8 @@ #include namespace rerun { - std::shared_ptr ComponentColumn::list_array_type_for( - std::shared_ptr inner_type - ) { - return arrow::list(inner_type); - } - Result ComponentColumn::from_batch_with_lengths( - ComponentBatch batch, const Collection& lengths, - std::shared_ptr list_array_type + ComponentBatch batch, const Collection& lengths ) { // Convert lengths into offsets. std::vector offsets(lengths.size() + 1); @@ -31,17 +24,16 @@ namespace rerun { offsets[i + 1] = offsets[i] + lengths[i]; } - return ComponentColumn::from_batch_with_offsets(batch, std::move(offsets), list_array_type); + return ComponentColumn::from_batch_with_offsets(batch, std::move(offsets)); } Result ComponentColumn::from_batch_with_offsets( - ComponentBatch batch, Collection offsets, - std::shared_ptr list_array_type + ComponentBatch batch, Collection offsets ) { auto length = offsets.size() - 1; auto offset_buffer = arrow_buffer_from_vector(std::move(offsets).to_vector()); auto list_array = std::make_shared( - list_array_type, + arrow::list(batch.array->type()), length, offset_buffer, std::move(batch.array) diff --git a/rerun_cpp/src/rerun/component_column.hpp b/rerun_cpp/src/rerun/component_column.hpp index 19695475e0aeb..1eea20dbfb708 100644 --- a/rerun_cpp/src/rerun/component_column.hpp +++ b/rerun_cpp/src/rerun/component_column.hpp @@ -33,19 +33,17 @@ namespace rerun { /// \param lengths The number of components in each run. for `rerun::RecordingStream::send_columns`, /// this specifies the number of components at each time point. /// The sum of the lengths must be equal to the number of components in the batch. + /// \param descriptor Descriptor of the component type for this column. template static Result from_loggable_with_lengths( - const Collection& components, const Collection& lengths + const Collection& components, const Collection& lengths, + const ComponentDescriptor& descriptor = Loggable::Descriptor ) { - auto component_batch_result = ComponentBatch::from_loggable(components); + auto component_batch_result = ComponentBatch::from_loggable(components, descriptor); if (component_batch_result.is_err()) { return component_batch_result.error; } - return from_batch_with_lengths( - component_batch_result.value, - lengths, - list_array_type_for() - ); + return from_batch_with_lengths(component_batch_result.value, lengths); } /// Creates a new component column from a collection of component instances where each run has a length of one. @@ -56,19 +54,30 @@ namespace rerun { /// Automatically registers the component type the first time this type is encountered. /// /// \param components Continuous collection of components which is about to be partitioned into runs of length one. + /// \param descriptor Descriptor of the component type for this column. template - static Result from_loggable(const Collection& components) { + static Result from_loggable( + const Collection& components, + const ComponentDescriptor& descriptor = Loggable::Descriptor + ) { return ComponentColumn::from_loggable_with_lengths( components, - Collection::take_ownership(std::vector(components.size(), 1)) + Collection::take_ownership(std::vector(components.size(), 1)), + descriptor ); } /// Creates a new component column with a given number of archetype indicators for a given archetype type. template static Result from_indicators(uint32_t num_indicators) { - return ComponentColumn::from_loggable( - std::vector(num_indicators) + auto component_batch_result = + ComponentBatch::from_loggable(typename Archetype::IndicatorComponent()); + if (component_batch_result.is_err()) { + return component_batch_result.error; + } + return ComponentColumn::from_batch_with_lengths( + component_batch_result.value, + Collection::take_ownership(std::vector(num_indicators, 0)) ); } @@ -78,11 +87,8 @@ namespace rerun { /// \param lengths The number of components in each run. for `rerun::RecordingStream::send_columns`, /// this specifies the number of components at each time point. /// The sum of the lengths must be equal to the number of components in the batch. - /// \param list_array_type The type of the list array to use for the component column. - /// Can be retrieved using `list_array_type_for()`. static Result from_batch_with_lengths( - ComponentBatch batch, const Collection& lengths, - std::shared_ptr list_array_type + ComponentBatch batch, const Collection& lengths ); /// Creates a new component batch partition from a batch and a collection of component offsets. @@ -94,32 +100,8 @@ namespace rerun { /// E.g. a `ParitionedComponentBatch` with a single component would have an offset array of `[0, 1]`. /// A `ComponentColumn` with 5 components divided into runs of length 2 and 3 // would have an offset array of `[0, 2, 5]`. - /// \param list_array_type The type of the list array to use for the component column. - /// Can be retrieved using `list_array_type_for()`. static Result from_batch_with_offsets( - ComponentBatch batch, Collection offsets, - std::shared_ptr list_array_type - ); - - /// Returns the list array type for the given loggable type. - /// - /// Lazily creates the type on first call and then returns a reference to it. - template - static const std::shared_ptr& list_array_type_for() { - static_assert( - rerun::is_loggable, - "The given type does not implement the rerun::Loggable trait." - ); - static std::shared_ptr data_type = - list_array_type_for(Loggable::arrow_datatype()); - return data_type; - } - - /// Creates a new arrow::Datatype for an underlying type. - /// - /// To avoid repeated allocation, use the templated version of this method. - static std::shared_ptr list_array_type_for( - std::shared_ptr inner_type + ComponentBatch batch, Collection offsets ); /// To rerun C API component batch. diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index 88f68415373d1..c073e9b4dbdba 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -717,6 +717,75 @@ namespace rerun { return try_send_columns(entity_path, time_columns, std::move(serialized_columns)); } + /// Directly log a columns of data to Rerun. + /// + /// This variant takes in arbitrary amount of `ComponentColumn`s and `ComponentColumn` collections. + /// + /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data + /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun. + /// The lengths of all of these columns must match, and all + /// data that shares the same index across the different columns will act as a single logical row, + /// equivalent to a single call to `RecordingStream::log`. + /// + /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs. + /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. + /// + /// Any failures that may occur during serialization are handled with `Error::handle`. + /// + /// \param entity_path Path to the entity in the space hierarchy. + /// \param time_columns The time columns to send. + /// \param component_columns The columns of components to send. Both individual `ComponentColumn`s and `Collection`s are accepted. + /// \see `try_send_columns` + template + void send_columns2( + std::string_view entity_path, Collection time_columns, + Ts... component_columns // NOLINT + ) const { + try_send_columns2(entity_path, time_columns, component_columns...).handle(); + } + + /// Directly log a columns of data to Rerun. + /// + /// This variant takes in arbitrary amount of `ComponentColumn`s and `ComponentColumn` collections. + /// + /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data + /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun. + /// The lengths of all of these columns must match, and all + /// data that shares the same index across the different columns will act as a single logical row, + /// equivalent to a single call to `RecordingStream::log`. + /// + /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs. + /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. + /// + /// \param entity_path Path to the entity in the space hierarchy. + /// \param time_columns The time columns to send. + /// \param component_columns The columns of components to send. Both individual `ComponentColumn`s and `Collection`s are accepted. + /// \see `send_columns` + template + Error try_send_columns2( + std::string_view entity_path, Collection time_columns, + Ts... component_columns // NOLINT + ) const { + std::vector flat_column_list; + ( + [&] { + static_assert( + std::is_same_v, ComponentColumn> || + std::is_constructible_v, Ts>, + "Ts must be ComponentColumn or a collection thereof" + ); + + push_back_columns(flat_column_list, std::move(component_columns)); + }(), + ... + ); + return try_send_columns( + entity_path, + std::move(time_columns), + std::move(flat_column_list) + ); + } + /// Directly log a columns of data to Rerun. /// /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data @@ -764,6 +833,21 @@ namespace rerun { /// @} private: + // Utility function to implement `try_send_columns` variadic template. + static void push_back_columns( + std::vector& component_columns, Collection new_columns + ) { + for (const auto& new_column : new_columns) { + component_columns.emplace_back(std::move(new_column)); + } + } + + static void push_back_columns( + std::vector& component_columns, ComponentColumn new_column + ) { + component_columns.emplace_back(std::move(new_column)); + } + RecordingStream(uint32_t id, StoreKind store_kind); uint32_t _id; diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp index a246cd4b21b1b..e25054b48b634 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp @@ -76,6 +76,174 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection AffixFuzzer1::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(23); + if (fuzz1001.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1001.value(), lengths_) + .value_or_throw()); + } + if (fuzz1002.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1002.value(), lengths_) + .value_or_throw()); + } + if (fuzz1003.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1003.value(), lengths_) + .value_or_throw()); + } + if (fuzz1004.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1004.value(), lengths_) + .value_or_throw()); + } + if (fuzz1005.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1005.value(), lengths_) + .value_or_throw()); + } + if (fuzz1006.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1006.value(), lengths_) + .value_or_throw()); + } + if (fuzz1007.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1007.value(), lengths_) + .value_or_throw()); + } + if (fuzz1008.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1008.value(), lengths_) + .value_or_throw()); + } + if (fuzz1009.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1009.value(), lengths_) + .value_or_throw()); + } + if (fuzz1010.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1010.value(), lengths_) + .value_or_throw()); + } + if (fuzz1011.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1011.value(), lengths_) + .value_or_throw()); + } + if (fuzz1012.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1012.value(), lengths_) + .value_or_throw()); + } + if (fuzz1013.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1013.value(), lengths_) + .value_or_throw()); + } + if (fuzz1014.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1014.value(), lengths_) + .value_or_throw()); + } + if (fuzz1015.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1015.value(), lengths_) + .value_or_throw()); + } + if (fuzz1016.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1016.value(), lengths_) + .value_or_throw()); + } + if (fuzz1017.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1017.value(), lengths_) + .value_or_throw()); + } + if (fuzz1018.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1018.value(), lengths_) + .value_or_throw()); + } + if (fuzz1019.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1019.value(), lengths_) + .value_or_throw()); + } + if (fuzz1020.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1020.value(), lengths_) + .value_or_throw()); + } + if (fuzz1021.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1021.value(), lengths_) + .value_or_throw()); + } + if (fuzz1022.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1022.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection AffixFuzzer1::columns() { + if (fuzz1001.has_value()) { + return columns(std::vector(fuzz1001.value().length(), 1)); + } + if (fuzz1002.has_value()) { + return columns(std::vector(fuzz1002.value().length(), 1)); + } + if (fuzz1003.has_value()) { + return columns(std::vector(fuzz1003.value().length(), 1)); + } + if (fuzz1004.has_value()) { + return columns(std::vector(fuzz1004.value().length(), 1)); + } + if (fuzz1005.has_value()) { + return columns(std::vector(fuzz1005.value().length(), 1)); + } + if (fuzz1006.has_value()) { + return columns(std::vector(fuzz1006.value().length(), 1)); + } + if (fuzz1007.has_value()) { + return columns(std::vector(fuzz1007.value().length(), 1)); + } + if (fuzz1008.has_value()) { + return columns(std::vector(fuzz1008.value().length(), 1)); + } + if (fuzz1009.has_value()) { + return columns(std::vector(fuzz1009.value().length(), 1)); + } + if (fuzz1010.has_value()) { + return columns(std::vector(fuzz1010.value().length(), 1)); + } + if (fuzz1011.has_value()) { + return columns(std::vector(fuzz1011.value().length(), 1)); + } + if (fuzz1012.has_value()) { + return columns(std::vector(fuzz1012.value().length(), 1)); + } + if (fuzz1013.has_value()) { + return columns(std::vector(fuzz1013.value().length(), 1)); + } + if (fuzz1014.has_value()) { + return columns(std::vector(fuzz1014.value().length(), 1)); + } + if (fuzz1015.has_value()) { + return columns(std::vector(fuzz1015.value().length(), 1)); + } + if (fuzz1016.has_value()) { + return columns(std::vector(fuzz1016.value().length(), 1)); + } + if (fuzz1017.has_value()) { + return columns(std::vector(fuzz1017.value().length(), 1)); + } + if (fuzz1018.has_value()) { + return columns(std::vector(fuzz1018.value().length(), 1)); + } + if (fuzz1019.has_value()) { + return columns(std::vector(fuzz1019.value().length(), 1)); + } + if (fuzz1020.has_value()) { + return columns(std::vector(fuzz1020.value().length(), 1)); + } + if (fuzz1021.has_value()) { + return columns(std::vector(fuzz1021.value().length(), 1)); + } + if (fuzz1022.has_value()) { + return columns(std::vector(fuzz1022.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp index cb270b82eeb30..350d801f9c0d0 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -405,6 +406,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_fuzz1022, Descriptor_fuzz1022).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp index 5e1e5deb4aaf8..5fd61a0841f06 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp @@ -67,6 +67,153 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection AffixFuzzer2::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(20); + if (fuzz1101.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1101.value(), lengths_) + .value_or_throw()); + } + if (fuzz1102.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1102.value(), lengths_) + .value_or_throw()); + } + if (fuzz1103.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1103.value(), lengths_) + .value_or_throw()); + } + if (fuzz1104.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1104.value(), lengths_) + .value_or_throw()); + } + if (fuzz1105.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1105.value(), lengths_) + .value_or_throw()); + } + if (fuzz1106.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1106.value(), lengths_) + .value_or_throw()); + } + if (fuzz1107.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1107.value(), lengths_) + .value_or_throw()); + } + if (fuzz1108.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1108.value(), lengths_) + .value_or_throw()); + } + if (fuzz1109.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1109.value(), lengths_) + .value_or_throw()); + } + if (fuzz1110.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1110.value(), lengths_) + .value_or_throw()); + } + if (fuzz1111.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1111.value(), lengths_) + .value_or_throw()); + } + if (fuzz1112.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1112.value(), lengths_) + .value_or_throw()); + } + if (fuzz1113.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1113.value(), lengths_) + .value_or_throw()); + } + if (fuzz1114.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1114.value(), lengths_) + .value_or_throw()); + } + if (fuzz1115.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1115.value(), lengths_) + .value_or_throw()); + } + if (fuzz1116.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1116.value(), lengths_) + .value_or_throw()); + } + if (fuzz1117.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1117.value(), lengths_) + .value_or_throw()); + } + if (fuzz1118.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1118.value(), lengths_) + .value_or_throw()); + } + if (fuzz1122.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz1122.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection AffixFuzzer2::columns() { + if (fuzz1101.has_value()) { + return columns(std::vector(fuzz1101.value().length(), 1)); + } + if (fuzz1102.has_value()) { + return columns(std::vector(fuzz1102.value().length(), 1)); + } + if (fuzz1103.has_value()) { + return columns(std::vector(fuzz1103.value().length(), 1)); + } + if (fuzz1104.has_value()) { + return columns(std::vector(fuzz1104.value().length(), 1)); + } + if (fuzz1105.has_value()) { + return columns(std::vector(fuzz1105.value().length(), 1)); + } + if (fuzz1106.has_value()) { + return columns(std::vector(fuzz1106.value().length(), 1)); + } + if (fuzz1107.has_value()) { + return columns(std::vector(fuzz1107.value().length(), 1)); + } + if (fuzz1108.has_value()) { + return columns(std::vector(fuzz1108.value().length(), 1)); + } + if (fuzz1109.has_value()) { + return columns(std::vector(fuzz1109.value().length(), 1)); + } + if (fuzz1110.has_value()) { + return columns(std::vector(fuzz1110.value().length(), 1)); + } + if (fuzz1111.has_value()) { + return columns(std::vector(fuzz1111.value().length(), 1)); + } + if (fuzz1112.has_value()) { + return columns(std::vector(fuzz1112.value().length(), 1)); + } + if (fuzz1113.has_value()) { + return columns(std::vector(fuzz1113.value().length(), 1)); + } + if (fuzz1114.has_value()) { + return columns(std::vector(fuzz1114.value().length(), 1)); + } + if (fuzz1115.has_value()) { + return columns(std::vector(fuzz1115.value().length(), 1)); + } + if (fuzz1116.has_value()) { + return columns(std::vector(fuzz1116.value().length(), 1)); + } + if (fuzz1117.has_value()) { + return columns(std::vector(fuzz1117.value().length(), 1)); + } + if (fuzz1118.has_value()) { + return columns(std::vector(fuzz1118.value().length(), 1)); + } + if (fuzz1122.has_value()) { + return columns(std::vector(fuzz1122.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp index 7683b5f5b5a82..a0e6231d27bf8 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -384,6 +385,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_fuzz1122, Descriptor_fuzz1122).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp index ef8a91d022de0..cf1efc4462659 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp @@ -64,6 +64,146 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection AffixFuzzer3::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(19); + if (fuzz2001.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2001.value(), lengths_) + .value_or_throw()); + } + if (fuzz2002.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2002.value(), lengths_) + .value_or_throw()); + } + if (fuzz2003.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2003.value(), lengths_) + .value_or_throw()); + } + if (fuzz2004.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2004.value(), lengths_) + .value_or_throw()); + } + if (fuzz2005.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2005.value(), lengths_) + .value_or_throw()); + } + if (fuzz2006.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2006.value(), lengths_) + .value_or_throw()); + } + if (fuzz2007.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2007.value(), lengths_) + .value_or_throw()); + } + if (fuzz2008.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2008.value(), lengths_) + .value_or_throw()); + } + if (fuzz2009.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2009.value(), lengths_) + .value_or_throw()); + } + if (fuzz2010.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2010.value(), lengths_) + .value_or_throw()); + } + if (fuzz2011.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2011.value(), lengths_) + .value_or_throw()); + } + if (fuzz2012.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2012.value(), lengths_) + .value_or_throw()); + } + if (fuzz2013.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2013.value(), lengths_) + .value_or_throw()); + } + if (fuzz2014.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2014.value(), lengths_) + .value_or_throw()); + } + if (fuzz2015.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2015.value(), lengths_) + .value_or_throw()); + } + if (fuzz2016.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2016.value(), lengths_) + .value_or_throw()); + } + if (fuzz2017.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2017.value(), lengths_) + .value_or_throw()); + } + if (fuzz2018.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2018.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection AffixFuzzer3::columns() { + if (fuzz2001.has_value()) { + return columns(std::vector(fuzz2001.value().length(), 1)); + } + if (fuzz2002.has_value()) { + return columns(std::vector(fuzz2002.value().length(), 1)); + } + if (fuzz2003.has_value()) { + return columns(std::vector(fuzz2003.value().length(), 1)); + } + if (fuzz2004.has_value()) { + return columns(std::vector(fuzz2004.value().length(), 1)); + } + if (fuzz2005.has_value()) { + return columns(std::vector(fuzz2005.value().length(), 1)); + } + if (fuzz2006.has_value()) { + return columns(std::vector(fuzz2006.value().length(), 1)); + } + if (fuzz2007.has_value()) { + return columns(std::vector(fuzz2007.value().length(), 1)); + } + if (fuzz2008.has_value()) { + return columns(std::vector(fuzz2008.value().length(), 1)); + } + if (fuzz2009.has_value()) { + return columns(std::vector(fuzz2009.value().length(), 1)); + } + if (fuzz2010.has_value()) { + return columns(std::vector(fuzz2010.value().length(), 1)); + } + if (fuzz2011.has_value()) { + return columns(std::vector(fuzz2011.value().length(), 1)); + } + if (fuzz2012.has_value()) { + return columns(std::vector(fuzz2012.value().length(), 1)); + } + if (fuzz2013.has_value()) { + return columns(std::vector(fuzz2013.value().length(), 1)); + } + if (fuzz2014.has_value()) { + return columns(std::vector(fuzz2014.value().length(), 1)); + } + if (fuzz2015.has_value()) { + return columns(std::vector(fuzz2015.value().length(), 1)); + } + if (fuzz2016.has_value()) { + return columns(std::vector(fuzz2016.value().length(), 1)); + } + if (fuzz2017.has_value()) { + return columns(std::vector(fuzz2017.value().length(), 1)); + } + if (fuzz2018.has_value()) { + return columns(std::vector(fuzz2018.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp index eda8dad541001..6e757f282f4cc 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -291,6 +292,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_fuzz2018, Descriptor_fuzz2018).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp index b2b02daaae39e..16093b3189cb5 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp @@ -64,6 +64,146 @@ namespace rerun::archetypes { .value_or_throw(); return archetype; } + + Collection AffixFuzzer4::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(19); + if (fuzz2101.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2101.value(), lengths_) + .value_or_throw()); + } + if (fuzz2102.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2102.value(), lengths_) + .value_or_throw()); + } + if (fuzz2103.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2103.value(), lengths_) + .value_or_throw()); + } + if (fuzz2104.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2104.value(), lengths_) + .value_or_throw()); + } + if (fuzz2105.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2105.value(), lengths_) + .value_or_throw()); + } + if (fuzz2106.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2106.value(), lengths_) + .value_or_throw()); + } + if (fuzz2107.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2107.value(), lengths_) + .value_or_throw()); + } + if (fuzz2108.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2108.value(), lengths_) + .value_or_throw()); + } + if (fuzz2109.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2109.value(), lengths_) + .value_or_throw()); + } + if (fuzz2110.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2110.value(), lengths_) + .value_or_throw()); + } + if (fuzz2111.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2111.value(), lengths_) + .value_or_throw()); + } + if (fuzz2112.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2112.value(), lengths_) + .value_or_throw()); + } + if (fuzz2113.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2113.value(), lengths_) + .value_or_throw()); + } + if (fuzz2114.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2114.value(), lengths_) + .value_or_throw()); + } + if (fuzz2115.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2115.value(), lengths_) + .value_or_throw()); + } + if (fuzz2116.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2116.value(), lengths_) + .value_or_throw()); + } + if (fuzz2117.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2117.value(), lengths_) + .value_or_throw()); + } + if (fuzz2118.has_value()) { + columns.push_back(ComponentColumn::from_batch_with_lengths(fuzz2118.value(), lengths_) + .value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection AffixFuzzer4::columns() { + if (fuzz2101.has_value()) { + return columns(std::vector(fuzz2101.value().length(), 1)); + } + if (fuzz2102.has_value()) { + return columns(std::vector(fuzz2102.value().length(), 1)); + } + if (fuzz2103.has_value()) { + return columns(std::vector(fuzz2103.value().length(), 1)); + } + if (fuzz2104.has_value()) { + return columns(std::vector(fuzz2104.value().length(), 1)); + } + if (fuzz2105.has_value()) { + return columns(std::vector(fuzz2105.value().length(), 1)); + } + if (fuzz2106.has_value()) { + return columns(std::vector(fuzz2106.value().length(), 1)); + } + if (fuzz2107.has_value()) { + return columns(std::vector(fuzz2107.value().length(), 1)); + } + if (fuzz2108.has_value()) { + return columns(std::vector(fuzz2108.value().length(), 1)); + } + if (fuzz2109.has_value()) { + return columns(std::vector(fuzz2109.value().length(), 1)); + } + if (fuzz2110.has_value()) { + return columns(std::vector(fuzz2110.value().length(), 1)); + } + if (fuzz2111.has_value()) { + return columns(std::vector(fuzz2111.value().length(), 1)); + } + if (fuzz2112.has_value()) { + return columns(std::vector(fuzz2112.value().length(), 1)); + } + if (fuzz2113.has_value()) { + return columns(std::vector(fuzz2113.value().length(), 1)); + } + if (fuzz2114.has_value()) { + return columns(std::vector(fuzz2114.value().length(), 1)); + } + if (fuzz2115.has_value()) { + return columns(std::vector(fuzz2115.value().length(), 1)); + } + if (fuzz2116.has_value()) { + return columns(std::vector(fuzz2116.value().length(), 1)); + } + if (fuzz2117.has_value()) { + return columns(std::vector(fuzz2117.value().length(), 1)); + } + if (fuzz2118.has_value()) { + return columns(std::vector(fuzz2118.value().length(), 1)); + } + return Collection(); + } } // namespace rerun::archetypes namespace rerun { diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp index 3da99e00180f7..7dc1aab65a286 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -309,6 +310,22 @@ namespace rerun::archetypes { ComponentBatch::from_loggable(_fuzz2118, Descriptor_fuzz2118).value_or_throw(); return std::move(*this); } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentColumn::from_batch_with_lengths`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); }; } // namespace rerun::archetypes From 6ab4951ae603cb856b191ff830fc273ec634400c Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 28 Jan 2025 09:56:52 +0100 Subject: [PATCH 13/43] Always split indicators into their own dedicated chunks (#8833) --- .../src/codegen/python/mod.rs | 18 ++--- .../re_types_builder/src/codegen/rust/api.rs | 13 +--- crates/store/re_chunk/src/batcher.rs | 24 +++++-- crates/store/re_chunk/src/merge.rs | 41 ++++++++++++ .../store/re_types/src/archetypes/scalar.rs | 5 +- .../descriptors/descr_builtin_archetype.rs | 67 ++++++++++++------- rerun_py/rerun_sdk/rerun/archetypes/scalar.py | 5 +- 7 files changed, 116 insertions(+), 57 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/python/mod.rs b/crates/build/re_types_builder/src/codegen/python/mod.rs index c1b855ab6b411..7fcbd82ec0ccb 100644 --- a/crates/build/re_types_builder/src/codegen/python/mod.rs +++ b/crates/build/re_types_builder/src/codegen/python/mod.rs @@ -2643,19 +2643,6 @@ fn quote_columnar_methods(reporter: &Reporter, obj: &Object, objects: &Objects) }; let doc_block = indent::indent_by(12, quote_doc_lines(doc_string_lines)); - // NOTE(#8768): Scalar indicators are extremely wasteful, and not actually used for anything. - let has_indicator = obj.fqname.as_str() != "rerun.archetypes.Scalar"; - let pack_and_return = if has_indicator { - indent::indent_by(12, unindent("\ - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) - - return ComponentColumnList([indicator_column] + columns) - ")) - } else { - "return ComponentColumnList(columns)".to_owned() - }; - // NOTE: Calling `update_fields` is not an option: we need to be able to pass // plural data, even to singular fields (mono-components). unindent(&format!( @@ -2680,7 +2667,10 @@ fn quote_columnar_methods(reporter: &Reporter, obj: &Object, objects: &Objects) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - {pack_and_return} + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) "# )) } diff --git a/crates/build/re_types_builder/src/codegen/rust/api.rs b/crates/build/re_types_builder/src/codegen/rust/api.rs index cf70b4b1a8a18..cb244bd6e1a9f 100644 --- a/crates/build/re_types_builder/src/codegen/rust/api.rs +++ b/crates/build/re_types_builder/src/codegen/rust/api.rs @@ -1638,13 +1638,9 @@ fn quote_builder_from_obj(reporter: &Reporter, objects: &Objects, obj: &Object) "); let columns_unary_doc = quote_doc_lines(&columns_unary_doc.lines().map(|l| l.to_owned()).collect_vec()); - let has_indicator = obj.fqname.as_str() != "rerun.archetypes.Scalar"; - let num_fields = required.iter().chain(optional.iter()).count(); - let fields = required.iter().chain(optional.iter()).map(|field| { let field_name = format_ident!("{}", field.name); - let clone = if num_fields == 1 && !has_indicator { quote!(.into_iter()) } else { quote!(.clone()) }; - quote!(self.#field_name.map(|#field_name| #field_name.partitioned(_lengths #clone)).transpose()?) + quote!(self.#field_name.map(|#field_name| #field_name.partitioned(_lengths.clone())).transpose()?) }); let field_lengths = required.iter().chain(optional.iter()).map(|field| { @@ -1656,12 +1652,7 @@ fn quote_builder_from_obj(reporter: &Reporter, objects: &Objects, obj: &Object) quote!(let #len_field_name = self.#field_name.as_ref().map(|b| b.array.len())) }); - let indicator_column = if !has_indicator { - // NOTE(#8768): Scalar indicators are extremely wasteful, and not actually used for anything. - quote!(None) - } else { - quote!(::re_types_core::indicator_column::(_lengths.into_iter().count())?) - }; + let indicator_column = quote!(::re_types_core::indicator_column::(_lengths.into_iter().count())?); quote! { #columns_doc diff --git a/crates/store/re_chunk/src/batcher.rs b/crates/store/re_chunk/src/batcher.rs index 92ca60804de4f..662ccdbecb6a3 100644 --- a/crates/store/re_chunk/src/batcher.rs +++ b/crates/store/re_chunk/src/batcher.rs @@ -561,7 +561,7 @@ fn batching_thread(config: ChunkBatcherConfig, rx_cmd: Receiver, tx_chu let chunks = PendingRow::many_into_chunks(acc.entity_path.clone(), chunk_max_rows_if_unsorted, rows); for chunk in chunks { - let chunk = match chunk { + let mut chunk = match chunk { Ok(chunk) => chunk, Err(err) => { re_log::error!(%err, "corrupt chunk detected, dropping"); @@ -571,7 +571,15 @@ fn batching_thread(config: ChunkBatcherConfig, rx_cmd: Receiver, tx_chu // NOTE: This can only fail if all receivers have been dropped, which simply cannot happen // as long the batching thread is alive… which is where we currently are. - tx_chunk.send(chunk).ok(); + + let split_indicators = chunk.split_indicators(); + if !chunk.components.is_empty() { + // make sure the chunk didn't contain *only* indicators! + tx_chunk.send(chunk).ok(); + } + if let Some(split_indicators) = split_indicators { + tx_chunk.send(split_indicators).ok(); + } } acc.reset(); @@ -600,10 +608,18 @@ fn batching_thread(config: ChunkBatcherConfig, rx_cmd: Receiver, tx_chu match cmd { - Command::AppendChunk(chunk) => { + Command::AppendChunk(mut chunk) => { // NOTE: This can only fail if all receivers have been dropped, which simply cannot happen // as long the batching thread is alive… which is where we currently are. - tx_chunk.send(chunk).ok(); + + let split_indicators = chunk.split_indicators(); + if !chunk.components.is_empty() { + // make sure the chunk didn't contain *only* indicators! + tx_chunk.send(chunk).ok(); + } + if let Some(split_indicators) = split_indicators { + tx_chunk.send(split_indicators).ok(); + } }, Command::AppendRow(entity_path, row) => { let acc = accs.entry(entity_path.clone()) diff --git a/crates/store/re_chunk/src/merge.rs b/crates/store/re_chunk/src/merge.rs index a7141243a187a..fe3001e892d68 100644 --- a/crates/store/re_chunk/src/merge.rs +++ b/crates/store/re_chunk/src/merge.rs @@ -292,6 +292,47 @@ impl Chunk { && self.same_datatypes(rhs) && self.same_descriptors(rhs) } + + /// Moves all indicator components from `self` into a new, dedicated chunk. + /// + /// The new chunk contains only the first index from each index column, and all the indicators, + /// packed in a single row. + /// Beware: `self` might be left with no component columns at all after this operation. + /// + /// This greatly reduces the overhead of indicators, both in the row-oriented and + /// column-oriented APIs. + /// See for further rationale. + pub fn split_indicators(&mut self) -> Option { + let indicators: ChunkComponents = self + .components + .iter_flattened() + .filter(|&(descr, _list_array)| descr.component_name.is_indicator_component()) + .filter(|&(_descr, list_array)| (!list_array.is_empty())) + .map(|(descr, list_array)| (descr.clone(), list_array.slice(0, 1))) + .collect(); + if indicators.is_empty() { + return None; + } + + let timelines = self + .timelines + .iter() + .map(|(timeline, time_column)| (*timeline, time_column.row_sliced(0, 1))) + .collect(); + + if let Ok(chunk) = Self::from_auto_row_ids( + ChunkId::new(), + self.entity_path.clone(), + timelines, + indicators, + ) { + self.components + .retain(|component_name, _per_desc| !component_name.is_indicator_component()); + return Some(chunk); + } + + None + } } impl TimeColumn { diff --git a/crates/store/re_types/src/archetypes/scalar.rs b/crates/store/re_types/src/archetypes/scalar.rs index cbcb1ad1f00d5..9812ab5f8c6a9 100644 --- a/crates/store/re_types/src/archetypes/scalar.rs +++ b/crates/store/re_types/src/archetypes/scalar.rs @@ -247,9 +247,10 @@ impl Scalar { { let columns = [self .scalar - .map(|scalar| scalar.partitioned(_lengths.into_iter())) + .map(|scalar| scalar.partitioned(_lengths.clone())) .transpose()?]; - let indicator_column = None; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; Ok(columns.into_iter().chain([indicator_column]).flatten()) } diff --git a/docs/snippets/all/descriptors/descr_builtin_archetype.rs b/docs/snippets/all/descriptors/descr_builtin_archetype.rs index 48ddffd25d5ad..f6e939e667508 100644 --- a/docs/snippets/all/descriptors/descr_builtin_archetype.rs +++ b/docs/snippets/all/descriptors/descr_builtin_archetype.rs @@ -44,36 +44,53 @@ fn check_tags(rec: &rerun::RecordingStream) { let store = stores.into_values().next().unwrap(); let chunks = store.iter_chunks().collect::>(); - assert_eq!(1, chunks.len()); + assert_eq!(2, chunks.len()); - let chunk = chunks.into_iter().next().unwrap(); + { + let chunk = &chunks[0]; - let mut descriptors = chunk - .components() - .values() - .flat_map(|per_desc| per_desc.keys()) - .cloned() - .collect::>(); - descriptors.sort(); + let mut descriptors = chunk + .components() + .values() + .flat_map(|per_desc| per_desc.keys()) + .cloned() + .collect::>(); + descriptors.sort(); - let expected = vec![ - ComponentDescriptor { + let expected = vec![ + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.Points3D".into()), + archetype_field_name: Some("positions".into()), + component_name: "rerun.components.Position3D".into(), + }, + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.Points3D".into()), + archetype_field_name: Some("radii".into()), + component_name: "rerun.components.Radius".into(), + }, + ]; + + similar_asserts::assert_eq!(expected, descriptors); + } + + { + let chunk = &chunks[1]; + + let mut descriptors = chunk + .components() + .values() + .flat_map(|per_desc| per_desc.keys()) + .cloned() + .collect::>(); + descriptors.sort(); + + let expected = vec![ComponentDescriptor { archetype_name: None, archetype_field_name: None, component_name: "rerun.components.Points3DIndicator".into(), - }, - ComponentDescriptor { - archetype_name: Some("rerun.archetypes.Points3D".into()), - archetype_field_name: Some("positions".into()), - component_name: "rerun.components.Position3D".into(), - }, - ComponentDescriptor { - archetype_name: Some("rerun.archetypes.Points3D".into()), - archetype_field_name: Some("radii".into()), - component_name: "rerun.components.Radius".into(), - }, - ]; - - similar_asserts::assert_eq!(expected, descriptors); + }]; + + similar_asserts::assert_eq!(expected, descriptors); + } } } diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index 0f680395b34b6..ba0cba02fbfbf 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -196,7 +196,10 @@ def columns( lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - return ComponentColumnList(columns) + indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) + indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + + return ComponentColumnList([indicator_column] + columns) scalar: components.ScalarBatch | None = field( metadata={"component": True}, From bf4c684207bbf42d5db41f21dc2087e5f4febbe4 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:21:43 +0100 Subject: [PATCH 14/43] Filter entities in the UI (part 6): Refactor `re_blueprint_tree` and add more tests (#8795) Co-authored-by: Emil Ernerfeldt --- Cargo.lock | 57 ++ crates/viewer/re_blueprint_tree/Cargo.toml | 12 +- .../re_blueprint_tree/src/blueprint_tree.rs | 695 ++++++------------ crates/viewer/re_blueprint_tree/src/data.rs | 509 +++++++++++++ crates/viewer/re_blueprint_tree/src/lib.rs | 6 + .../tests/blueprint_tree_tests.rs | 16 +- ...print_panel_filter_active_above_origin.png | 4 +- .../view_structure_test/no-query/empty.png | 3 + .../no-query/multiple_proj.png | 3 + .../no-query/non_root_origin.png | 3 + .../no-query/proj_with_placeholder.png | 3 + .../no-query/root_origin.png | 3 + .../no-query/single_proj.png | 3 + .../no-query/unknown_origin.png | 3 + .../view_structure_test/query-path/empty.png | 3 + .../query-path/multiple_proj.png | 3 + .../query-path/non_root_origin.png | 3 + .../query-path/proj_with_placeholder.png | 3 + .../query-path/root_origin.png | 3 + .../query-path/single_proj.png | 3 + .../query-path/unknown_origin.png | 3 + .../view_structure_test/query-t/empty.png | 3 + .../query-t/multiple_proj.png | 3 + .../query-t/non_root_origin.png | 3 + .../query-t/proj_with_placeholder.png | 3 + .../query-t/root_origin.png | 3 + .../query-t/single_proj.png | 3 + .../query-t/unknown_origin.png | 3 + .../view_structure_test/query-void/empty.png | 3 + .../query-void/multiple_proj.png | 3 + .../query-void/non_root_origin.png | 3 + .../query-void/proj_with_placeholder.png | 3 + .../query-void/root_origin.png | 3 + .../query-void/single_proj.png | 3 + .../query-void/unknown_origin.png | 3 + .../view_structure_test__no-query-empty.snap | 32 + ...tructure_test__no-query-multiple_proj.snap | 71 ++ ...ucture_test__no-query-non_root_origin.snap | 83 +++ ..._test__no-query-proj_with_placeholder.snap | 134 ++++ ..._structure_test__no-query-root_origin.snap | 123 ++++ ..._structure_test__no-query-single_proj.snap | 94 +++ ...ructure_test__no-query-unknown_origin.snap | 34 + ...view_structure_test__query-path-empty.snap | 5 + ...ucture_test__query-path-multiple_proj.snap | 5 + ...ture_test__query-path-non_root_origin.snap | 5 + ...est__query-path-proj_with_placeholder.snap | 55 ++ ...tructure_test__query-path-root_origin.snap | 104 +++ ...tructure_test__query-path-single_proj.snap | 5 + ...cture_test__query-path-unknown_origin.snap | 36 + .../view_structure_test__query-t-empty.snap | 5 + ...structure_test__query-t-multiple_proj.snap | 64 ++ ...ructure_test__query-t-non_root_origin.snap | 91 +++ ...e_test__query-t-proj_with_placeholder.snap | 148 ++++ ...w_structure_test__query-t-root_origin.snap | 135 ++++ ...w_structure_test__query-t-single_proj.snap | 91 +++ ...tructure_test__query-t-unknown_origin.snap | 36 + ...view_structure_test__query-void-empty.snap | 5 + ...ucture_test__query-void-multiple_proj.snap | 50 ++ ...ture_test__query-void-non_root_origin.snap | 61 ++ ...est__query-void-proj_with_placeholder.snap | 61 ++ ...tructure_test__query-void-root_origin.snap | 80 ++ ...tructure_test__query-void-single_proj.snap | 61 ++ ...cture_test__query-void-unknown_origin.snap | 5 + .../tests/view_structure_test.rs | 249 +++++++ crates/viewer/re_ui/src/filter_widget.rs | 18 +- .../viewer/re_viewer_context/src/contents.rs | 1 + .../re_viewer_context/src/test_context.rs | 42 +- .../viewer/re_viewport_blueprint/src/view.rs | 17 +- 68 files changed, 2884 insertions(+), 505 deletions(-) create mode 100644 crates/viewer/re_blueprint_tree/src/data.rs create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/view_structure_test.rs diff --git a/Cargo.lock b/Cargo.lock index 1dad0b098aa93..e42a06badff99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3635,6 +3635,9 @@ dependencies = [ "console", "lazy_static", "linked-hash-map", + "pest", + "pest_derive", + "serde", "similar", ] @@ -4940,6 +4943,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +dependencies = [ + "memchr", + "thiserror 2.0.7", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "pest_meta" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "petgraph" version = "0.6.5" @@ -5638,6 +5686,8 @@ version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_kittest", + "egui_tiles", + "insta", "itertools 0.13.0", "re_chunk_store", "re_context_menu", @@ -5651,6 +5701,7 @@ dependencies = [ "re_view_spatial", "re_viewer_context", "re_viewport_blueprint", + "serde", "smallvec", ] @@ -9224,6 +9275,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "uds_windows" version = "1.1.0" diff --git a/crates/viewer/re_blueprint_tree/Cargo.toml b/crates/viewer/re_blueprint_tree/Cargo.toml index a6489b8d63263..daba6ada7340b 100644 --- a/crates/viewer/re_blueprint_tree/Cargo.toml +++ b/crates/viewer/re_blueprint_tree/Cargo.toml @@ -18,6 +18,11 @@ workspace = true [package.metadata.docs.rs] all-features = true +[features] +default = [] +testing = ["dep:serde"] + + [dependencies] re_context_menu.workspace = true re_data_ui.workspace = true @@ -31,14 +36,17 @@ re_viewer_context.workspace = true re_viewport_blueprint.workspace = true egui.workspace = true +egui_tiles.workspace = true itertools.workspace = true +serde = { workspace = true, optional = true } smallvec.workspace = true [dev-dependencies] -re_viewer_context = { workspace = true, features = ["testing"] } -re_viewport_blueprint = { workspace = true, features = ["testing"] } re_chunk_store.workspace = true re_view_spatial.workspace = true +re_viewer_context = { workspace = true, features = ["testing"] } +re_viewport_blueprint = { workspace = true, features = ["testing"] } egui_kittest.workspace = true +insta = { workspace = true, features = ["redactions", "yaml"] } diff --git a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs index 8fb9b8d967f08..38b921c25c20d 100644 --- a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs +++ b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs @@ -1,25 +1,23 @@ use egui::{Response, Ui}; -use itertools::Itertools; use smallvec::SmallVec; use re_context_menu::{context_menu_ui_for_item_with_context, SelectionUpdateBehavior}; use re_data_ui::item_ui::guess_instance_path_icon; use re_entity_db::InstancePath; use re_log_types::{ApplicationId, EntityPath}; -use re_types::blueprint::components::Visible; +use re_ui::filter_widget::format_matching_text; use re_ui::{ drag_and_drop::DropTarget, filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _, }; use re_viewer_context::{ contents_name_style, icon_for_container_kind, CollapseScope, ContainerId, Contents, - DataQueryResult, DataResultNode, DragAndDropFeedback, DragAndDropPayload, HoverHighlight, Item, - ItemContext, SystemCommandSender, ViewId, ViewerContext, -}; -use re_viewport_blueprint::{ - ui::show_add_view_or_container_modal, ViewBlueprint, ViewportBlueprint, + DragAndDropFeedback, DragAndDropPayload, HoverHighlight, Item, ItemContext, + SystemCommandSender, ViewId, ViewerContext, }; +use re_viewport_blueprint::{ui::show_add_view_or_container_modal, ViewportBlueprint}; -use crate::data_result_node_or_path::DataResultNodeOrPath; +use crate::data::BlueprintTreeData; +use crate::data::{ContainerData, ContentsData, DataResultData, DataResultKind, ViewData}; /// Holds the state of the blueprint tree UI. #[derive(Default)] @@ -37,7 +35,7 @@ pub struct BlueprintTree { /// See [`Self::is_candidate_drop_parent_container`] for details. candidate_drop_parent_container_id: Option, - /// Candidate parent container to be drawn on next frame. + /// Candidate parent container to be drawn on the next frame. /// /// We double-buffer this value to deal with ordering constraints. next_candidate_drop_parent_container_id: Option, @@ -62,9 +60,11 @@ impl BlueprintTree { pub fn show( &mut self, ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, + viewport_blueprint: &ViewportBlueprint, ui: &mut egui::Ui, ) { + re_tracing::profile_function!(); + // Invalidate the filter widget if the store id has changed. if self.filter_state_app_id.as_ref() != Some(&ctx.store_context.app_id) { self.filter_state = Default::default(); @@ -90,9 +90,9 @@ impl BlueprintTree { } }) .menu_button(&re_ui::icons::MORE, |ui| { - add_new_view_or_container_menu_button(ctx, viewport, ui); + add_new_view_or_container_menu_button(ctx, viewport_blueprint, ui); set_blueprint_to_default_menu_buttons(ctx, ui); - set_blueprint_to_auto_menu_button(ctx, viewport, ui); + set_blueprint_to_auto_menu_button(ctx, viewport_blueprint, ui); }), ); }); @@ -102,14 +102,14 @@ impl BlueprintTree { // This call is excluded from `panel_content` because it has a ScrollArea, which should not be // inset. Instead, it calls panel_content itself inside the ScrollArea. - self.tree_ui(ctx, viewport, ui); + self.tree_ui(ctx, viewport_blueprint, ui); } /// Show the blueprint panel tree view. fn tree_ui( &mut self, ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, + viewport_blueprint: &ViewportBlueprint, ui: &mut egui::Ui, ) { re_tracing::profile_function!(); @@ -118,20 +118,26 @@ impl BlueprintTree { self.candidate_drop_parent_container_id = self.next_candidate_drop_parent_container_id; self.next_candidate_drop_parent_container_id = None; - let filter_matcher = self.filter_state.filter(); + let blueprint_tree_data = BlueprintTreeData::from_blueprint_and_filter( + ctx, + viewport_blueprint, + &self.filter_state.filter(), + ); egui::ScrollArea::both() .id_salt("blueprint_tree_scroll_area") .auto_shrink([true, false]) .show(ui, |ui| { ui.panel_content(|ui| { - self.blueprint_tree_scroll_to_item = ctx - .focused_item - .as_ref() - .and_then(|item| self.handle_focused_item(ctx, viewport, ui, item)); + self.blueprint_tree_scroll_to_item = + ctx.focused_item.as_ref().and_then(|item| { + self.handle_focused_item(ctx, viewport_blueprint, ui, item) + }); list_item::list_item_scope(ui, "blueprint tree", |ui| { - self.root_container_ui(ctx, viewport, ui, &filter_matcher); + if let Some(root_container) = blueprint_tree_data.root_container { + self.root_container_ui(ctx, viewport_blueprint, ui, &root_container); + } }); let empty_space_response = @@ -145,7 +151,7 @@ impl BlueprintTree { // handle drag and drop interaction on empty space self.handle_empty_space_drag_and_drop_interaction( ctx, - viewport, + viewport_blueprint, ui, empty_space_response.rect, ); @@ -153,50 +159,6 @@ impl BlueprintTree { }); } - /// Check if the provided item should be scrolled to. - fn scroll_to_me_if_needed(&self, ui: &egui::Ui, item: &Item, response: &egui::Response) { - if Some(item) == self.blueprint_tree_scroll_to_item.as_ref() { - // Scroll only if the entity isn't already visible. This is important because that's what - // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be - // annoying to induce a scroll motion. - if !ui.clip_rect().contains_rect(response.rect) { - response.scroll_to_me(Some(egui::Align::Center)); - } - } - } - - /// If a group or view has a total of this number of elements, show its subtree by default? - fn default_open_for_data_result(group: &DataResultNode) -> bool { - let num_children = group.children.len(); - 2 <= num_children && num_children <= 3 - } - - fn contents_ui( - &mut self, - ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, - ui: &mut egui::Ui, - contents: &Contents, - parent_visible: bool, - filter_matcher: &filter_widget::FilterMatcher, - ) { - match contents { - Contents::Container(container_id) => { - self.container_ui( - ctx, - viewport, - ui, - container_id, - parent_visible, - filter_matcher, - ); - } - Contents::View(view_id) => { - self.view_ui(ctx, viewport, ui, view_id, parent_visible, filter_matcher); - } - }; - } - /// Display the root container. /// /// The root container is different from other containers in that it cannot be removed or dragged, and it cannot be @@ -204,42 +166,34 @@ impl BlueprintTree { fn root_container_ui( &mut self, ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, + viewport_blueprint: &ViewportBlueprint, ui: &mut egui::Ui, - filter_matcher: &filter_widget::FilterMatcher, + container_data: &ContainerData, ) { - let container_id = viewport.root_container; - if !match_container(ctx, viewport, &container_id, filter_matcher) { - return; - } - - let Some(container_blueprint) = viewport.container(&container_id) else { - re_log::warn!("Failed to find root container {container_id} in ViewportBlueprint"); - return; - }; - - let item = Item::Container(container_id); - let container_name = container_blueprint.display_name_or_default(); + let item = Item::Container(container_data.id); let item_response = ui .list_item() .selected(ctx.selection().contains_item(&item)) .draggable(true) // allowed for consistency but results in an invalid drag - .drop_target_style(self.is_candidate_drop_parent_container(&container_id)) + .drop_target_style(self.is_candidate_drop_parent_container(&container_data.id)) .show_flat( ui, - list_item::LabelContent::new(format!("Viewport ({})", container_name.as_ref())) - .label_style(contents_name_style(&container_name)) - .with_icon(icon_for_container_kind(&container_blueprint.container_kind)), + list_item::LabelContent::new(format!( + "Viewport ({})", + container_data.name.as_ref() + )) + .label_style(contents_name_style(&container_data.name)) + .with_icon(icon_for_container_kind(&container_data.kind)), ); - for child in &container_blueprint.contents { - self.contents_ui(ctx, viewport, ui, child, true, filter_matcher); + for child in &container_data.children { + self.contents_ui(ctx, viewport_blueprint, ui, child, true); } context_menu_ui_for_item_with_context( ctx, - viewport, + viewport_blueprint, &item, // expand/collapse context menu actions need this information ItemContext::BlueprintTree { @@ -253,45 +207,49 @@ impl BlueprintTree { self.handle_root_container_drag_and_drop_interaction( ctx, - viewport, + viewport_blueprint, ui, - Contents::Container(container_id), + Contents::Container(container_data.id), &item_response, ); } + fn contents_ui( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + ui: &mut egui::Ui, + contents_data: &ContentsData, + parent_visible: bool, + ) { + match contents_data { + ContentsData::Container(container_data) => { + self.container_ui(ctx, viewport_blueprint, ui, container_data, parent_visible); + } + ContentsData::View(view_data) => { + self.view_ui(ctx, viewport_blueprint, ui, view_data, parent_visible); + } + }; + } + fn container_ui( &mut self, ctx: &ViewerContext<'_>, viewport: &ViewportBlueprint, ui: &mut egui::Ui, - container_id: &ContainerId, + container_data: &ContainerData, parent_visible: bool, - filter_matcher: &filter_widget::FilterMatcher, ) { - if !match_container(ctx, viewport, container_id, filter_matcher) { - return; - } - - let item = Item::Container(*container_id); - let content = Contents::Container(*container_id); + let item = Item::Container(container_data.id); + let content = Contents::Container(container_data.id); - let Some(container_blueprint) = viewport.container(container_id) else { - re_log::warn_once!("Ignoring unknown container {container_id}"); - return; - }; - - let mut visible = container_blueprint.visible; + let mut visible = container_data.visible; let container_visible = visible && parent_visible; - let default_open = true; - - let container_name = container_blueprint.display_name_or_default(); - - let item_content = list_item::LabelContent::new(container_name.as_ref()) + let item_content = list_item::LabelContent::new(container_data.name.as_ref()) .subdued(!container_visible) - .label_style(contents_name_style(&container_name)) - .with_icon(icon_for_container_kind(&container_blueprint.container_kind)) + .label_style(contents_name_style(&container_data.name)) + .with_icon(icon_for_container_kind(&container_data.kind)) .with_buttons(|ui| { let vis_response = visibility_button_ui(ui, parent_visible, &mut visible); @@ -306,7 +264,7 @@ impl BlueprintTree { // Globally unique id - should only be one of these in view at one time. // We do this so that we can support "collapse/expand all" command. - let id = egui::Id::new(self.collapse_scope().container(*container_id)); + let id = egui::Id::new(self.collapse_scope().container(container_data.id)); let list_item::ShowCollapsingResponse { item_response: response, @@ -316,17 +274,20 @@ impl BlueprintTree { .list_item() .selected(ctx.selection().contains_item(&item)) .draggable(true) - .drop_target_style(self.is_candidate_drop_parent_container(container_id)) - .show_hierarchical_with_children(ui, id, default_open, item_content, |ui| { - for child in &container_blueprint.contents { - self.contents_ui(ctx, viewport, ui, child, container_visible, filter_matcher); - } - }); + .drop_target_style(self.is_candidate_drop_parent_container(&container_data.id)) + .show_hierarchical_with_children( + ui, + id, + container_data.default_open, + item_content, + |ui| { + for child in &container_data.children { + self.contents_ui(ctx, viewport, ui, child, container_visible); + } + }, + ); - let response = response.on_hover_text(format!( - "{:?} container", - container_blueprint.container_kind - )); + let response = response.on_hover_text(format!("{:?} container", container_data.kind)); context_menu_ui_for_item_with_context( ctx, @@ -357,43 +318,24 @@ impl BlueprintTree { fn view_ui( &mut self, ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, + viewport_blueprint: &ViewportBlueprint, ui: &mut egui::Ui, - view_id: &ViewId, + view_data: &ViewData, container_visible: bool, - filter_matcher: &filter_widget::FilterMatcher, ) { - if !match_view(ctx, view_id, filter_matcher) { - return; - } - - let Some(view) = viewport.view(view_id) else { - re_log::warn_once!("Bug: asked to show a UI for a view that doesn't exist"); - return; - }; - debug_assert_eq!(view.id, *view_id); - - let query_result = ctx.lookup_query_result(view.id); - let result_tree = &query_result.tree; - - let mut visible = view.visible; + let mut visible = view_data.visible; let view_visible = visible && container_visible; - let item = Item::View(view.id); - - let root_node = result_tree.root_node(); + let item = Item::View(view_data.id); - // empty views should display as open by default to highlight the fact that they are empty - let default_open = self.filter_state.is_active() - || root_node.map_or(true, Self::default_open_for_data_result); + let class = ctx + .view_class_registry + .get_class_or_log_error(view_data.class_identifier); let is_item_hovered = ctx.selection_state().highlight_for_ui_element(&item) == HoverHighlight::Hovered; - let class = &view.class(ctx.view_class_registry); - let view_name = view.display_name_or_default(); - - let item_content = list_item::LabelContent::new(view_name.as_ref()) - .label_style(contents_name_style(&view_name)) + let item_content = list_item::LabelContent::new(view_data.name.as_ref()) + .label_style(contents_name_style(&view_data.name)) .with_icon(class.icon()) .subdued(!view_visible) .with_buttons(|ui| { @@ -401,8 +343,8 @@ impl BlueprintTree { let response = remove_button_ui(ui, "Remove view from the viewport"); if response.clicked() { - viewport.mark_user_interaction(ctx); - viewport.remove_contents(Contents::View(*view_id)); + viewport_blueprint.mark_user_interaction(ctx); + viewport_blueprint.remove_contents(Contents::View(view_data.id)); } response | vis_response @@ -410,7 +352,7 @@ impl BlueprintTree { // Globally unique id - should only be one of these in view at one time. // We do this so that we can support "collapse/expand all" command. - let id = egui::Id::new(self.collapse_scope().view(*view_id)); + let id = egui::Id::new(self.collapse_scope().view(view_data.id)); let list_item::ShowCollapsingResponse { item_response: response, @@ -421,66 +363,25 @@ impl BlueprintTree { .selected(ctx.selection().contains_item(&item)) .draggable(true) .force_hovered(is_item_hovered) - .show_hierarchical_with_children(ui, id, default_open, item_content, |ui| { - // Always show the origin hierarchy first. - self.data_result_ui( - ctx, - viewport, - ui, - query_result, - &DataResultNodeOrPath::from_path_lookup(result_tree, &view.space_origin), - view, - view_visible, - false, - filter_matcher, - ); - - // Show 'projections' if there's any items that weren't part of the tree under origin but are directly included. - // The latter is important since `+ image/camera/**` necessarily has `image` and `image/camera` in the data result tree. - let mut projections = Vec::new(); - result_tree.visit(&mut |node| { - if node.data_result.entity_path.starts_with(&view.space_origin) { - false // If it's under the origin, we're not interested, stop recursing. - } else if node.data_result.tree_prefix_only { - true // Keep recursing until we find a projection. - } else { - // We found a projection, but we must check if it is ruled out by the - // filter. - if self.match_data_result( - query_result, - &DataResultNodeOrPath::DataResultNode(node), - view, - true, - filter_matcher, - ) { - projections.push(node); - } - - // No further recursion needed in this branch, everything below is included - // in the projection (or shouldn't be included if the projection has already - // been filtered out). - false - } - }); + .show_hierarchical_with_children(ui, id, view_data.default_open, item_content, |ui| { + if let Some(data_result_data) = &view_data.origin_tree { + self.data_result_ui( + ctx, + viewport_blueprint, + ui, + data_result_data, + view_visible, + ); + } - if !projections.is_empty() { + if !view_data.projection_trees.is_empty() { ui.list_item().interactive(false).show_flat( ui, list_item::LabelContent::new("Projections:").italics(true), ); - for projection in projections { - self.data_result_ui( - ctx, - viewport, - ui, - query_result, - &DataResultNodeOrPath::DataResultNode(projection), - view, - view_visible, - true, - filter_matcher, - ); + for projection in &view_data.projection_trees { + self.data_result_ui(ctx, viewport_blueprint, ui, projection, view_visible); } } }); @@ -488,12 +389,12 @@ impl BlueprintTree { let response = response.on_hover_text(format!("{} view", class.display_name())); if response.clicked() { - viewport.focus_tab(view.id); + viewport_blueprint.focus_tab(view_data.id); } context_menu_ui_for_item_with_context( ctx, - viewport, + viewport_blueprint, &item, // expand/collapse context menu actions need this information ItemContext::BlueprintTree { @@ -505,12 +406,12 @@ impl BlueprintTree { self.scroll_to_me_if_needed(ui, &item, &response); ctx.handle_select_hover_drag_interactions(&response, item, true); - let content = Contents::View(*view_id); + let content = Contents::View(view_data.id); - viewport.set_content_visibility(ctx, &content, visible); + viewport_blueprint.set_content_visibility(ctx, &content, visible); self.handle_drag_and_drop_interaction( ctx, - viewport, + viewport_blueprint, ui, content, &response, @@ -522,85 +423,87 @@ impl BlueprintTree { fn data_result_ui( &self, ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, + viewport_blueprint: &ViewportBlueprint, ui: &mut egui::Ui, - query_result: &DataQueryResult, - node_or_path: &DataResultNodeOrPath<'_>, - view: &ViewBlueprint, + data_result_data: &DataResultData, view_visible: bool, - projection_mode: bool, - filter_matcher: &filter_widget::FilterMatcher, ) { - if !self.match_data_result( - query_result, - node_or_path, - view, - projection_mode, - filter_matcher, - ) { - return; - } + let item = Item::DataResult( + data_result_data.view_id, + data_result_data.entity_path.clone().into(), + ); - let entity_path = node_or_path.path(); - let display_origin_placeholder = projection_mode && entity_path == &view.space_origin; - if display_origin_placeholder { - if ui - .list_item() - .show_hierarchical( - ui, - list_item::LabelContent::new("$origin") - .subdued(true) - .italics(true) - .with_icon(&re_ui::icons::INTERNAL_LINK), - ) - .on_hover_text( - "This subtree corresponds to the View's origin, and is displayed above \ - the 'Projections' section. Click to select it.", - ) - .clicked() - { - ctx.selection_state().set_selection(Item::DataResult( - view.id, - InstancePath::entity_all(entity_path.clone()), + let item_content = match data_result_data.kind { + DataResultKind::EmptyOriginPlaceholder | DataResultKind::EntityPart => { + let is_empty_origin_placeholder = matches!( + data_result_data.kind, + DataResultKind::EmptyOriginPlaceholder + ); + + let item_content = list_item::LabelContent::new(format_matching_text( + ctx.egui_ctx, + &data_result_data.label, + data_result_data.highlight_sections.iter().cloned(), + is_empty_origin_placeholder.then(|| ui.visuals().warn_fg_color), + )) + .with_icon(guess_instance_path_icon( + ctx, + &data_result_data.instance_path(), )); - } - return; - } - let data_result_node = node_or_path.data_result_node(); + if is_empty_origin_placeholder { + item_content.subdued(true) + } else { + item_content + .subdued(!view_visible || !data_result_data.visible) + .with_buttons(|ui: &mut egui::Ui| { + let mut visible_after = data_result_data.visible; + let vis_response = + visibility_button_ui(ui, view_visible, &mut visible_after); + if visible_after != data_result_data.visible { + data_result_data.update_visibility(ctx, visible_after); + } + + let response = remove_button_ui( + ui, + "Remove this entity and all its children from the view", + ); + if response.clicked() { + data_result_data + .remove_data_result_from_view(ctx, viewport_blueprint); + } - let item = Item::DataResult(view.id, entity_path.clone().into()); - let is_selected = ctx.selection().contains_item(&item); - let is_item_hovered = - ctx.selection_state().highlight_for_ui_element(&item) == HoverHighlight::Hovered; + response | vis_response + }) + } + } - let visible = data_result_node.is_some_and(|n| n.data_result.is_visible(ctx)); - let empty_origin = entity_path == &view.space_origin && data_result_node.is_none(); + DataResultKind::OriginProjectionPlaceholder => { + if ui + .list_item() + .show_hierarchical( + ui, + list_item::LabelContent::new("$origin") + .subdued(true) + .italics(true) + .with_icon(&re_ui::icons::INTERNAL_LINK), + ) + .on_hover_text( + "This subtree corresponds to the view's origin, and is displayed above \ + the 'Projections' section. Click to select it.", + ) + .clicked() + { + ctx.selection_state().set_selection(item); + } - let item_label = if entity_path.is_root() { - "/ (root)".to_owned() - } else { - entity_path - .iter() - .last() - .map_or("unknown".to_owned(), |e| e.ui_string()) - }; - let item_label = if ctx.recording().is_known_entity(entity_path) { - filter_matcher - .matches_formatted(ui.ctx(), &item_label) - .unwrap_or_else(|| item_label.into()) - } else { - ui.ctx().warning_text(item_label).into() + return; + } }; - let subdued = !view_visible || !visible; - - let mut item_content = list_item::LabelContent::new(item_label) - .with_icon(guess_instance_path_icon( - ctx, - &InstancePath::from(entity_path.clone()), - )) - .subdued(subdued); + let is_selected = ctx.selection().contains_item(&item); + let is_item_hovered = + ctx.selection_state().highlight_for_ui_element(&item) == HoverHighlight::Hovered; let list_item = ui .list_item() @@ -608,76 +511,28 @@ impl BlueprintTree { .selected(is_selected) .force_hovered(is_item_hovered); - // We force the origin to be displayed, even if it's fully empty, in which case it can be - // neither shown/hidden nor removed. - if !empty_origin { - item_content = item_content.with_buttons(|ui: &mut egui::Ui| { - let mut visible_after = visible; - let vis_response = visibility_button_ui(ui, view_visible, &mut visible_after); - if visible_after != visible { - if let Some(data_result_node) = data_result_node { - data_result_node - .data_result - .save_recursive_override_or_clear_if_redundant( - ctx, - &query_result.tree, - &Visible::from(visible_after), - ); - } - } - - let response = - remove_button_ui(ui, "Remove this entity and all its children from the view"); - if response.clicked() { - view.contents - .remove_subtree_and_matching_rules(ctx, entity_path.clone()); - } - - response | vis_response - }); - } - // If there's any children on the data result nodes, show them, otherwise we're good with this list item as is. - let has_children = data_result_node.is_some_and(|n| !n.children.is_empty()); - let response = if let (true, Some(node)) = (has_children, data_result_node) { - // Don't default open projections. - let default_open = self.filter_state.is_active() - || (entity_path.starts_with(&view.space_origin) - && Self::default_open_for_data_result(node)); - + let has_children = !data_result_data.children.is_empty(); //data_result_node.is_some_and(|n| !n.children.is_empty()); + let response = if has_children { // Globally unique id - should only be one of these in view at one time. // We do this so that we can support "collapse/expand all" command. - let id = egui::Id::new( - self.collapse_scope() - .data_result(view.id, entity_path.clone()), - ); + let id = egui::Id::new(self.collapse_scope().data_result( + data_result_data.view_id, + data_result_data.entity_path.clone(), + )); list_item - .show_hierarchical_with_children(ui, id, default_open, item_content, |ui| { - for child in node.children.iter().sorted_by_key(|c| { - query_result - .tree - .lookup_result(**c) - .map_or(&view.space_origin, |c| &c.entity_path) - }) { - let Some(child_node) = query_result.tree.lookup_node(*child) else { - debug_assert!(false, "DataResultNode {node:?} has an invalid child"); - continue; - }; - - self.data_result_ui( - ctx, - viewport, - ui, - query_result, - &DataResultNodeOrPath::DataResultNode(child_node), - view, - view_visible, - projection_mode, - filter_matcher, - ); - } - }) + .show_hierarchical_with_children( + ui, + id, + data_result_data.default_open, + item_content, + |ui| { + for child in &data_result_data.children { + self.data_result_ui(ctx, viewport_blueprint, ui, child, view_visible); + } + }, + ) .item_response } else { list_item.show_hierarchical(ui, item_content) @@ -691,11 +546,14 @@ impl BlueprintTree { ctx, &query, ctx.recording(), - entity_path, + &data_result_data.entity_path, include_subtree, ); - if empty_origin { + if matches!( + data_result_data.kind, + DataResultKind::EmptyOriginPlaceholder + ) { ui.label(ui.ctx().warning_text( "This view's query did not match any data under the space origin", )); @@ -704,7 +562,7 @@ impl BlueprintTree { context_menu_ui_for_item_with_context( ctx, - viewport, + viewport_blueprint, &item, // expand/collapse context menu actions need this information ItemContext::BlueprintTree { @@ -717,80 +575,16 @@ impl BlueprintTree { ctx.handle_select_hover_drag_interactions(&response, item, true); } - /// Should this data result (and its children) be displayed? - fn match_data_result( - &self, - query_result: &DataQueryResult, - node_or_path: &DataResultNodeOrPath<'_>, - view: &ViewBlueprint, - projection_mode: bool, - filter_matcher: &filter_widget::FilterMatcher, - ) -> bool { - let entity_path = node_or_path.path(); - let display_origin_placeholder = projection_mode && entity_path == &view.space_origin; - - if filter_matcher.matches_nothing() { - return false; - } - - // Filter is inactive or otherwise whitelisting everything. - if filter_matcher.matches_everything() { - return true; - } - - // We never display the origin placeholder if the filter is active, because if the - // `$origin` subtree matched something, it would be visible in the non-projected - // data-results. - if display_origin_placeholder && self.filter_state.is_active() { - return false; - } - - // Is the current path a match? - // - // This is subtle! If we are in projection mode, we check for all parts starting at the - // root for a match. However, if we are _not_ in projection mode, we skip checking the - // origin part (which is always the first part of the entity path in this case), because - // that part is not displayed and, as such, should not trigger a match. - if entity_path - .iter() - .skip( - if !projection_mode && entity_path.starts_with(&view.space_origin) { - view.space_origin.len() - } else { - 0 - }, - ) - .any(|entity_part| filter_matcher.matches(&entity_part.ui_string())) - { - return true; - } - - // Our subtree contains a match. - if let Some(node) = node_or_path.data_result_node() { - if query_result - .tree - .find_node_by(Some(node), |node| { - // If are in projection mode, we must reject anything that is the origin or - // its child. If there was a match there, then it would be displayed in the - // non-projected data results. - if projection_mode - && node.data_result.entity_path.starts_with(&view.space_origin) - { - return false; - } - - node.data_result - .entity_path - .last() - .is_some_and(|entity_part| filter_matcher.matches(&entity_part.ui_string())) - }) - .is_some() - { - return true; + /// Check if the provided item should be scrolled to. + fn scroll_to_me_if_needed(&self, ui: &egui::Ui, item: &Item, response: &egui::Response) { + if Some(item) == self.blueprint_tree_scroll_to_item.as_ref() { + // Scroll only if the entity isn't already visible. This is important because that's what + // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be + // annoying to induce a scroll motion. + if !ui.clip_rect().contains_rect(response.rect) { + response.scroll_to_me(Some(egui::Align::Center)); } } - - false } // ---------------------------------------------------------------------------- @@ -1030,7 +824,7 @@ impl BlueprintTree { self.candidate_drop_parent_container_id.as_ref() == Some(container_id) } - fn collapse_scope(&self) -> CollapseScope { + pub fn collapse_scope(&self) -> CollapseScope { match self.filter_state.session_id() { None => CollapseScope::BlueprintTree, Some(session_id) => CollapseScope::BlueprintTreeFiltered { session_id }, @@ -1157,69 +951,6 @@ impl BlueprintTree { // ---------------------------------------------------------------------------- -fn match_container( - ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, - container_id: &ContainerId, - filter_matcher: &filter_widget::FilterMatcher, -) -> bool { - if filter_matcher.matches_everything() { - return true; - } - - if filter_matcher.matches_nothing() { - return false; - } - - viewport - .find_contents_in_container_by( - &|content| { - // dont recurse infinitely - if content == &Contents::Container(*container_id) { - return false; - } - - match content { - Contents::Container(container_id) => { - match_container(ctx, viewport, container_id, filter_matcher) - } - Contents::View(view_id) => match_view(ctx, view_id, filter_matcher), - } - }, - container_id, - ) - .is_some() -} - -/// Does this view match the provided filter? -fn match_view( - ctx: &ViewerContext<'_>, - view_id: &ViewId, - filter_matcher: &filter_widget::FilterMatcher, -) -> bool { - if filter_matcher.matches_everything() { - return true; - } - - if filter_matcher.matches_nothing() { - return false; - }; - - let query_result = ctx.lookup_query_result(*view_id); - let result_tree = &query_result.tree; - - result_tree - .find_node_by(None, |node| { - node.data_result - .entity_path - .last() - .is_some_and(|entity_part| filter_matcher.matches(&entity_part.ui_string())) - }) - .is_some() -} - -// ---------------------------------------------------------------------------- - /// Add a button to trigger the addition of a new view or container. fn add_new_view_or_container_menu_button( ctx: &ViewerContext<'_>, diff --git a/crates/viewer/re_blueprint_tree/src/data.rs b/crates/viewer/re_blueprint_tree/src/data.rs new file mode 100644 index 0000000000000..63c5a36f0b623 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/src/data.rs @@ -0,0 +1,509 @@ +//! Data structure describing the contents of the blueprint tree +//! +//! The design goal of these structures is to cover the entire underlying tree (container hierarchy +//! and data result hierarchies) by walking it once entirely, applying filtering on the way. +//! +//! This is done regardless of whether the data is actually used by the UI (e.g. if everything is +//! collapsed). Benchmarks have indicated that this approach incurs a negligible overhead compared +//! to the overall cost of having large blueprint trees (a.k.a the many-entities performance +//! issues: ). + +use std::ops::Range; + +use itertools::Itertools; +use smallvec::SmallVec; + +use re_entity_db::InstancePath; +use re_log_types::external::re_types_core::ViewClassIdentifier; +use re_log_types::{EntityPath, EntityPathPart}; +use re_types::blueprint::components::Visible; +use re_ui::filter_widget::FilterMatcher; +use re_viewer_context::{ + ContainerId, Contents, ContentsName, DataQueryResult, DataResultNode, ViewId, ViewerContext, +}; +use re_viewport_blueprint::{ContainerBlueprint, ViewBlueprint, ViewportBlueprint}; + +use crate::data_result_node_or_path::DataResultNodeOrPath; + +/// Top-level blueprint tree structure. +#[derive(Debug, Default)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] +pub struct BlueprintTreeData { + pub root_container: Option, +} + +impl BlueprintTreeData { + pub fn from_blueprint_and_filter( + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + filter_matcher: &FilterMatcher, + ) -> Self { + re_tracing::profile_function!(); + + Self { + root_container: viewport_blueprint + .container(&viewport_blueprint.root_container) + .and_then(|container_blueprint| { + ContainerData::from_blueprint_and_filter( + ctx, + viewport_blueprint, + container_blueprint, + filter_matcher, + ) + }), + } + } +} + +// --- + +/// Data for either a container or a view (both of which possible child of a container). +#[derive(Debug)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] +pub enum ContentsData { + Container(ContainerData), + View(ViewData), +} + +/// Data related to a single container and its children. +#[derive(Debug)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] +pub struct ContainerData { + pub id: ContainerId, + pub name: ContentsName, + pub kind: egui_tiles::ContainerKind, + pub visible: bool, + pub default_open: bool, + + pub children: Vec, +} + +impl ContainerData { + pub fn from_blueprint_and_filter( + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + container_blueprint: &ContainerBlueprint, + filter_matcher: &FilterMatcher, + ) -> Option { + let children = container_blueprint + .contents + .iter() + .filter_map(|content| match content { + Contents::Container(container_id) => { + if let Some(container_blueprint) = viewport_blueprint.container(container_id) { + Self::from_blueprint_and_filter( + ctx, + viewport_blueprint, + container_blueprint, + filter_matcher, + ) + .map(ContentsData::Container) + } else { + re_log::warn_once!( + "Failed to find container {container_id} in ViewportBlueprint" + ); + None + } + } + Contents::View(view_id) => { + if let Some(view_blueprint) = viewport_blueprint.view(view_id) { + ViewData::from_blueprint_and_filter(ctx, view_blueprint, filter_matcher) + .map(ContentsData::View) + } else { + re_log::warn_once!("Failed to find view {view_id} in ViewportBlueprint"); + None + } + } + }) + .collect_vec(); + + // everything was filtered out + if filter_matcher.is_active() && children.is_empty() { + return None; + } + + Some(Self { + id: container_blueprint.id, + name: container_blueprint.display_name_or_default(), + kind: container_blueprint.container_kind, + visible: container_blueprint.visible, + default_open: true, + children, + }) + } +} + +// --- + +/// Data related to a single view and its content. +#[derive(Debug)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] +pub struct ViewData { + pub id: ViewId, + + pub class_identifier: ViewClassIdentifier, + + pub name: ContentsName, + pub visible: bool, + pub default_open: bool, + + /// The origin tree contains the data results contained in the subtree defined by the view + /// origin. They are presented first in the blueprint tree. + pub origin_tree: Option, + + /// Projection trees are the various trees contained data results which are outside the view + /// origin subtrees. They are presented after a "Projections:" label in the blueprint tree. + /// + /// These trees may be super-trees of the view origin trees. In that case, the view origin + /// subtree is represented by a stub item, see [`DataResultKind::OriginProjectionPlaceholder`]. + pub projection_trees: Vec, +} + +impl ViewData { + fn from_blueprint_and_filter( + ctx: &ViewerContext<'_>, + view_blueprint: &ViewBlueprint, + filter_matcher: &FilterMatcher, + ) -> Option { + re_tracing::profile_function!(); + + let query_result = ctx.lookup_query_result(view_blueprint.id); + let result_tree = &query_result.tree; + + // + // Data results within the view origin subtree + // + + let mut hierarchy = Vec::with_capacity(10); + let origin_tree = DataResultData::from_data_result_and_filter( + ctx, + view_blueprint, + query_result, + &DataResultNodeOrPath::from_path_lookup(result_tree, &view_blueprint.space_origin), + false, + &mut hierarchy, + filter_matcher, + false, + ); + + debug_assert!(hierarchy.is_empty()); + hierarchy.clear(); + + // + // Data results outside the view origin subtree (a.k.a projections) + // + + let mut projections = Vec::new(); + result_tree.visit(&mut |node| { + if node + .data_result + .entity_path + .starts_with(&view_blueprint.space_origin) + { + // If it's under the origin, we're not interested, stop recursing. + false + } else if node.data_result.tree_prefix_only { + // Keep recursing until we find a projection. + true + } else { + projections.push(node); + + // No further recursion needed in this branch, everything below is included + // in the projection (or shouldn't be included if the projection has already + // been filtered out). + false + } + }); + + let projection_trees = projections + .into_iter() + .filter_map(|node| { + let projection_tree = DataResultData::from_data_result_and_filter( + ctx, + view_blueprint, + query_result, + &DataResultNodeOrPath::DataResultNode(node), + true, + &mut hierarchy, + filter_matcher, + false, + ); + + debug_assert!(hierarchy.is_empty()); + hierarchy.clear(); + + projection_tree + }) + .collect_vec(); + + if origin_tree.is_none() && projection_trees.is_empty() { + return None; + } + + let default_open = filter_matcher.is_active() + || origin_tree.as_ref().map_or(true, |data_result_data| { + default_open_for_data_result(data_result_data.children.len()) + }); + + Some(Self { + id: view_blueprint.id, + class_identifier: view_blueprint.class_identifier(), + name: view_blueprint.display_name_or_default(), + visible: view_blueprint.visible, + default_open, + origin_tree, + projection_trees, + }) + } +} + +// --- + +/// The various kind of things that may be represented in a data result tree. +#[derive(Debug)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] +pub enum DataResultKind { + /// This is a regular entity part of a data result (or the tree that contains it). + EntityPart, + + /// When the view has no data result contained in the view origin subtree, we still display the + /// origin with a warning styling to highlight what is likely an undesired view configuration. + EmptyOriginPlaceholder, + + /// Since the view origin tree is displayed on its own, we don't repeat it within projections + /// and instead replace it with this placeholder. + OriginProjectionPlaceholder, +} + +#[derive(Debug)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] +pub struct DataResultData { + pub kind: DataResultKind, + pub entity_path: EntityPath, + pub visible: bool, + + pub view_id: ViewId, + + /// Label that should be used for display. + /// + /// This typically corresponds to `entity_path.last().ui_string()` but covers corner cases. + pub label: String, + + /// The sections within the label that correspond to a filter match and should thus be + /// highlighted. + pub highlight_sections: SmallVec<[Range; 1]>, + + pub default_open: bool, + pub children: Vec, +} + +impl DataResultData { + #[allow(clippy::too_many_arguments)] + fn from_data_result_and_filter( + ctx: &ViewerContext<'_>, + view_blueprint: &ViewBlueprint, + query_result: &DataQueryResult, + data_result_or_path: &DataResultNodeOrPath<'_>, + projection: bool, + hierarchy: &mut Vec, + filter_matcher: &FilterMatcher, + mut is_already_a_match: bool, + ) -> Option { + re_tracing::profile_function!(); + + // Early out. + if filter_matcher.matches_nothing() { + return None; + } + + let entity_path = data_result_or_path.path().clone(); + let data_result_node = data_result_or_path.data_result_node(); + let visible = data_result_node.is_some_and(|node| node.data_result.is_visible(ctx)); + + let (label, should_pop) = if let Some(entity_part) = entity_path.last() { + hierarchy.push(entity_part.clone()); + (entity_part.ui_string(), true) + } else { + ("/ (root)".to_owned(), false) + }; + + // + // Filtering + // + + // TODO(ab): we're currently only matching on the last part of `hierarchy`. Technically, + // this means that `hierarchy` is not needed at all. It will however be needed when we match + // across multiple parts, so it's good to have it already. + let (entity_part_matches, highlight_sections) = if filter_matcher.matches_everything() { + // fast path (filter is inactive) + (true, SmallVec::new()) + } else if let Some(entity_part) = hierarchy.last() { + // Nominal case of matching the hierarchy. + if let Some(match_sections) = filter_matcher.find_matches(&entity_part.ui_string()) { + (true, match_sections.collect()) + } else { + (false, SmallVec::new()) + } + } else { + // `entity_path` is the root, it can never match anything + (false, SmallVec::new()) + }; + + // We want to keep entire branches if a single of its node matches. So we must propagate the + // "matched" state so we can make the right call when we reach leaf nodes. + is_already_a_match |= entity_part_matches; + + // + // "Nominal" data result node (extracted for deduplication). + // + + let view_id = view_blueprint.id; + let mut from_data_result_node = |data_result_node: &DataResultNode, + highlight_sections: SmallVec<_>, + entity_path: EntityPath, + label, + default_open| { + let mut children = data_result_node + .children + .iter() + .filter_map(|child_handle| { + let child_node = query_result.tree.lookup_node(*child_handle); + + debug_assert!( + child_node.is_some(), + "DataResultNode {data_result_node:?} has an invalid child" + ); + + child_node.and_then(|child_node| { + Self::from_data_result_and_filter( + ctx, + view_blueprint, + query_result, + &DataResultNodeOrPath::DataResultNode(child_node), + projection, + hierarchy, + filter_matcher, + is_already_a_match, + ) + }) + }) + .collect_vec(); + + children.sort_by(|a, b| a.entity_path.cmp(&b.entity_path)); + + (is_already_a_match || !children.is_empty()).then(|| Self { + kind: DataResultKind::EntityPart, + entity_path, + visible, + view_id, + label, + highlight_sections, + default_open, + children, + }) + }; + + // + // Handle all situations + // + + let result = if projection { + // projections are collapsed by default + let default_open = filter_matcher.is_active(); + + if entity_path == view_blueprint.space_origin { + is_already_a_match.then(|| Self { + kind: DataResultKind::OriginProjectionPlaceholder, + entity_path, + visible, + view_id, + label, + highlight_sections, + default_open, + children: vec![], + }) + } else if let Some(data_result_node) = data_result_node { + from_data_result_node( + data_result_node, + highlight_sections, + entity_path, + label, + filter_matcher.is_active(), + ) + } else { + // TODO(ab): what are the circumstances for this? Should we warn about it? + None + } + } else { + // empty origin case + if entity_path == view_blueprint.space_origin && data_result_node.is_none() { + is_already_a_match.then(|| Self { + kind: DataResultKind::EmptyOriginPlaceholder, + entity_path, + visible, + view_id, + label, + highlight_sections, + default_open: false, // not hierarchical anyway + children: vec![], + }) + } else if let Some(data_result_node) = data_result_node { + let default_open = filter_matcher.is_active() + || default_open_for_data_result(data_result_node.children.len()); + + from_data_result_node( + data_result_node, + highlight_sections, + entity_path, + label, + default_open, + ) + } else { + // TODO(ab): what are the circumstances for this? Should we warn about it? + None + } + }; + + if should_pop { + hierarchy.pop(); + } + + result + } + + pub fn instance_path(&self) -> InstancePath { + self.entity_path.clone().into() + } + + /// Update the visibility of this data result. + pub fn update_visibility(&self, ctx: &ViewerContext<'_>, visible: bool) { + let query_result = ctx.lookup_query_result(self.view_id); + let result_tree = &query_result.tree; + if let Some(data_result) = result_tree.lookup_result_by_path(&self.entity_path) { + data_result.save_recursive_override_or_clear_if_redundant( + ctx, + &query_result.tree, + &Visible::from(visible), + ); + } + } + + /// Remove this data result from the view. + pub fn remove_data_result_from_view( + &self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + ) { + if let Some(view_blueprint) = viewport_blueprint.view(&self.view_id) { + view_blueprint + .contents + .remove_subtree_and_matching_rules(ctx, self.entity_path.clone()); + } + } +} + +/// If a group or view has a total of this number of elements, show its subtree by default? +//TODO(ab): taken from legacy implementation, does it still make sense? +fn default_open_for_data_result(num_children: usize) -> bool { + 2 <= num_children && num_children <= 3 +} diff --git a/crates/viewer/re_blueprint_tree/src/lib.rs b/crates/viewer/re_blueprint_tree/src/lib.rs index bc1f8000b3879..39cb4b301d8a3 100644 --- a/crates/viewer/re_blueprint_tree/src/lib.rs +++ b/crates/viewer/re_blueprint_tree/src/lib.rs @@ -1,6 +1,12 @@ //! This crate implements the UI for the blueprint tree in the left panel. mod blueprint_tree; + +#[cfg(feature = "testing")] +pub mod data; + +#[cfg(not(feature = "testing"))] +pub(crate) mod data; mod data_result_node_or_path; pub use blueprint_tree::BlueprintTree; diff --git a/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs b/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs index a5763373ac071..a07681b53fd9c 100644 --- a/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs +++ b/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "testing")] + use egui::Vec2; use re_blueprint_tree::BlueprintTree; @@ -5,7 +7,9 @@ use re_chunk_store::external::re_chunk::ChunkBuilder; use re_chunk_store::RowId; use re_log_types::build_frame_nr; use re_types::archetypes::Points3D; -use re_viewer_context::{test_context::TestContext, CollapseScope, RecommendedView, ViewClass}; +use re_viewer_context::{ + test_context::TestContext, CollapseScope, RecommendedView, ViewClass, ViewId, +}; use re_viewport_blueprint::{ test_context_ext::TestContextExt as _, ViewBlueprint, ViewportBlueprint, }; @@ -51,19 +55,19 @@ fn collapse_expand_all_blueprint_panel_should_match_snapshot() { test_context.log_entity("/path/to/entity1".into(), add_point_to_chunk_builder); test_context.log_entity("/another/way/to/entity2".into(), add_point_to_chunk_builder); - let view_id = test_context.setup_viewport_blueprint(|_ctx, blueprint| { - let view = ViewBlueprint::new( + let view_id = ViewId::hashed_from_str("some-view-id-hash"); + + test_context.setup_viewport_blueprint(|_ctx, blueprint| { + let view = ViewBlueprint::new_with_id( re_view_spatial::SpatialView3D::identifier(), RecommendedView::root(), + view_id, ); - let view_id = view.id; blueprint.add_views(std::iter::once(view), None, None); // TODO(ab): add containers in the hierarchy (requires work on the container API, // currently very cumbersome to use for testing purposes). - - view_id }); let mut blueprint_tree = BlueprintTree::default(); diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_above_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_above_origin.png index a7fa222be7b68..ccd83e0307ae1 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_above_origin.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_above_origin.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f6d2f7f5ee34fa4fc0609c55a3dca06cea2984d1d6a99569014e8801fcb07a0 -size 22280 +oid sha256:7357c66c618ecbdfbd1f3af3cdc6f684336e90926c99b3358b4964fd07b77090 +size 24034 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/empty.png new file mode 100644 index 0000000000000..5b571fb638a08 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:deb78300c1479f2b096e8d8de36a1e6c966dc713b264cf62587e0691e56cf4ad +size 15302 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/multiple_proj.png new file mode 100644 index 0000000000000..88ef30df521cb --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cca67ba9bb1cabbb116a1a7efc9277fb139e6563e93c575f2c9d60bbe41ef837 +size 22066 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/non_root_origin.png new file mode 100644 index 0000000000000..239e2d74123d4 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb9cbc8f2527196235106bd1d64f795d44f4f21965bdecbaf21453bd17335c5f +size 20070 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png new file mode 100644 index 0000000000000..559a159104b4c --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:376195ce2c78131a841a1821ff671f385e573288ddec37d5c5d5650b675c4622 +size 29183 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png new file mode 100644 index 0000000000000..7d21ee0c45707 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4691797c61a5102ffd886b4710c8dc4b80a70b715d7a8b25018a6dfce4c98ff0 +size 24161 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/single_proj.png new file mode 100644 index 0000000000000..7d4c9b089603f --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7395f95a2a90fc21b7065ac0d69f54366b2894af313be320f2f978b15193ae96 +size 23788 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/unknown_origin.png new file mode 100644 index 0000000000000..5176adc59a787 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:083cbd36db0cd1bbf54ebf88dd8bb6fabf778e859f1b1cea9228a4b09aa2d23f +size 16721 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/empty.png new file mode 100644 index 0000000000000..1ba890fb15375 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28b601ca8a0080da7219f9765fedb28bc6429a0f4ca963bbb5ee161a080e84b1 +size 10203 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/multiple_proj.png new file mode 100644 index 0000000000000..1ba890fb15375 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28b601ca8a0080da7219f9765fedb28bc6429a0f4ca963bbb5ee161a080e84b1 +size 10203 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/non_root_origin.png new file mode 100644 index 0000000000000..1ba890fb15375 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28b601ca8a0080da7219f9765fedb28bc6429a0f4ca963bbb5ee161a080e84b1 +size 10203 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png new file mode 100644 index 0000000000000..c7c94cca8c4b4 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27c98e696b61320f03b47a7f91a38e8cc0bd186dbc7661c0d2b36b4ea38f54b7 +size 21630 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png new file mode 100644 index 0000000000000..39325a1624d63 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7fc9099bc9bce0336a1f82b849009709efbe6bf682d7422377d51b4873574502 +size 21422 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/single_proj.png new file mode 100644 index 0000000000000..1ba890fb15375 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28b601ca8a0080da7219f9765fedb28bc6429a0f4ca963bbb5ee161a080e84b1 +size 10203 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/unknown_origin.png new file mode 100644 index 0000000000000..90ca003c26473 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79b5e3b2a8565ec802d43ead2f95ad46dfae013b643399860dd0a2ab63708a52 +size 16647 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/empty.png new file mode 100644 index 0000000000000..4a05b6f46985d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5d221abb19b3e530beb74c287780f536e490c59dcade30b30f06a54dbf0c10e +size 9650 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/multiple_proj.png new file mode 100644 index 0000000000000..e04149cb42c36 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:235cb85c828dcb94ae3343b94ab27d5073a92ffd15dcb9ea65b15024563f58cf +size 20257 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/non_root_origin.png new file mode 100644 index 0000000000000..0c783b9bf9d02 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28464a68f749aa952d3b67d6efe45d820b7157882b9e4c4de491fa32a772e0f5 +size 19413 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png new file mode 100644 index 0000000000000..92fe911ee3dfd --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5735ced6fd972b257cb7a3d9c65fc81495fa5c01c76af4df85c79ced033d26c9 +size 28591 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png new file mode 100644 index 0000000000000..62bd11e2412a0 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d51d3c378e5ef7a31dee7a05a7192b3c2a4c301f3976fcff7a896a73dcb4442f +size 23569 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/single_proj.png new file mode 100644 index 0000000000000..7e4994add3aac --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f8ebe3a4bfa35246fbcc0ad3e624328b69b36e926637951b9193ab3e28c04b0 +size 22032 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/unknown_origin.png new file mode 100644 index 0000000000000..d3be09a32d344 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be54ffe77e68e2e896807f5afd08bbfe75d51cffaefdaa1add891b8bcf1e56cb +size 16015 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/empty.png new file mode 100644 index 0000000000000..bf4a8cd4db6f5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65102d91a1f5f99c7eda9c17d4bedd66291788084f443e9e1d1ecdd1790ca5a6 +size 10232 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/multiple_proj.png new file mode 100644 index 0000000000000..6d5c8d147e6d0 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b7000931dba10b877f9333762a1efe33314f7a35e7ec2392cfae5db3d0cfc6b +size 19711 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/non_root_origin.png new file mode 100644 index 0000000000000..9bcdecd6854fe --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42d6cb895d0c28c778155c0b7c99366e30ad6cba0c2b1567ff952da6f6709a41 +size 17939 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/proj_with_placeholder.png new file mode 100644 index 0000000000000..9bcdecd6854fe --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42d6cb895d0c28c778155c0b7c99366e30ad6cba0c2b1567ff952da6f6709a41 +size 17939 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/root_origin.png new file mode 100644 index 0000000000000..10a359268b6ad --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c74ec0d271594999ac2f1c86b960176bb62cd8f8cdb2920450e24d035eba0cec +size 19523 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/single_proj.png new file mode 100644 index 0000000000000..dae559723ae3a --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a64ddb5afa41613ce6741c854c6fbd7d2af489eeb7eb5bdeae43a347e24bd79b +size 20557 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/unknown_origin.png new file mode 100644 index 0000000000000..bf4a8cd4db6f5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-void/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65102d91a1f5f99c7eda9c17d4bedd66291788084f443e9e1d1ecdd1790ca5a6 +size 10232 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-empty.snap new file mode 100644 index 0000000000000..2feaee91c8e0a --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-empty.snap @@ -0,0 +1,32 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: false + origin_tree: + kind: EmptyOriginPlaceholder + entity_path: [] + visible: false + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: false + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-multiple_proj.snap new file mode 100644 index 0000000000000..9da05a081b2eb --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-multiple_proj.snap @@ -0,0 +1,71 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: false + origin_tree: + kind: EntityPart + entity_path: + - center + - way + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: way + highlight_sections: [] + default_open: false + children: [] + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-non_root_origin.snap new file mode 100644 index 0000000000000..dcd755fb910bc --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-non_root_origin.snap @@ -0,0 +1,83 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: false + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-proj_with_placeholder.snap new file mode 100644 index 0000000000000..358a6ce9c6fcd --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-proj_with_placeholder.snap @@ -0,0 +1,134 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: false + children: [] + projection_trees: + - kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - center + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: center + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - center + - way + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: way + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: false + children: + - kind: OriginProjectionPlaceholder + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-root_origin.snap new file mode 100644 index 0000000000000..50a8535ede563 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-root_origin.snap @@ -0,0 +1,123 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - center + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: center + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - center + - way + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: way + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: false + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-single_proj.snap new file mode 100644 index 0000000000000..71442e1cc5a88 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-single_proj.snap @@ -0,0 +1,94 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: false + origin_tree: + kind: EntityPart + entity_path: + - center + - way + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: way + highlight_sections: [] + default_open: false + children: [] + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: [] + default_open: false + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-unknown_origin.snap new file mode 100644 index 0000000000000..0c48dcf8b8db2 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__no-query-unknown_origin.snap @@ -0,0 +1,34 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: wrong/path + visible: true + default_open: false + origin_tree: + kind: EmptyOriginPlaceholder + entity_path: + - wrong + - path + visible: false + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: false + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-empty.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-multiple_proj.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-multiple_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-non_root_origin.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-non_root_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-proj_with_placeholder.snap new file mode 100644 index 0000000000000..47f2c260bd610 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-proj_with_placeholder.snap @@ -0,0 +1,55 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: + - kind: OriginProjectionPlaceholder + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-root_origin.snap new file mode 100644 index 0000000000000..bfd26e4b5e734 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-root_origin.snap @@ -0,0 +1,104 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: [] + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: [] + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-single_proj.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-single_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-unknown_origin.snap new file mode 100644 index 0000000000000..a51aa4a4aaa1a --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-path-unknown_origin.snap @@ -0,0 +1,36 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: wrong/path + visible: true + default_open: true + origin_tree: + kind: EmptyOriginPlaceholder + entity_path: + - wrong + - path + visible: false + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 0 + end: 4 + default_open: false + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-empty.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-multiple_proj.snap new file mode 100644 index 0000000000000..00df3f243346a --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-multiple_proj.snap @@ -0,0 +1,64 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: + - start: 4 + end: 5 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-non_root_origin.snap new file mode 100644 index 0000000000000..1bf6580755fb1 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-non_root_origin.snap @@ -0,0 +1,91 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: + - start: 3 + end: 4 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: + - start: 4 + end: 5 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-proj_with_placeholder.snap new file mode 100644 index 0000000000000..1881ef1c6d2c1 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-proj_with_placeholder.snap @@ -0,0 +1,148 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: + - start: 3 + end: 4 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: + - start: 4 + end: 5 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: + - kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - center + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: center + highlight_sections: + - start: 3 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - center + - way + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: way + highlight_sections: [] + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - kind: OriginProjectionPlaceholder + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-root_origin.snap new file mode 100644 index 0000000000000..bc93b1e4ac60c --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-root_origin.snap @@ -0,0 +1,135 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - center + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: center + highlight_sections: + - start: 3 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - center + - way + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: way + highlight_sections: [] + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: + - start: 3 + end: 4 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: + - start: 4 + end: 5 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-single_proj.snap new file mode 100644 index 0000000000000..3d415da358696 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-single_proj.snap @@ -0,0 +1,91 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - left + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: left + highlight_sections: + - start: 3 + end: 4 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: + - start: 4 + end: 5 + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-unknown_origin.snap new file mode 100644 index 0000000000000..02f9a114f0d01 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-t-unknown_origin.snap @@ -0,0 +1,36 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: wrong/path + visible: true + default_open: true + origin_tree: + kind: EmptyOriginPlaceholder + entity_path: + - wrong + - path + visible: false + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 2 + end: 3 + default_open: false + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-empty.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-multiple_proj.snap new file mode 100644 index 0000000000000..9bc9f2b0b8713 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-multiple_proj.snap @@ -0,0 +1,50 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-non_root_origin.snap new file mode 100644 index 0000000000000..a592391fcf7cd --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-non_root_origin.snap @@ -0,0 +1,61 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-proj_with_placeholder.snap new file mode 100644 index 0000000000000..a592391fcf7cd --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-proj_with_placeholder.snap @@ -0,0 +1,61 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-root_origin.snap new file mode 100644 index 0000000000000..11a4c73875ba4 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-root_origin.snap @@ -0,0 +1,80 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-single_proj.snap new file mode 100644 index 0000000000000..9be22058589b9 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-single_proj.snap @@ -0,0 +1,61 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-unknown_origin.snap new file mode 100644 index 0000000000000..6007f31692d51 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test__query-void-unknown_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs new file mode 100644 index 0000000000000..8c318f4fb374e --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs @@ -0,0 +1,249 @@ +//! Snapshot testTest suite dedicated to snapshot the way we present various kinds of blueprint tree structures +//! with a focus on various view contents and filter configuration. + +#![cfg(feature = "testing")] + +use egui::Vec2; +use egui_kittest::{SnapshotError, SnapshotOptions}; +use itertools::Itertools; + +use re_blueprint_tree::data::BlueprintTreeData; +use re_blueprint_tree::BlueprintTree; +use re_chunk_store::external::re_chunk::ChunkBuilder; +use re_chunk_store::RowId; +use re_log_types::{build_frame_nr, EntityPath}; +use re_types::archetypes::Points3D; +use re_ui::filter_widget::FilterState; +use re_viewer_context::test_context::TestContext; +use re_viewer_context::{RecommendedView, ViewClass, ViewId}; +use re_viewport_blueprint::test_context_ext::TestContextExt; +use re_viewport_blueprint::{ViewBlueprint, ViewportBlueprint}; + +const VIEW_ID: &str = "this-is-a-view-id"; + +#[derive(Debug, Clone, Copy)] +enum RecordingKind { + /// No entities are logged. + Empty, + + /// Some placeholder entity hierarchy is logged. + Regular, +} + +struct TestCase { + name: &'static str, + + origin: EntityPath, + entity_filter: &'static str, + + recording_kind: RecordingKind, +} + +fn base_test_cases() -> impl Iterator { + [ + TestCase { + name: "empty", + origin: EntityPath::root(), + entity_filter: "$origin/**", + recording_kind: RecordingKind::Empty, + }, + TestCase { + name: "root_origin", + origin: EntityPath::root(), + entity_filter: "$origin/**", + recording_kind: RecordingKind::Regular, + }, + TestCase { + name: "non_root_origin", + origin: EntityPath::from("/path/to"), + entity_filter: "$origin/**", + + recording_kind: RecordingKind::Regular, + }, + TestCase { + name: "unknown_origin", + origin: EntityPath::from("/wrong/path"), + entity_filter: "$origin/**", + recording_kind: RecordingKind::Regular, + }, + TestCase { + name: "single_proj", + origin: EntityPath::from("/center/way"), + entity_filter: "$origin/**\n/path/to/**", + recording_kind: RecordingKind::Regular, + }, + TestCase { + name: "proj_with_placeholder", + origin: EntityPath::from("/path/to"), + entity_filter: "/**", + recording_kind: RecordingKind::Regular, + }, + TestCase { + name: "multiple_proj", + origin: EntityPath::from("/center/way"), + entity_filter: "$origin/**\n/path/to/right\n/path/to/the/**", + recording_kind: RecordingKind::Regular, + }, + ] + .into_iter() +} + +fn filter_queries() -> impl Iterator> { + [None, Some("t"), Some("void"), Some("path")].into_iter() +} + +fn test_context(test_case: &TestCase) -> TestContext { + let mut test_context = TestContext::default(); + + test_context.register_view_class::(); + + match test_case.recording_kind { + RecordingKind::Empty => {} + RecordingKind::Regular => { + test_context.log_entity("/path/to/left".into(), add_point_to_chunk_builder); + test_context.log_entity("/path/to/right".into(), add_point_to_chunk_builder); + test_context.log_entity("/path/to/the/void".into(), add_point_to_chunk_builder); + test_context.log_entity("/center/way".into(), add_point_to_chunk_builder); + } + } + + test_context.setup_viewport_blueprint(|_, blueprint| { + let view = ViewBlueprint::new_with_id( + re_view_spatial::SpatialView3D::identifier(), + RecommendedView { + origin: test_case.origin.clone(), + query_filter: test_case + .entity_filter + .try_into() + .expect("invalid entity filter"), + }, + ViewId::hashed_from_str(VIEW_ID), + ); + + blueprint.add_views(std::iter::once(view), None, None); + }); + + test_context +} + +fn add_point_to_chunk_builder(builder: ChunkBuilder) -> ChunkBuilder { + builder.with_archetype( + RowId::new(), + [build_frame_nr(0)], + &Points3D::new([[0.0, 0.0, 0.0]]), + ) +} + +#[test] +fn test_all_snapshot_test_cases() { + let errors = filter_queries() + .flat_map(|filter_query| { + base_test_cases() + .map(move |test_case| (filter_query, run_test_case(&test_case, filter_query))) + }) + .filter_map(|(filter_query, result)| result.err().map(|err| (filter_query, err))) + .collect_vec(); + + for (filter_query, error) in &errors { + eprintln!("ERR: filter '{filter_query:?}': {error:?}"); + } + + assert!(errors.is_empty(), "Some test cases failed"); +} + +fn run_test_case(test_case: &TestCase, filter_query: Option<&str>) -> Result<(), SnapshotError> { + let mut test_context = test_context(test_case); + let view_id = ViewId::hashed_from_str(VIEW_ID); + + let mut blueprint_tree = BlueprintTree::default(); + + // This trick here is to run the blueprint panel for a frame, such that it registers the current + // application id. This way, the blueprint panel will not discard the filter state we set up + // when it's run for the snapshot. + test_context.run_in_egui_central_panel(|ctx, ui| { + let blueprint = + ViewportBlueprint::try_from_db(ctx.store_context.blueprint, ctx.blueprint_query); + + blueprint_tree.show(ctx, &blueprint, ui); + }); + + if let Some(filter_query) = filter_query { + blueprint_tree.activate_filter(filter_query); + } + + let mut harness = test_context + .setup_kittest_for_rendering() + .with_size(Vec2::new(400.0, 800.0)) + .build_ui(|ui| { + test_context.run(&ui.ctx().clone(), |viewer_ctx| { + re_context_menu::collapse_expand::collapse_expand_view( + viewer_ctx, + &view_id, + blueprint_tree.collapse_scope(), + true, + ); + + let blueprint = ViewportBlueprint::try_from_db( + viewer_ctx.store_context.blueprint, + viewer_ctx.blueprint_query, + ); + + blueprint_tree.show(viewer_ctx, &blueprint, ui); + }); + + test_context.handle_system_commands(); + }); + + harness.run(); + + let options = SnapshotOptions::default().output_path(format!( + "tests/snapshots/view_structure_test/{}", + filter_query + .map(|query| format!("query-{query}")) + .unwrap_or("no-query".to_owned()) + )); + harness.try_snapshot_options(test_case.name, &options) +} + +// --- + +#[test] +fn test_all_insta_test_cases() { + for test_case in base_test_cases() { + for filter_query in filter_queries() { + let test_context = test_context(&test_case); + + let blueprint_tree_data = + test_context.run_once_in_egui_central_panel(|viewer_ctx, _| { + let blueprint = ViewportBlueprint::try_from_db( + viewer_ctx.store_context.blueprint, + viewer_ctx.blueprint_query, + ); + + let mut filter_state = FilterState::default(); + + if let Some(filter_query) = filter_query { + filter_state.activate(filter_query); + } + + BlueprintTreeData::from_blueprint_and_filter( + viewer_ctx, + &blueprint, + &filter_state.filter(), + ) + }); + + let snapshot_name = format!( + "{}-{}", + filter_query + .map(|query| format!("query-{query}")) + .unwrap_or("no-query".to_owned()), + test_case.name + ); + + insta::assert_yaml_snapshot!(snapshot_name, blueprint_tree_data, { + ".root_container.id.id" => "" + }); + } + } +} diff --git a/crates/viewer/re_ui/src/filter_widget.rs b/crates/viewer/re_ui/src/filter_widget.rs index 16b72f1e5d418..a79d20e68d4dd 100644 --- a/crates/viewer/re_ui/src/filter_widget.rs +++ b/crates/viewer/re_ui/src/filter_widget.rs @@ -191,6 +191,11 @@ impl FilterMatcher { } } + /// Is the filter currently active? + pub fn is_active(&self) -> bool { + self.lowercase_query.is_some() + } + /// Is the filter set to match everything? /// /// Can be used by client code to short-circuit more expansive matching logic. @@ -223,7 +228,7 @@ impl FilterMatcher { /// Returns `None` when there is no match. /// Returns `Some` when the filter is inactive (and thus matches everything), or if there is an /// actual match. - fn find_matches(&self, text: &str) -> Option> + '_> { + pub fn find_matches(&self, text: &str) -> Option> + '_> { let query = match self.lowercase_query.as_deref() { None => { return Some(Either::Left(std::iter::empty())); @@ -257,7 +262,7 @@ impl FilterMatcher { /// actual match. pub fn matches_formatted(&self, ctx: &egui::Context, text: &str) -> Option { self.find_matches(text) - .map(|match_iter| format_matching_text(ctx, text, match_iter)) + .map(|match_iter| format_matching_text(ctx, text, match_iter, None)) } } @@ -267,10 +272,13 @@ pub fn format_matching_text( ctx: &egui::Context, text: &str, match_iter: impl Iterator>, + text_color: Option, ) -> egui::WidgetText { let mut current = 0; let mut job = egui::text::LayoutJob::default(); + let color = text_color.unwrap_or(Color32::PLACEHOLDER); + for Range { start, end } in match_iter { if current < start { job.append( @@ -278,7 +286,7 @@ pub fn format_matching_text( 0.0, egui::TextFormat { font_id: egui::TextStyle::Body.resolve(&ctx.style()), - color: Color32::PLACEHOLDER, + color, ..Default::default() }, ); @@ -289,7 +297,7 @@ pub fn format_matching_text( 0.0, egui::TextFormat { font_id: egui::TextStyle::Body.resolve(&ctx.style()), - color: Color32::PLACEHOLDER, + color, background: ctx.style().visuals.selection.bg_fill, ..Default::default() }, @@ -304,7 +312,7 @@ pub fn format_matching_text( 0.0, egui::TextFormat { font_id: egui::TextStyle::Body.resolve(&ctx.style()), - color: Color32::PLACEHOLDER, + color, ..Default::default() }, ); diff --git a/crates/viewer/re_viewer_context/src/contents.rs b/crates/viewer/re_viewer_context/src/contents.rs index 558fbe8ad941b..2290c5c44bd40 100644 --- a/crates/viewer/re_viewer_context/src/contents.rs +++ b/crates/viewer/re_viewer_context/src/contents.rs @@ -101,6 +101,7 @@ impl From for Contents { /// The name of a [`Contents`]. #[derive(Clone, Debug)] +#[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] pub enum ContentsName { /// This [`Contents`] has been given a name by the user. Named(String), diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 21e1ac379b1d2..d00d5ef41efff 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -305,8 +305,9 @@ impl TestContext { /// Notes: /// - Uses [`egui::__run_test_ctx`]. /// - There is a possibility that the closure will be called more than once, see - /// [`egui::Context::run`]. - //TODO(ab): replace this with a kittest-based helper. + /// [`egui::Context::run`]. Use [`Self::run_once_in_egui_central_panel`] if you want to ensure + /// that the closure is called exactly once. + //TODO(ab): should this be removed entirely in favor of `run_once_in_egui_central_panel`? pub fn run_in_egui_central_panel( &self, mut func: impl FnMut(&ViewerContext<'_>, &mut egui::Ui), @@ -322,6 +323,36 @@ impl TestContext { }); } + /// Run the given function once with a [`ViewerContext`] produced by the [`Self`], in the + /// context of an [`egui::CentralPanel`]. + /// + /// IMPORTANT: call [`Self::handle_system_commands`] after calling this function if your test + /// relies on system commands. + /// + /// Notes: + /// - Uses [`egui::__run_test_ctx`]. + pub fn run_once_in_egui_central_panel( + &self, + func: impl FnOnce(&ViewerContext<'_>, &mut egui::Ui) -> R, + ) -> R { + let mut func = Some(func); + let mut result = None; + + egui::__run_test_ctx(|ctx| { + egui::CentralPanel::default().show(ctx, |ui| { + let egui_ctx = ui.ctx().clone(); + + self.run(&egui_ctx, |ctx| { + if let Some(func) = func.take() { + result = Some(func(ctx, ui)); + } + }); + }); + }); + + result.expect("Function should have been called at least once") + } + /// Best-effort attempt to meaningfully handle some of the system commands. pub fn handle_system_commands(&mut self) { while let Some(command) = self.command_receiver.recv_system() { @@ -379,10 +410,9 @@ impl TestContext { SystemCommand::FileSaver(_) => handled = false, } - eprintln!( - "{} system command: {command_name:?}", - if handled { "Handled" } else { "Ignored" } - ); + if !handled { + eprintln!("Ignored system command: {command_name:?}",); + } } } } diff --git a/crates/viewer/re_viewport_blueprint/src/view.rs b/crates/viewer/re_viewport_blueprint/src/view.rs index 5b65507fd3be3..84e14ca6c4a4f 100644 --- a/crates/viewer/re_viewport_blueprint/src/view.rs +++ b/crates/viewer/re_viewport_blueprint/src/view.rs @@ -66,11 +66,24 @@ impl ViewBlueprint { /// Creates a new [`ViewBlueprint`] with a single [`ViewContents`]. /// - /// This [`ViewBlueprint`] is ephemeral. If you want to make it permanent you + /// This [`ViewBlueprint`] is ephemeral. If you want to make it permanent, you /// must call [`Self::save_to_blueprint_store`]. pub fn new(view_class: ViewClassIdentifier, recommended: RecommendedView) -> Self { - let id = ViewId::random(); + Self::new_with_id(view_class, recommended, ViewId::random()) + } + /// Creates a new [`ViewBlueprint`] with a single [`ViewContents`], using the provided id. + /// + /// Useful for testing contexts where random ids are not desired. Avoid using in production + /// code. + /// + /// This [`ViewBlueprint`] is ephemeral. If you want to make it permanent, you + /// must call [`Self::save_to_blueprint_store`]. + pub fn new_with_id( + view_class: ViewClassIdentifier, + recommended: RecommendedView, + id: ViewId, + ) -> Self { let path_subs = EntityPathSubs::new_with_origin(&recommended.origin); let query_filter = recommended.query_filter.resolve_forgiving(&path_subs); From a54c80d3aecf2b5513c388ce40e742490789e375 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:37:24 +0100 Subject: [PATCH 15/43] Improve performance for Blueprint & Streams Panel for many entities (#8808) --- .../re_blueprint_tree/src/blueprint_tree.rs | 16 +++++++--- crates/viewer/re_time_panel/src/lib.rs | 29 +++++++++++-------- .../viewer/re_ui/src/list_item/list_item.rs | 23 +++++++++++++++ 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs index 38b921c25c20d..36bc26934d3af 100644 --- a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs +++ b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs @@ -174,6 +174,7 @@ impl BlueprintTree { let item_response = ui .list_item() + .render_offscreen(false) .selected(ctx.selection().contains_item(&item)) .draggable(true) // allowed for consistency but results in an invalid drag .drop_target_style(self.is_candidate_drop_parent_container(&container_data.id)) @@ -272,6 +273,7 @@ impl BlueprintTree { .. } = ui .list_item() + .render_offscreen(false) .selected(ctx.selection().contains_item(&item)) .draggable(true) .drop_target_style(self.is_candidate_drop_parent_container(&container_data.id)) @@ -360,6 +362,7 @@ impl BlueprintTree { .. } = ui .list_item() + .render_offscreen(false) .selected(ctx.selection().contains_item(&item)) .draggable(true) .force_hovered(is_item_hovered) @@ -375,10 +378,13 @@ impl BlueprintTree { } if !view_data.projection_trees.is_empty() { - ui.list_item().interactive(false).show_flat( - ui, - list_item::LabelContent::new("Projections:").italics(true), - ); + ui.list_item() + .render_offscreen(false) + .interactive(false) + .show_flat( + ui, + list_item::LabelContent::new("Projections:").italics(true), + ); for projection in &view_data.projection_trees { self.data_result_ui(ctx, viewport_blueprint, ui, projection, view_visible); @@ -481,6 +487,7 @@ impl BlueprintTree { DataResultKind::OriginProjectionPlaceholder => { if ui .list_item() + .render_offscreen(false) .show_hierarchical( ui, list_item::LabelContent::new("$origin") @@ -507,6 +514,7 @@ impl BlueprintTree { let list_item = ui .list_item() + .render_offscreen(false) .draggable(true) .selected(is_selected) .force_hovered(is_item_hovered); diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 6dacd912ea0e0..69a110f676ad6 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -760,6 +760,7 @@ impl TimePanel { .. } = ui .list_item() + .render_offscreen(false) .selected(is_selected) .draggable(true) .force_hovered(is_item_hovered) @@ -925,6 +926,7 @@ impl TimePanel { let response = ui .list_item() + .render_offscreen(false) .selected(ctx.selection().contains_item(&item.to_item())) .force_hovered( ctx.selection_state() @@ -975,18 +977,21 @@ impl TimePanel { format!("{} times", re_format::format_uint(num_messages)) }; - ui.list_item().interactive(false).show_flat( - ui, - list_item::LabelContent::new(format!( - "{kind} component, logged {num_messages}" - )) - .truncate(false) - .with_icon(if is_static { - &re_ui::icons::COMPONENT_STATIC - } else { - &re_ui::icons::COMPONENT_TEMPORAL - }), - ); + ui.list_item() + .interactive(false) + .render_offscreen(false) + .show_flat( + ui, + list_item::LabelContent::new(format!( + "{kind} component, logged {num_messages}" + )) + .truncate(false) + .with_icon(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT_TEMPORAL + }), + ); // Static components are not displayed at all on the timeline, so cannot be // previewed there. So we display their content in this tooltip instead. diff --git a/crates/viewer/re_ui/src/list_item/list_item.rs b/crates/viewer/re_ui/src/list_item/list_item.rs index c4904cddee447..051c7c33cbe25 100644 --- a/crates/viewer/re_ui/src/list_item/list_item.rs +++ b/crates/viewer/re_ui/src/list_item/list_item.rs @@ -49,6 +49,7 @@ pub struct ListItem { force_background: Option, pub collapse_openness: Option, height: f32, + render_offscreen: bool, } impl Default for ListItem { @@ -62,6 +63,7 @@ impl Default for ListItem { force_background: None, collapse_openness: None, height: DesignTokens::list_item_height(), + render_offscreen: true, } } } @@ -140,6 +142,18 @@ impl ListItem { self } + /// Controls whether [`Self`] calls [`ListItemContent::ui`] when the item is not currently + /// visible. + /// + /// Skipping rendering can increase performances for long lists that are mostly out of view, but + /// this will prevent any side effects from [`ListItemContent::ui`] from occurring. For this + /// reason, this is an opt-in optimization. + #[inline] + pub fn render_offscreen(mut self, render_offscreen: bool) -> Self { + self.render_offscreen = render_offscreen; + self + } + /// Draw the item as part of a flat list. /// /// *Important*: must be called while nested in a [`super::list_item_scope`]. @@ -274,6 +288,7 @@ impl ListItem { force_background, collapse_openness, height, + render_offscreen, } = self; let collapse_extra = if collapse_openness.is_some() { @@ -329,6 +344,14 @@ impl ListItem { // allocate past the available width. response.rect = rect; + let should_render = render_offscreen || ui.is_rect_visible(rect); + if !should_render { + return ListItemResponse { + response, + collapse_response: None, + }; + } + // override_hover should not affect the returned response let mut style_response = response.clone(); if force_hovered { From d9fefc3c1124d72f14715b1950570c21d6056f4f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 28 Jan 2025 10:45:36 +0100 Subject: [PATCH 16/43] Add `with_many_` variants for C++ archetype mono fields & port remaining snippets (#8836) --- .../re_types_builder/src/codegen/cpp/mod.rs | 33 +++ .../reference/migration/migration-0-22.md | 16 ++ .../all/archetypes/image_send_columns.cpp | 2 +- .../all/archetypes/points3d_send_columns.cpp | 8 +- .../all/archetypes/scalar_send_columns.cpp | 12 +- .../all/archetypes/video_auto_frames.cpp | 5 +- docs/snippets/snippets.toml | 3 - .../rerun/archetypes/annotation_context.hpp | 11 + rerun_cpp/src/rerun/archetypes/arrows2d.hpp | 22 ++ rerun_cpp/src/rerun/archetypes/arrows3d.hpp | 11 + rerun_cpp/src/rerun/archetypes/asset3d.hpp | 32 +++ .../src/rerun/archetypes/asset_video.hpp | 25 +- rerun_cpp/src/rerun/archetypes/bar_chart.hpp | 18 ++ rerun_cpp/src/rerun/archetypes/boxes2d.hpp | 22 ++ rerun_cpp/src/rerun/archetypes/boxes3d.hpp | 21 ++ rerun_cpp/src/rerun/archetypes/capsules3d.hpp | 12 + rerun_cpp/src/rerun/archetypes/clear.hpp | 12 + .../src/rerun/archetypes/depth_image.hpp | 73 +++++ .../src/rerun/archetypes/ellipsoids3d.hpp | 23 ++ .../src/rerun/archetypes/encoded_image.hpp | 42 +++ .../src/rerun/archetypes/graph_edges.hpp | 11 + .../src/rerun/archetypes/graph_nodes.hpp | 12 + rerun_cpp/src/rerun/archetypes/image.hpp | 37 +++ .../src/rerun/archetypes/line_strips2d.hpp | 24 ++ .../src/rerun/archetypes/line_strips3d.hpp | 12 + rerun_cpp/src/rerun/archetypes/mesh3d.hpp | 42 +++ rerun_cpp/src/rerun/archetypes/pinhole.hpp | 51 ++++ rerun_cpp/src/rerun/archetypes/points2d.hpp | 22 ++ rerun_cpp/src/rerun/archetypes/points3d.hpp | 19 +- rerun_cpp/src/rerun/archetypes/scalar.hpp | 21 +- .../rerun/archetypes/segmentation_image.hpp | 42 +++ .../src/rerun/archetypes/series_line.hpp | 40 +++ .../src/rerun/archetypes/series_point.hpp | 39 +++ rerun_cpp/src/rerun/archetypes/tensor.hpp | 20 ++ .../src/rerun/archetypes/text_document.hpp | 21 ++ rerun_cpp/src/rerun/archetypes/text_log.hpp | 27 ++ .../src/rerun/archetypes/transform3d.hpp | 80 ++++++ .../archetypes/video_frame_reference.hpp | 30 ++- .../src/rerun/archetypes/view_coordinates.hpp | 10 + rerun_cpp/src/rerun/recording_stream.hpp | 92 ++----- .../generated/archetypes/affix_fuzzer1.hpp | 255 ++++++++++++++++++ .../generated/archetypes/affix_fuzzer3.hpp | 207 ++++++++++++++ tests/cpp/plot_dashboard_stress/main.cpp | 10 +- 43 files changed, 1408 insertions(+), 119 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/cpp/mod.rs b/crates/build/re_types_builder/src/codegen/cpp/mod.rs index ccb03882eb77e..bcbac763b69bb 100644 --- a/crates/build/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/build/re_types_builder/src/codegen/cpp/mod.rs @@ -603,6 +603,35 @@ impl QuotedObject { }, inline: true, }); + + // Add a `with_many_` variant if this is a mono field. + // Make an exception for blueprint types since it practically never makes sense there. + if !obj_field.typ.is_plural() && !is_blueprint_type(obj) { + let method_ident_many = format_ident!("with_many_{}", obj_field.name); + let docstring_many = unindent::unindent(&format!("\ + This method makes it possible to pack multiple `{}` in a single component batch. + + This only makes sense when used in conjunction with `columns`. `{method_ident}` should + be used when logging a single row's worth of data. + ", obj_field.name)); + + methods.push(Method { + docs: docstring_many.into(), + declaration: MethodDeclaration { + is_static: false, + return_type: quote!(#archetype_type_ident), + name_and_parameters: quote! { + #method_ident_many(const Collection<#field_type>& #parameter_ident) && + }, + }, + definition_body: quote! { + #field_ident = ComponentBatch::from_loggable(#parameter_ident, #descriptor).value_or_throw(); + #NEWLINE_TOKEN + return std::move(*this); + }, + inline: true, + }); + } } // columns method that allows partitioning into columns @@ -2799,3 +2828,7 @@ fn quote_deprecation_ignore_start_and_end( fn archetype_component_descriptor_constant_ident(obj_field: &ObjectField) -> Ident { format_ident!("Descriptor_{}", obj_field.name) } + +fn is_blueprint_type(obj: &Object) -> bool { + obj.pkg_name.contains("blueprint") +} diff --git a/docs/content/reference/migration/migration-0-22.md b/docs/content/reference/migration/migration-0-22.md index d3987f28773af..093f5d730c8bb 100644 --- a/docs/content/reference/migration/migration-0-22.md +++ b/docs/content/reference/migration/migration-0-22.md @@ -38,3 +38,19 @@ Instead, there's now methods with the same name, i.e. `ViewCoordinates::RUB()`. As part of the switch to "eager archetype serialization" (serialization of archetype components now occurs at time of archetype instantiation rather than logging), we can no longer offer exposing the `Tensor` **archetype** as `ndarray::ArrayView` directly. However, it is still possible to do so with the `TensorData` component. + +### C++ `RecordingStream::send_column` no longer takes raw component collections + +Previously, `RecordingStream::send_column` accepted raw component collections. + +This is no longer the case and only `rerun::ComponentColumn` and anything else from which +a `Collection` can be constructed is accepted. +The preferred way to create `rerun::ComponentColumn`s is to use the new `columns` method on archetypes. + +For instance in order to send a column of scalars, you can now do this. +```cpp +rec.send_columns("scalars", time_column, + rerun::Scalar().with_many_scalar(scalar_data).columns() +); +``` +All [example snippets](https://github.com/rerun-io/rerun/blob/0.22.0/docs/snippets/INDEX.md?speculative-link) have been updated accordingly. diff --git a/docs/snippets/all/archetypes/image_send_columns.cpp b/docs/snippets/all/archetypes/image_send_columns.cpp index 9482a3030a8ca..f179bdfefc9b5 100644 --- a/docs/snippets/all/archetypes/image_send_columns.cpp +++ b/docs/snippets/all/archetypes/image_send_columns.cpp @@ -45,6 +45,6 @@ int main() { rec.send_columns( "images", rerun::TimeColumn::from_sequence_points("step", std::move(times)), - rerun::borrow(image_data) + rerun::Image().with_many_buffer(std::move(image_data)).columns() ); } diff --git a/docs/snippets/all/archetypes/points3d_send_columns.cpp b/docs/snippets/all/archetypes/points3d_send_columns.cpp index bf5e73ca5d248..15c3a99c6b71f 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.cpp +++ b/docs/snippets/all/archetypes/points3d_send_columns.cpp @@ -30,10 +30,8 @@ int main() { auto time_column = rerun::TimeColumn::from_times("time", std::move(times)); // Partition our data as expected across the 5 timesteps. - auto position = - rerun::Points3D::update_fields().with_positions(positions).columns({2, 4, 4, 3, 4}); - auto color_and_radius = - rerun::Points3D::update_fields().with_colors(colors).with_radii(radii).columns(); + auto position = rerun::Points3D().with_positions(positions).columns({2, 4, 4, 3, 4}); + auto color_and_radius = rerun::Points3D().with_colors(colors).with_radii(radii).columns(); - rec.send_columns2("points", time_column, position, color_and_radius); + rec.send_columns("points", time_column, position, color_and_radius); } diff --git a/docs/snippets/all/archetypes/scalar_send_columns.cpp b/docs/snippets/all/archetypes/scalar_send_columns.cpp index a9081c1a351ff..1a748591f037d 100644 --- a/docs/snippets/all/archetypes/scalar_send_columns.cpp +++ b/docs/snippets/all/archetypes/scalar_send_columns.cpp @@ -18,10 +18,10 @@ int main() { std::vector times(64); std::iota(times.begin(), times.end(), 0); - // Convert to rerun time / scalars - auto time_column = rerun::TimeColumn::from_sequence_points("step", std::move(times)); - auto scalar_data_collection = - rerun::Collection(std::move(scalar_data)); - - rec.send_columns("scalars", time_column, scalar_data_collection); + // Serialize to columns and send. + rec.send_columns( + "scalars", + rerun::TimeColumn::from_sequence_points("step", std::move(times)), + rerun::Scalar().with_many_scalar(std::move(scalar_data)).columns() + ); } diff --git a/docs/snippets/all/archetypes/video_auto_frames.cpp b/docs/snippets/all/archetypes/video_auto_frames.cpp index 26f5a694af87e..aa2dd6a11d5c6 100644 --- a/docs/snippets/all/archetypes/video_auto_frames.cpp +++ b/docs/snippets/all/archetypes/video_auto_frames.cpp @@ -42,9 +42,6 @@ int main(int argc, char* argv[]) { rec.send_columns( "video", time_column, - { - video_frame_reference_indicators.value_or_throw(), - rerun::ComponentColumn::from_loggable(rerun::borrow(video_timestamps)).value_or_throw(), - } + rerun::VideoFrameReference().with_many_timestamp(rerun::borrow(video_timestamps)).columns() ); } diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index e438c4a099dd1..d50f28be5316c 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -244,9 +244,6 @@ quick_start = [ # These examples don't have exactly the same implementation. "archetypes/scalar_multiple_plots" = [ # trigonometric functions have slightly different outcomes "cpp", ] -"archetypes/scalar_send_columns" = [ - "cpp", # TODO(#8754): needs tagged columnar APIs -] "archetypes/tensor_simple" = [ # TODO(#3206): examples use different RNGs "cpp", "py", diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp index 1575cdb75ec2a..8a5cebd4072bf 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp @@ -108,6 +108,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `context` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_context` should + /// be used when logging a single row's worth of data. + AnnotationContext with_many_context( + const Collection& _context + ) && { + context = ComponentBatch::from_loggable(_context, Descriptor_context).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp index b4b24f0dac80b..eea32eea35fbd 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp @@ -198,6 +198,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Arrows2D with_many_show_labels(const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. @@ -207,6 +218,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + Arrows2D with_many_draw_order(const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp index a3d8246bb6dac..6f6b888c12773 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp @@ -204,6 +204,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Arrows3D with_many_show_labels(const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.hpp b/rerun_cpp/src/rerun/archetypes/asset3d.hpp index d8cde2391e27f..a95cd32e277d6 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.hpp @@ -148,6 +148,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `blob` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_blob` should + /// be used when logging a single row's worth of data. + Asset3D with_many_blob(const Collection& _blob) && { + blob = ComponentBatch::from_loggable(_blob, Descriptor_blob).value_or_throw(); + return std::move(*this); + } + /// The Media Type of the asset. /// /// Supported values: @@ -164,6 +173,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `media_type` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_media_type` should + /// be used when logging a single row's worth of data. + Asset3D with_many_media_type(const Collection& _media_type + ) && { + media_type = + ComponentBatch::from_loggable(_media_type, Descriptor_media_type).value_or_throw(); + return std::move(*this); + } + /// A color multiplier applied to the whole asset. /// /// For mesh who already have `albedo_factor` in materials, @@ -174,6 +194,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `albedo_factor` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_albedo_factor` should + /// be used when logging a single row's worth of data. + Asset3D with_many_albedo_factor( + const Collection& _albedo_factor + ) && { + albedo_factor = ComponentBatch::from_loggable(_albedo_factor, Descriptor_albedo_factor) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.hpp b/rerun_cpp/src/rerun/archetypes/asset_video.hpp index bd62127702d36..6f514ecca4792 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.hpp @@ -75,10 +75,7 @@ namespace rerun::archetypes { /// rec.send_columns( /// "video", /// time_column, - /// { - /// video_frame_reference_indicators.value_or_throw(), - /// rerun::ComponentColumn::from_loggable(rerun::borrow(video_timestamps)).value_or_throw(), - /// } + /// rerun::VideoFrameReference().with_many_timestamp(rerun::borrow(video_timestamps)).columns() /// ); /// } /// ``` @@ -204,6 +201,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `blob` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_blob` should + /// be used when logging a single row's worth of data. + AssetVideo with_many_blob(const Collection& _blob) && { + blob = ComponentBatch::from_loggable(_blob, Descriptor_blob).value_or_throw(); + return std::move(*this); + } + /// The Media Type of the asset. /// /// Supported values: @@ -217,6 +223,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `media_type` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_media_type` should + /// be used when logging a single row's worth of data. + AssetVideo with_many_media_type(const Collection& _media_type + ) && { + media_type = + ComponentBatch::from_loggable(_media_type, Descriptor_media_type).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp index 50eb559decc0c..9f9ee53c8b898 100644 --- a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp +++ b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp @@ -204,12 +204,30 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `values` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_values` should + /// be used when logging a single row's worth of data. + BarChart with_many_values(const Collection& _values) && { + values = ComponentBatch::from_loggable(_values, Descriptor_values).value_or_throw(); + return std::move(*this); + } + /// The color of the bar chart BarChart with_color(const rerun::components::Color& _color) && { color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `color` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_color` should + /// be used when logging a single row's worth of data. + BarChart with_many_color(const Collection& _color) && { + color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp index c2e48b460cfed..3195f647eb269 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp @@ -220,6 +220,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Boxes2D with_many_show_labels(const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. @@ -231,6 +242,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + Boxes2D with_many_draw_order(const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Optional `components::ClassId`s for the boxes. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp index 1d9ceca3f7b21..9ad37f142f590 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp @@ -290,6 +290,16 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `fill_mode` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fill_mode` should + /// be used when logging a single row's worth of data. + Boxes3D with_many_fill_mode(const Collection& _fill_mode) && { + fill_mode = + ComponentBatch::from_loggable(_fill_mode, Descriptor_fill_mode).value_or_throw(); + return std::move(*this); + } + /// Optional text labels for the boxes. /// /// If there's a single label present, it will be placed at the center of the entity. @@ -306,6 +316,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Boxes3D with_many_show_labels(const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional `components::ClassId`s for the boxes. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/capsules3d.hpp b/rerun_cpp/src/rerun/archetypes/capsules3d.hpp index 3f9162203542f..ea393defd6f8f 100644 --- a/rerun_cpp/src/rerun/archetypes/capsules3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/capsules3d.hpp @@ -278,6 +278,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Capsules3D with_many_show_labels( + const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional class ID for the ellipsoids. /// /// The class ID provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/clear.hpp b/rerun_cpp/src/rerun/archetypes/clear.hpp index 613e3f5f64d3d..ccf9cae4186b9 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.hpp +++ b/rerun_cpp/src/rerun/archetypes/clear.hpp @@ -135,6 +135,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `is_recursive` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_is_recursive` should + /// be used when logging a single row's worth of data. + Clear with_many_is_recursive( + const Collection& _is_recursive + ) && { + is_recursive = ComponentBatch::from_loggable(_is_recursive, Descriptor_is_recursive) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/depth_image.hpp b/rerun_cpp/src/rerun/archetypes/depth_image.hpp index f1505405d8c46..b42cbdf00d1d9 100644 --- a/rerun_cpp/src/rerun/archetypes/depth_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/depth_image.hpp @@ -249,12 +249,30 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `buffer` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_buffer` should + /// be used when logging a single row's worth of data. + DepthImage with_many_buffer(const Collection& _buffer) && { + buffer = ComponentBatch::from_loggable(_buffer, Descriptor_buffer).value_or_throw(); + return std::move(*this); + } + /// The format of the image. DepthImage with_format(const rerun::components::ImageFormat& _format) && { format = ComponentBatch::from_loggable(_format, Descriptor_format).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `format` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_format` should + /// be used when logging a single row's worth of data. + DepthImage with_many_format(const Collection& _format) && { + format = ComponentBatch::from_loggable(_format, Descriptor_format).value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies how long a meter is in the native depth units. /// /// For instance: with uint16, perhaps meter=1000 which would mean you have millimeter precision @@ -267,6 +285,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `meter` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_meter` should + /// be used when logging a single row's worth of data. + DepthImage with_many_meter(const Collection& _meter) && { + meter = ComponentBatch::from_loggable(_meter, Descriptor_meter).value_or_throw(); + return std::move(*this); + } + /// Colormap to use for rendering the depth image. /// /// If not set, the depth image will be rendered using the Turbo colormap. @@ -276,6 +303,16 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `colormap` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_colormap` should + /// be used when logging a single row's worth of data. + DepthImage with_many_colormap(const Collection& _colormap) && { + colormap = + ComponentBatch::from_loggable(_colormap, Descriptor_colormap).value_or_throw(); + return std::move(*this); + } + /// The expected range of depth values. /// /// This is typically the expected range of valid values. @@ -293,6 +330,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `depth_range` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_depth_range` should + /// be used when logging a single row's worth of data. + DepthImage with_many_depth_range( + const Collection& _depth_range + ) && { + depth_range = ComponentBatch::from_loggable(_depth_range, Descriptor_depth_range) + .value_or_throw(); + return std::move(*this); + } + /// Scale the radii of the points in the point cloud generated from this image. /// /// A fill ratio of 1.0 (the default) means that each point is as big as to touch the center of its neighbor @@ -307,6 +356,19 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `point_fill_ratio` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_point_fill_ratio` should + /// be used when logging a single row's worth of data. + DepthImage with_many_point_fill_ratio( + const Collection& _point_fill_ratio + ) && { + point_fill_ratio = + ComponentBatch::from_loggable(_point_fill_ratio, Descriptor_point_fill_ratio) + .value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order, used only if the depth image is shown as a 2D image. /// /// Objects with higher values are drawn on top of those with lower values. @@ -316,6 +378,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + DepthImage with_many_draw_order(const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp index ba61754a59e57..da2f9975bb4c6 100644 --- a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp @@ -304,6 +304,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `fill_mode` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fill_mode` should + /// be used when logging a single row's worth of data. + Ellipsoids3D with_many_fill_mode(const Collection& _fill_mode + ) && { + fill_mode = + ComponentBatch::from_loggable(_fill_mode, Descriptor_fill_mode).value_or_throw(); + return std::move(*this); + } + /// Optional text labels for the ellipsoids. Ellipsoids3D with_labels(const Collection& _labels) && { labels = ComponentBatch::from_loggable(_labels, Descriptor_labels).value_or_throw(); @@ -317,6 +328,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Ellipsoids3D with_many_show_labels( + const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional class ID for the ellipsoids. /// /// The class ID provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/encoded_image.hpp b/rerun_cpp/src/rerun/archetypes/encoded_image.hpp index d9a551a2a47d0..8cd541bfd0e6b 100644 --- a/rerun_cpp/src/rerun/archetypes/encoded_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/encoded_image.hpp @@ -142,6 +142,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `blob` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_blob` should + /// be used when logging a single row's worth of data. + EncodedImage with_many_blob(const Collection& _blob) && { + blob = ComponentBatch::from_loggable(_blob, Descriptor_blob).value_or_throw(); + return std::move(*this); + } + /// The Media Type of the asset. /// /// Supported values: @@ -156,6 +165,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `media_type` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_media_type` should + /// be used when logging a single row's worth of data. + EncodedImage with_many_media_type( + const Collection& _media_type + ) && { + media_type = + ComponentBatch::from_loggable(_media_type, Descriptor_media_type).value_or_throw(); + return std::move(*this); + } + /// Opacity of the image, useful for layering several images. /// /// Defaults to 1.0 (fully opaque). @@ -164,6 +185,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `opacity` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_opacity` should + /// be used when logging a single row's worth of data. + EncodedImage with_many_opacity(const Collection& _opacity) && { + opacity = ComponentBatch::from_loggable(_opacity, Descriptor_opacity).value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. @@ -173,6 +203,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + EncodedImage with_many_draw_order( + const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp index c0fe9bab70a58..054c65fdc5c9f 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp @@ -107,6 +107,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `graph_type` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_graph_type` should + /// be used when logging a single row's worth of data. + GraphEdges with_many_graph_type(const Collection& _graph_type + ) && { + graph_type = + ComponentBatch::from_loggable(_graph_type, Descriptor_graph_type).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp index 0fefb168ca1b1..3c0ca2644e679 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp @@ -154,6 +154,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + GraphNodes with_many_show_labels( + const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional radii for nodes. GraphNodes with_radii(const Collection& _radii) && { radii = ComponentBatch::from_loggable(_radii, Descriptor_radii).value_or_throw(); diff --git a/rerun_cpp/src/rerun/archetypes/image.hpp b/rerun_cpp/src/rerun/archetypes/image.hpp index 3706095bc0b5c..6c2a3df74cf03 100644 --- a/rerun_cpp/src/rerun/archetypes/image.hpp +++ b/rerun_cpp/src/rerun/archetypes/image.hpp @@ -339,12 +339,30 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `buffer` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_buffer` should + /// be used when logging a single row's worth of data. + Image with_many_buffer(const Collection& _buffer) && { + buffer = ComponentBatch::from_loggable(_buffer, Descriptor_buffer).value_or_throw(); + return std::move(*this); + } + /// The format of the image. Image with_format(const rerun::components::ImageFormat& _format) && { format = ComponentBatch::from_loggable(_format, Descriptor_format).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `format` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_format` should + /// be used when logging a single row's worth of data. + Image with_many_format(const Collection& _format) && { + format = ComponentBatch::from_loggable(_format, Descriptor_format).value_or_throw(); + return std::move(*this); + } + /// Opacity of the image, useful for layering several images. /// /// Defaults to 1.0 (fully opaque). @@ -353,6 +371,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `opacity` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_opacity` should + /// be used when logging a single row's worth of data. + Image with_many_opacity(const Collection& _opacity) && { + opacity = ComponentBatch::from_loggable(_opacity, Descriptor_opacity).value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. @@ -362,6 +389,16 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + Image with_many_draw_order(const Collection& _draw_order) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp index 4a0a7691dda96..bbe2e7bacfae2 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp @@ -210,6 +210,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + LineStrips2D with_many_show_labels( + const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order of each line strip. /// /// Objects with higher values are drawn on top of those with lower values. @@ -219,6 +231,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + LineStrips2D with_many_draw_order( + const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Optional `components::ClassId`s for the lines. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp index dfd3c9f5f29ce..175f1dbced38d 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp @@ -214,6 +214,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + LineStrips3D with_many_show_labels( + const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional `components::ClassId`s for the lines. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp index 5ee8cf58714a2..30672bcacfea7 100644 --- a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp @@ -274,6 +274,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `albedo_factor` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_albedo_factor` should + /// be used when logging a single row's worth of data. + Mesh3D with_many_albedo_factor( + const Collection& _albedo_factor + ) && { + albedo_factor = ComponentBatch::from_loggable(_albedo_factor, Descriptor_albedo_factor) + .value_or_throw(); + return std::move(*this); + } + /// Optional albedo texture. /// /// Used with the `components::Texcoord2D` of the mesh. @@ -291,6 +303,21 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `albedo_texture_buffer` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_albedo_texture_buffer` should + /// be used when logging a single row's worth of data. + Mesh3D with_many_albedo_texture_buffer( + const Collection& _albedo_texture_buffer + ) && { + albedo_texture_buffer = ComponentBatch::from_loggable( + _albedo_texture_buffer, + Descriptor_albedo_texture_buffer + ) + .value_or_throw(); + return std::move(*this); + } + /// The format of the `albedo_texture_buffer`, if any. Mesh3D with_albedo_texture_format( const rerun::components::ImageFormat& _albedo_texture_format @@ -303,6 +330,21 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `albedo_texture_format` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_albedo_texture_format` should + /// be used when logging a single row's worth of data. + Mesh3D with_many_albedo_texture_format( + const Collection& _albedo_texture_format + ) && { + albedo_texture_format = ComponentBatch::from_loggable( + _albedo_texture_format, + Descriptor_albedo_texture_format + ) + .value_or_throw(); + return std::move(*this); + } + /// Optional class Ids for the vertices. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.hpp b/rerun_cpp/src/rerun/archetypes/pinhole.hpp index f7468a6ab4ba0..17ca8a060f940 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.hpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.hpp @@ -237,6 +237,19 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `image_from_camera` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_image_from_camera` should + /// be used when logging a single row's worth of data. + Pinhole with_many_image_from_camera( + const Collection& _image_from_camera + ) && { + image_from_camera = + ComponentBatch::from_loggable(_image_from_camera, Descriptor_image_from_camera) + .value_or_throw(); + return std::move(*this); + } + /// Pixel resolution (usually integers) of child image space. Width and height. /// /// Example: @@ -251,6 +264,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `resolution` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_resolution` should + /// be used when logging a single row's worth of data. + Pinhole with_many_resolution(const Collection& _resolution + ) && { + resolution = + ComponentBatch::from_loggable(_resolution, Descriptor_resolution).value_or_throw(); + return std::move(*this); + } + /// Sets the view coordinates for the camera. /// /// All common values are available as constants on the `components::ViewCoordinates` class. @@ -284,6 +308,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `camera_xyz` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_camera_xyz` should + /// be used when logging a single row's worth of data. + Pinhole with_many_camera_xyz( + const Collection& _camera_xyz + ) && { + camera_xyz = + ComponentBatch::from_loggable(_camera_xyz, Descriptor_camera_xyz).value_or_throw(); + return std::move(*this); + } + /// The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. /// /// This is only used for visualization purposes, and does not affect the projection itself. @@ -298,6 +334,21 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `image_plane_distance` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_image_plane_distance` should + /// be used when logging a single row's worth of data. + Pinhole with_many_image_plane_distance( + const Collection& _image_plane_distance + ) && { + image_plane_distance = ComponentBatch::from_loggable( + _image_plane_distance, + Descriptor_image_plane_distance + ) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/points2d.hpp b/rerun_cpp/src/rerun/archetypes/points2d.hpp index 695c7955c8dec..e60cbba3a1726 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.hpp @@ -243,6 +243,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Points2D with_many_show_labels(const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. @@ -252,6 +263,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + Points2D with_many_draw_order(const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/points3d.hpp b/rerun_cpp/src/rerun/archetypes/points3d.hpp index 39e2805a2c6a4..4cee27e36ff2f 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.hpp @@ -134,12 +134,10 @@ namespace rerun::archetypes { /// auto time_column = rerun::TimeColumn::from_times("time", std::move(times)); /// /// // Partition our data as expected across the 5 timesteps. - /// auto position = - /// rerun::Points3D::update_fields().with_positions(positions).columns({2, 4, 4, 3, 4}); - /// auto color_and_radius = - /// rerun::Points3D::update_fields().with_colors(colors).with_radii(radii).columns(); + /// auto position = rerun::Points3D().with_positions(positions).columns({2, 4, 4, 3, 4}); + /// auto color_and_radius = rerun::Points3D().with_colors(colors).with_radii(radii).columns(); /// - /// rec.send_columns2("points", time_column, position, color_and_radius); + /// rec.send_columns("points", time_column, position, color_and_radius); /// } /// ``` struct Points3D { @@ -271,6 +269,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `show_labels` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_show_labels` should + /// be used when logging a single row's worth of data. + Points3D with_many_show_labels(const Collection& _show_labels + ) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); + return std::move(*this); + } + /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. diff --git a/rerun_cpp/src/rerun/archetypes/scalar.hpp b/rerun_cpp/src/rerun/archetypes/scalar.hpp index 0d042e46ea916..eed555eb6eda7 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.hpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.hpp @@ -70,12 +70,12 @@ namespace rerun::archetypes { /// std::vector times(64); /// std::iota(times.begin(), times.end(), 0); /// - /// // Convert to rerun time / scalars - /// auto time_column = rerun::TimeColumn::from_sequence_points("step", std::move(times)); - /// auto scalar_data_collection = - /// rerun::Collection(std::move(scalar_data)); - /// - /// rec.send_columns("scalars", time_column, scalar_data_collection); + /// // Serialize to columns and send. + /// rec.send_columns( + /// "scalars", + /// rerun::TimeColumn::from_sequence_points("step", std::move(times)), + /// rerun::Scalar().with_many_scalar(std::move(scalar_data)).columns() + /// ); /// } /// ``` struct Scalar { @@ -120,6 +120,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `scalar` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_scalar` should + /// be used when logging a single row's worth of data. + Scalar with_many_scalar(const Collection& _scalar) && { + scalar = ComponentBatch::from_loggable(_scalar, Descriptor_scalar).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp index 0f7bd33ad6840..bf0be13d9837b 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp @@ -203,12 +203,32 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `buffer` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_buffer` should + /// be used when logging a single row's worth of data. + SegmentationImage with_many_buffer(const Collection& _buffer + ) && { + buffer = ComponentBatch::from_loggable(_buffer, Descriptor_buffer).value_or_throw(); + return std::move(*this); + } + /// The format of the image. SegmentationImage with_format(const rerun::components::ImageFormat& _format) && { format = ComponentBatch::from_loggable(_format, Descriptor_format).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `format` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_format` should + /// be used when logging a single row's worth of data. + SegmentationImage with_many_format(const Collection& _format + ) && { + format = ComponentBatch::from_loggable(_format, Descriptor_format).value_or_throw(); + return std::move(*this); + } + /// Opacity of the image, useful for layering the segmentation image on top of another image. /// /// Defaults to 0.5 if there's any other images in the scene, otherwise 1.0. @@ -217,6 +237,16 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `opacity` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_opacity` should + /// be used when logging a single row's worth of data. + SegmentationImage with_many_opacity(const Collection& _opacity + ) && { + opacity = ComponentBatch::from_loggable(_opacity, Descriptor_opacity).value_or_throw(); + return std::move(*this); + } + /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. @@ -226,6 +256,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `draw_order` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_draw_order` should + /// be used when logging a single row's worth of data. + SegmentationImage with_many_draw_order( + const Collection& _draw_order + ) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index 1f54fc0929aef..4722904b7ba57 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -130,12 +130,30 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `color` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_color` should + /// be used when logging a single row's worth of data. + SeriesLine with_many_color(const Collection& _color) && { + color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); + return std::move(*this); + } + /// Stroke width for the corresponding series. SeriesLine with_width(const rerun::components::StrokeWidth& _width) && { width = ComponentBatch::from_loggable(_width, Descriptor_width).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `width` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_width` should + /// be used when logging a single row's worth of data. + SeriesLine with_many_width(const Collection& _width) && { + width = ComponentBatch::from_loggable(_width, Descriptor_width).value_or_throw(); + return std::move(*this); + } + /// Display name of the series. /// /// Used in the legend. @@ -144,6 +162,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `name` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_name` should + /// be used when logging a single row's worth of data. + SeriesLine with_many_name(const Collection& _name) && { + name = ComponentBatch::from_loggable(_name, Descriptor_name).value_or_throw(); + return std::move(*this); + } + /// Configures the zoom-dependent scalar aggregation. /// /// This is done only if steps on the X axis go below a single pixel, @@ -158,6 +185,19 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `aggregation_policy` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_aggregation_policy` should + /// be used when logging a single row's worth of data. + SeriesLine with_many_aggregation_policy( + const Collection& _aggregation_policy + ) && { + aggregation_policy = + ComponentBatch::from_loggable(_aggregation_policy, Descriptor_aggregation_policy) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index 4d7abb13a9647..47b59063e40b2 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -134,12 +134,30 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `color` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_color` should + /// be used when logging a single row's worth of data. + SeriesPoint with_many_color(const Collection& _color) && { + color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); + return std::move(*this); + } + /// What shape to use to represent the point SeriesPoint with_marker(const rerun::components::MarkerShape& _marker) && { marker = ComponentBatch::from_loggable(_marker, Descriptor_marker).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `marker` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_marker` should + /// be used when logging a single row's worth of data. + SeriesPoint with_many_marker(const Collection& _marker) && { + marker = ComponentBatch::from_loggable(_marker, Descriptor_marker).value_or_throw(); + return std::move(*this); + } + /// Display name of the series. /// /// Used in the legend. @@ -148,6 +166,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `name` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_name` should + /// be used when logging a single row's worth of data. + SeriesPoint with_many_name(const Collection& _name) && { + name = ComponentBatch::from_loggable(_name, Descriptor_name).value_or_throw(); + return std::move(*this); + } + /// Size of the marker. SeriesPoint with_marker_size(const rerun::components::MarkerSize& _marker_size) && { marker_size = ComponentBatch::from_loggable(_marker_size, Descriptor_marker_size) @@ -155,6 +182,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `marker_size` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_marker_size` should + /// be used when logging a single row's worth of data. + SeriesPoint with_many_marker_size( + const Collection& _marker_size + ) && { + marker_size = ComponentBatch::from_loggable(_marker_size, Descriptor_marker_size) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/tensor.hpp b/rerun_cpp/src/rerun/archetypes/tensor.hpp index 97c1b2f0c4526..5de4d5df1b957 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.hpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.hpp @@ -143,6 +143,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `data` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_data` should + /// be used when logging a single row's worth of data. + Tensor with_many_data(const Collection& _data) && { + data = ComponentBatch::from_loggable(_data, Descriptor_data).value_or_throw(); + return std::move(*this); + } + /// The expected range of values. /// /// This is typically the expected range of valid values. @@ -160,6 +169,17 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `value_range` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_value_range` should + /// be used when logging a single row's worth of data. + Tensor with_many_value_range(const Collection& _value_range + ) && { + value_range = ComponentBatch::from_loggable(_value_range, Descriptor_value_range) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/text_document.hpp b/rerun_cpp/src/rerun/archetypes/text_document.hpp index 4db23a9dd6df3..9424df819d022 100644 --- a/rerun_cpp/src/rerun/archetypes/text_document.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_document.hpp @@ -131,6 +131,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `text` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_text` should + /// be used when logging a single row's worth of data. + TextDocument with_many_text(const Collection& _text) && { + text = ComponentBatch::from_loggable(_text, Descriptor_text).value_or_throw(); + return std::move(*this); + } + /// The Media Type of the text. /// /// For instance: @@ -144,6 +153,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `media_type` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_media_type` should + /// be used when logging a single row's worth of data. + TextDocument with_many_media_type( + const Collection& _media_type + ) && { + media_type = + ComponentBatch::from_loggable(_media_type, Descriptor_media_type).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/text_log.hpp b/rerun_cpp/src/rerun/archetypes/text_log.hpp index 11d432261aeb3..3d36b2f3beb76 100644 --- a/rerun_cpp/src/rerun/archetypes/text_log.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_log.hpp @@ -137,6 +137,15 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `text` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_text` should + /// be used when logging a single row's worth of data. + TextLog with_many_text(const Collection& _text) && { + text = ComponentBatch::from_loggable(_text, Descriptor_text).value_or_throw(); + return std::move(*this); + } + /// The verbosity level of the message. /// /// This can be used to filter the log messages in the Rerun Viewer. @@ -145,12 +154,30 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `level` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_level` should + /// be used when logging a single row's worth of data. + TextLog with_many_level(const Collection& _level) && { + level = ComponentBatch::from_loggable(_level, Descriptor_level).value_or_throw(); + return std::move(*this); + } + /// Optional color to use for the log line in the Rerun Viewer. TextLog with_color(const rerun::components::Color& _color) && { color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `color` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_color` should + /// be used when logging a single row's worth of data. + TextLog with_many_color(const Collection& _color) && { + color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index 11a35cd92f5b3..b5a1a6272dd7f 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -615,6 +615,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `translation` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_translation` should + /// be used when logging a single row's worth of data. + Transform3D with_many_translation( + const Collection& _translation + ) && { + translation = ComponentBatch::from_loggable(_translation, Descriptor_translation) + .value_or_throw(); + return std::move(*this); + } + /// Rotation via axis + angle. Transform3D with_rotation_axis_angle( const rerun::components::RotationAxisAngle& _rotation_axis_angle @@ -625,6 +637,19 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `rotation_axis_angle` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_rotation_axis_angle` should + /// be used when logging a single row's worth of data. + Transform3D with_many_rotation_axis_angle( + const Collection& _rotation_axis_angle + ) && { + rotation_axis_angle = + ComponentBatch::from_loggable(_rotation_axis_angle, Descriptor_rotation_axis_angle) + .value_or_throw(); + return std::move(*this); + } + /// Rotation via quaternion. Transform3D with_quaternion(const rerun::components::RotationQuat& _quaternion) && { quaternion = @@ -632,18 +657,49 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `quaternion` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_quaternion` should + /// be used when logging a single row's worth of data. + Transform3D with_many_quaternion( + const Collection& _quaternion + ) && { + quaternion = + ComponentBatch::from_loggable(_quaternion, Descriptor_quaternion).value_or_throw(); + return std::move(*this); + } + /// Scaling factor. Transform3D with_scale(const rerun::components::Scale3D& _scale) && { scale = ComponentBatch::from_loggable(_scale, Descriptor_scale).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `scale` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_scale` should + /// be used when logging a single row's worth of data. + Transform3D with_many_scale(const Collection& _scale) && { + scale = ComponentBatch::from_loggable(_scale, Descriptor_scale).value_or_throw(); + return std::move(*this); + } + /// 3x3 transformation matrix. Transform3D with_mat3x3(const rerun::components::TransformMat3x3& _mat3x3) && { mat3x3 = ComponentBatch::from_loggable(_mat3x3, Descriptor_mat3x3).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `mat3x3` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_mat3x3` should + /// be used when logging a single row's worth of data. + Transform3D with_many_mat3x3(const Collection& _mat3x3 + ) && { + mat3x3 = ComponentBatch::from_loggable(_mat3x3, Descriptor_mat3x3).value_or_throw(); + return std::move(*this); + } + /// Specifies the relation this transform establishes between this entity and its parent. Transform3D with_relation(const rerun::components::TransformRelation& _relation) && { relation = @@ -651,6 +707,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `relation` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_relation` should + /// be used when logging a single row's worth of data. + Transform3D with_many_relation( + const Collection& _relation + ) && { + relation = + ComponentBatch::from_loggable(_relation, Descriptor_relation).value_or_throw(); + return std::move(*this); + } + /// Visual length of the 3 axes. /// /// The length is interpreted in the local coordinate system of the transform. @@ -661,6 +729,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `axis_length` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_axis_length` should + /// be used when logging a single row's worth of data. + Transform3D with_many_axis_length( + const Collection& _axis_length + ) && { + axis_length = ComponentBatch::from_loggable(_axis_length, Descriptor_axis_length) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp index 299a9d6b5a658..e9f206bdb686b 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp @@ -71,10 +71,7 @@ namespace rerun::archetypes { /// rec.send_columns( /// "video", /// time_column, - /// { - /// video_frame_reference_indicators.value_or_throw(), - /// rerun::ComponentColumn::from_loggable(rerun::borrow(video_timestamps)).value_or_throw(), - /// } + /// rerun::VideoFrameReference().with_many_timestamp(rerun::borrow(video_timestamps)).columns() /// ); /// } /// ``` @@ -186,6 +183,18 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `timestamp` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_timestamp` should + /// be used when logging a single row's worth of data. + VideoFrameReference with_many_timestamp( + const Collection& _timestamp + ) && { + timestamp = + ComponentBatch::from_loggable(_timestamp, Descriptor_timestamp).value_or_throw(); + return std::move(*this); + } + /// Optional reference to an entity with a `archetypes::AssetVideo`. /// /// If none is specified, the video is assumed to be at the same entity. @@ -204,6 +213,19 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `video_reference` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_video_reference` should + /// be used when logging a single row's worth of data. + VideoFrameReference with_many_video_reference( + const Collection& _video_reference + ) && { + video_reference = + ComponentBatch::from_loggable(_video_reference, Descriptor_video_reference) + .value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index 224f237a989a3..04fed58dd189c 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -345,6 +345,16 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `xyz` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_xyz` should + /// be used when logging a single row's worth of data. + ViewCoordinates with_many_xyz(const Collection& _xyz + ) && { + xyz = ComponentBatch::from_loggable(_xyz, Descriptor_xyz).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index c073e9b4dbdba..30293fe296707 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -644,79 +644,6 @@ namespace rerun { std::string_view entity_path_prefix = std::string_view(), bool static_ = false ) const; - /// Directly log a columns of data to Rerun. - /// - /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data - /// in a columnar form. Each `TimeColumn` and `Collection` represents a column of data that will be sent to Rerun. - /// The lengths of all of these columns must match, equivalent to a single call to `RecordingStream::log` with a list - /// of individual components. - /// - /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs. - /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. - /// - /// Any failures that may occur during serialization are handled with `Error::handle`. - /// - /// \param entity_path Path to the entity in the space hierarchy. - /// \param time_columns The time columns to send. - /// \param component_columns The columns of components to send. - /// Each individual component in each collection will be associated with a single time value. - /// I.e. this creates `ComponentColumn` objects consisting of single component runs. - /// \see `try_send_columns` - template - void send_columns( - std::string_view entity_path, Collection time_columns, - Collection... component_columns // NOLINT - ) const { - try_send_columns(entity_path, time_columns, component_columns...).handle(); - } - - /// Directly log a columns of data to Rerun. - /// - /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data - /// in a columnar form. Each `TimeColumn` and `Collection` represents a column of data that will be sent to Rerun. - /// The lengths of all of these columns must match, equivalent to a single call to `RecordingStream::log` with a list - /// of individual components. - /// - /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs. - /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. - /// - /// \param entity_path Path to the entity in the space hierarchy. - /// \param time_columns The time columns to send. - /// \param component_columns The columns of components to send. - /// Each individual component in each collection will be associated with a single time value. - /// I.e. this creates `ComponentColumn` objects consisting of single component runs. - /// \see `send_columns` - template - Error try_send_columns( - std::string_view entity_path, Collection time_columns, - Collection... component_columns // NOLINT - ) const { - if (!is_enabled()) { - return Error::ok(); - } - std::vector serialized_columns; - Error err; - ( - [&] { - if (err.is_err()) { - return; - } - - const Result serialization_result = - ComponentColumn::from_loggable(component_columns); - if (serialization_result.is_err()) { - err = serialization_result.error; - return; - } - serialized_columns.emplace_back(std::move(serialization_result.value)); - }(), - ... - ); - RR_RETURN_NOT_OK(err); - - return try_send_columns(entity_path, time_columns, std::move(serialized_columns)); - } - /// Directly log a columns of data to Rerun. /// /// This variant takes in arbitrary amount of `ComponentColumn`s and `ComponentColumn` collections. @@ -737,11 +664,11 @@ namespace rerun { /// \param component_columns The columns of components to send. Both individual `ComponentColumn`s and `Collection`s are accepted. /// \see `try_send_columns` template - void send_columns2( + void send_columns( std::string_view entity_path, Collection time_columns, Ts... component_columns // NOLINT ) const { - try_send_columns2(entity_path, time_columns, component_columns...).handle(); + try_send_columns(entity_path, time_columns, component_columns...).handle(); } /// Directly log a columns of data to Rerun. @@ -762,10 +689,20 @@ namespace rerun { /// \param component_columns The columns of components to send. Both individual `ComponentColumn`s and `Collection`s are accepted. /// \see `send_columns` template - Error try_send_columns2( + Error try_send_columns( std::string_view entity_path, Collection time_columns, Ts... component_columns // NOLINT ) const { + if constexpr (sizeof...(Ts) == 1) { + // Directly forward if this is only a single element, + // skipping collection of component column vector. + return try_send_columns( + entity_path, + std::move(time_columns), + Collection(std::forward(component_columns...)) + ); + } + std::vector flat_column_list; ( [&] { @@ -782,7 +719,8 @@ namespace rerun { return try_send_columns( entity_path, std::move(time_columns), - std::move(flat_column_list) + // Need to create collection explicitly, otherwise this becomes a recursive call. + Collection(std::move(flat_column_list)) ); } diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp index 350d801f9c0d0..a5da323aa7838 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp @@ -281,132 +281,387 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1001` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1001` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1001(const Collection& _fuzz1001 + ) && { + fuzz1001 = + ComponentBatch::from_loggable(_fuzz1001, Descriptor_fuzz1001).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1002(const rerun::components::AffixFuzzer2& _fuzz1002) && { fuzz1002 = ComponentBatch::from_loggable(_fuzz1002, Descriptor_fuzz1002).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1002` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1002` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1002(const Collection& _fuzz1002 + ) && { + fuzz1002 = + ComponentBatch::from_loggable(_fuzz1002, Descriptor_fuzz1002).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1003(const rerun::components::AffixFuzzer3& _fuzz1003) && { fuzz1003 = ComponentBatch::from_loggable(_fuzz1003, Descriptor_fuzz1003).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1003` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1003` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1003(const Collection& _fuzz1003 + ) && { + fuzz1003 = + ComponentBatch::from_loggable(_fuzz1003, Descriptor_fuzz1003).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1004(const rerun::components::AffixFuzzer4& _fuzz1004) && { fuzz1004 = ComponentBatch::from_loggable(_fuzz1004, Descriptor_fuzz1004).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1004` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1004` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1004(const Collection& _fuzz1004 + ) && { + fuzz1004 = + ComponentBatch::from_loggable(_fuzz1004, Descriptor_fuzz1004).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1005(const rerun::components::AffixFuzzer5& _fuzz1005) && { fuzz1005 = ComponentBatch::from_loggable(_fuzz1005, Descriptor_fuzz1005).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1005` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1005` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1005(const Collection& _fuzz1005 + ) && { + fuzz1005 = + ComponentBatch::from_loggable(_fuzz1005, Descriptor_fuzz1005).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1006(const rerun::components::AffixFuzzer6& _fuzz1006) && { fuzz1006 = ComponentBatch::from_loggable(_fuzz1006, Descriptor_fuzz1006).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1006` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1006` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1006(const Collection& _fuzz1006 + ) && { + fuzz1006 = + ComponentBatch::from_loggable(_fuzz1006, Descriptor_fuzz1006).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1007(const rerun::components::AffixFuzzer7& _fuzz1007) && { fuzz1007 = ComponentBatch::from_loggable(_fuzz1007, Descriptor_fuzz1007).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1007` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1007` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1007(const Collection& _fuzz1007 + ) && { + fuzz1007 = + ComponentBatch::from_loggable(_fuzz1007, Descriptor_fuzz1007).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1008(const rerun::components::AffixFuzzer8& _fuzz1008) && { fuzz1008 = ComponentBatch::from_loggable(_fuzz1008, Descriptor_fuzz1008).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1008` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1008` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1008(const Collection& _fuzz1008 + ) && { + fuzz1008 = + ComponentBatch::from_loggable(_fuzz1008, Descriptor_fuzz1008).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1009(const rerun::components::AffixFuzzer9& _fuzz1009) && { fuzz1009 = ComponentBatch::from_loggable(_fuzz1009, Descriptor_fuzz1009).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1009` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1009` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1009(const Collection& _fuzz1009 + ) && { + fuzz1009 = + ComponentBatch::from_loggable(_fuzz1009, Descriptor_fuzz1009).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1010(const rerun::components::AffixFuzzer10& _fuzz1010) && { fuzz1010 = ComponentBatch::from_loggable(_fuzz1010, Descriptor_fuzz1010).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1010` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1010` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1010( + const Collection& _fuzz1010 + ) && { + fuzz1010 = + ComponentBatch::from_loggable(_fuzz1010, Descriptor_fuzz1010).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1011(const rerun::components::AffixFuzzer11& _fuzz1011) && { fuzz1011 = ComponentBatch::from_loggable(_fuzz1011, Descriptor_fuzz1011).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1011` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1011` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1011( + const Collection& _fuzz1011 + ) && { + fuzz1011 = + ComponentBatch::from_loggable(_fuzz1011, Descriptor_fuzz1011).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1012(const rerun::components::AffixFuzzer12& _fuzz1012) && { fuzz1012 = ComponentBatch::from_loggable(_fuzz1012, Descriptor_fuzz1012).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1012` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1012` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1012( + const Collection& _fuzz1012 + ) && { + fuzz1012 = + ComponentBatch::from_loggable(_fuzz1012, Descriptor_fuzz1012).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1013(const rerun::components::AffixFuzzer13& _fuzz1013) && { fuzz1013 = ComponentBatch::from_loggable(_fuzz1013, Descriptor_fuzz1013).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1013` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1013` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1013( + const Collection& _fuzz1013 + ) && { + fuzz1013 = + ComponentBatch::from_loggable(_fuzz1013, Descriptor_fuzz1013).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1014(const rerun::components::AffixFuzzer14& _fuzz1014) && { fuzz1014 = ComponentBatch::from_loggable(_fuzz1014, Descriptor_fuzz1014).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1014` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1014` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1014( + const Collection& _fuzz1014 + ) && { + fuzz1014 = + ComponentBatch::from_loggable(_fuzz1014, Descriptor_fuzz1014).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1015(const rerun::components::AffixFuzzer15& _fuzz1015) && { fuzz1015 = ComponentBatch::from_loggable(_fuzz1015, Descriptor_fuzz1015).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1015` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1015` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1015( + const Collection& _fuzz1015 + ) && { + fuzz1015 = + ComponentBatch::from_loggable(_fuzz1015, Descriptor_fuzz1015).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1016(const rerun::components::AffixFuzzer16& _fuzz1016) && { fuzz1016 = ComponentBatch::from_loggable(_fuzz1016, Descriptor_fuzz1016).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1016` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1016` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1016( + const Collection& _fuzz1016 + ) && { + fuzz1016 = + ComponentBatch::from_loggable(_fuzz1016, Descriptor_fuzz1016).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1017(const rerun::components::AffixFuzzer17& _fuzz1017) && { fuzz1017 = ComponentBatch::from_loggable(_fuzz1017, Descriptor_fuzz1017).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1017` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1017` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1017( + const Collection& _fuzz1017 + ) && { + fuzz1017 = + ComponentBatch::from_loggable(_fuzz1017, Descriptor_fuzz1017).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1018(const rerun::components::AffixFuzzer18& _fuzz1018) && { fuzz1018 = ComponentBatch::from_loggable(_fuzz1018, Descriptor_fuzz1018).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1018` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1018` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1018( + const Collection& _fuzz1018 + ) && { + fuzz1018 = + ComponentBatch::from_loggable(_fuzz1018, Descriptor_fuzz1018).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1019(const rerun::components::AffixFuzzer19& _fuzz1019) && { fuzz1019 = ComponentBatch::from_loggable(_fuzz1019, Descriptor_fuzz1019).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1019` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1019` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1019( + const Collection& _fuzz1019 + ) && { + fuzz1019 = + ComponentBatch::from_loggable(_fuzz1019, Descriptor_fuzz1019).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1020(const rerun::components::AffixFuzzer20& _fuzz1020) && { fuzz1020 = ComponentBatch::from_loggable(_fuzz1020, Descriptor_fuzz1020).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1020` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1020` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1020( + const Collection& _fuzz1020 + ) && { + fuzz1020 = + ComponentBatch::from_loggable(_fuzz1020, Descriptor_fuzz1020).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1021(const rerun::components::AffixFuzzer21& _fuzz1021) && { fuzz1021 = ComponentBatch::from_loggable(_fuzz1021, Descriptor_fuzz1021).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1021` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1021` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1021( + const Collection& _fuzz1021 + ) && { + fuzz1021 = + ComponentBatch::from_loggable(_fuzz1021, Descriptor_fuzz1021).value_or_throw(); + return std::move(*this); + } + AffixFuzzer1 with_fuzz1022(const rerun::components::AffixFuzzer22& _fuzz1022) && { fuzz1022 = ComponentBatch::from_loggable(_fuzz1022, Descriptor_fuzz1022).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz1022` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz1022` should + /// be used when logging a single row's worth of data. + AffixFuzzer1 with_many_fuzz1022( + const Collection& _fuzz1022 + ) && { + fuzz1022 = + ComponentBatch::from_loggable(_fuzz1022, Descriptor_fuzz1022).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp index 6e757f282f4cc..e320ae6331e4f 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp @@ -191,108 +191,315 @@ namespace rerun::archetypes { return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2001` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2001` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2001(const Collection& _fuzz2001 + ) && { + fuzz2001 = + ComponentBatch::from_loggable(_fuzz2001, Descriptor_fuzz2001).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2002(const rerun::components::AffixFuzzer2& _fuzz2002) && { fuzz2002 = ComponentBatch::from_loggable(_fuzz2002, Descriptor_fuzz2002).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2002` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2002` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2002(const Collection& _fuzz2002 + ) && { + fuzz2002 = + ComponentBatch::from_loggable(_fuzz2002, Descriptor_fuzz2002).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2003(const rerun::components::AffixFuzzer3& _fuzz2003) && { fuzz2003 = ComponentBatch::from_loggable(_fuzz2003, Descriptor_fuzz2003).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2003` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2003` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2003(const Collection& _fuzz2003 + ) && { + fuzz2003 = + ComponentBatch::from_loggable(_fuzz2003, Descriptor_fuzz2003).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2004(const rerun::components::AffixFuzzer4& _fuzz2004) && { fuzz2004 = ComponentBatch::from_loggable(_fuzz2004, Descriptor_fuzz2004).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2004` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2004` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2004(const Collection& _fuzz2004 + ) && { + fuzz2004 = + ComponentBatch::from_loggable(_fuzz2004, Descriptor_fuzz2004).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2005(const rerun::components::AffixFuzzer5& _fuzz2005) && { fuzz2005 = ComponentBatch::from_loggable(_fuzz2005, Descriptor_fuzz2005).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2005` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2005` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2005(const Collection& _fuzz2005 + ) && { + fuzz2005 = + ComponentBatch::from_loggable(_fuzz2005, Descriptor_fuzz2005).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2006(const rerun::components::AffixFuzzer6& _fuzz2006) && { fuzz2006 = ComponentBatch::from_loggable(_fuzz2006, Descriptor_fuzz2006).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2006` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2006` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2006(const Collection& _fuzz2006 + ) && { + fuzz2006 = + ComponentBatch::from_loggable(_fuzz2006, Descriptor_fuzz2006).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2007(const rerun::components::AffixFuzzer7& _fuzz2007) && { fuzz2007 = ComponentBatch::from_loggable(_fuzz2007, Descriptor_fuzz2007).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2007` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2007` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2007(const Collection& _fuzz2007 + ) && { + fuzz2007 = + ComponentBatch::from_loggable(_fuzz2007, Descriptor_fuzz2007).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2008(const rerun::components::AffixFuzzer8& _fuzz2008) && { fuzz2008 = ComponentBatch::from_loggable(_fuzz2008, Descriptor_fuzz2008).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2008` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2008` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2008(const Collection& _fuzz2008 + ) && { + fuzz2008 = + ComponentBatch::from_loggable(_fuzz2008, Descriptor_fuzz2008).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2009(const rerun::components::AffixFuzzer9& _fuzz2009) && { fuzz2009 = ComponentBatch::from_loggable(_fuzz2009, Descriptor_fuzz2009).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2009` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2009` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2009(const Collection& _fuzz2009 + ) && { + fuzz2009 = + ComponentBatch::from_loggable(_fuzz2009, Descriptor_fuzz2009).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2010(const rerun::components::AffixFuzzer10& _fuzz2010) && { fuzz2010 = ComponentBatch::from_loggable(_fuzz2010, Descriptor_fuzz2010).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2010` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2010` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2010( + const Collection& _fuzz2010 + ) && { + fuzz2010 = + ComponentBatch::from_loggable(_fuzz2010, Descriptor_fuzz2010).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2011(const rerun::components::AffixFuzzer11& _fuzz2011) && { fuzz2011 = ComponentBatch::from_loggable(_fuzz2011, Descriptor_fuzz2011).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2011` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2011` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2011( + const Collection& _fuzz2011 + ) && { + fuzz2011 = + ComponentBatch::from_loggable(_fuzz2011, Descriptor_fuzz2011).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2012(const rerun::components::AffixFuzzer12& _fuzz2012) && { fuzz2012 = ComponentBatch::from_loggable(_fuzz2012, Descriptor_fuzz2012).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2012` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2012` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2012( + const Collection& _fuzz2012 + ) && { + fuzz2012 = + ComponentBatch::from_loggable(_fuzz2012, Descriptor_fuzz2012).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2013(const rerun::components::AffixFuzzer13& _fuzz2013) && { fuzz2013 = ComponentBatch::from_loggable(_fuzz2013, Descriptor_fuzz2013).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2013` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2013` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2013( + const Collection& _fuzz2013 + ) && { + fuzz2013 = + ComponentBatch::from_loggable(_fuzz2013, Descriptor_fuzz2013).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2014(const rerun::components::AffixFuzzer14& _fuzz2014) && { fuzz2014 = ComponentBatch::from_loggable(_fuzz2014, Descriptor_fuzz2014).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2014` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2014` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2014( + const Collection& _fuzz2014 + ) && { + fuzz2014 = + ComponentBatch::from_loggable(_fuzz2014, Descriptor_fuzz2014).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2015(const rerun::components::AffixFuzzer15& _fuzz2015) && { fuzz2015 = ComponentBatch::from_loggable(_fuzz2015, Descriptor_fuzz2015).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2015` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2015` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2015( + const Collection& _fuzz2015 + ) && { + fuzz2015 = + ComponentBatch::from_loggable(_fuzz2015, Descriptor_fuzz2015).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2016(const rerun::components::AffixFuzzer16& _fuzz2016) && { fuzz2016 = ComponentBatch::from_loggable(_fuzz2016, Descriptor_fuzz2016).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2016` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2016` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2016( + const Collection& _fuzz2016 + ) && { + fuzz2016 = + ComponentBatch::from_loggable(_fuzz2016, Descriptor_fuzz2016).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2017(const rerun::components::AffixFuzzer17& _fuzz2017) && { fuzz2017 = ComponentBatch::from_loggable(_fuzz2017, Descriptor_fuzz2017).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2017` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2017` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2017( + const Collection& _fuzz2017 + ) && { + fuzz2017 = + ComponentBatch::from_loggable(_fuzz2017, Descriptor_fuzz2017).value_or_throw(); + return std::move(*this); + } + AffixFuzzer3 with_fuzz2018(const rerun::components::AffixFuzzer18& _fuzz2018) && { fuzz2018 = ComponentBatch::from_loggable(_fuzz2018, Descriptor_fuzz2018).value_or_throw(); return std::move(*this); } + /// This method makes it possible to pack multiple `fuzz2018` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_fuzz2018` should + /// be used when logging a single row's worth of data. + AffixFuzzer3 with_many_fuzz2018( + const Collection& _fuzz2018 + ) && { + fuzz2018 = + ComponentBatch::from_loggable(_fuzz2018, Descriptor_fuzz2018).value_or_throw(); + return std::move(*this); + } + /// Partitions the component data into multiple sub-batches. /// /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s diff --git a/tests/cpp/plot_dashboard_stress/main.cpp b/tests/cpp/plot_dashboard_stress/main.cpp index 9a582b1e42495..17b7650f5aaa4 100644 --- a/tests/cpp/plot_dashboard_stress/main.cpp +++ b/tests/cpp/plot_dashboard_stress/main.cpp @@ -189,10 +189,12 @@ int main(int argc, char** argv) { rec.send_columns( path, *time_column, - rerun::Collection::borrow( - series_values.data() + time_step, - *temporal_batch_size - ) + rerun::Scalar::update_fields() + .with_many_scalar(rerun::borrow( + series_values.data() + time_step, + *temporal_batch_size + )) + .columns() ); } else { rec.log(path, rerun::Scalar(series_values[time_step])); From 7293f690ba539b3f99798f4fec0aeb30f34b287e Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 28 Jan 2025 12:08:28 +0100 Subject: [PATCH 17/43] Python: remove legacy `send_columns` and update everything left (#8799) Title. --- .../rerun/components/video_timestamp.fbs | 1 + .../rerun/datatypes/video_timestamp.fbs | 1 + .../data-out/analyze-and-send.md | 16 +- docs/snippets/INDEX.md | 2 +- .../all/archetypes/image_send_columns.py | 14 +- .../all/archetypes/mesh3d_partial_updates.py | 3 +- .../points3d_partial_updates_legacy.cpp | 58 ------- .../points3d_partial_updates_legacy.py | 32 ---- .../points3d_partial_updates_legacy.rs | 51 ------- .../all/archetypes/points3d_send_columns.py | 2 +- .../all/archetypes/scalar_send_columns.py | 2 +- .../all/archetypes/video_auto_frames.py | 5 +- .../all/concepts/static/send_static.py | 2 +- .../all/howto/any_batch_value_send_columns.py | 2 +- .../all/howto/any_values_send_columns.py | 2 +- docs/snippets/all/tutorials/data_out.py | 14 +- docs/snippets/snippets.toml | 1 - .../air_traffic_data/air_traffic_data.py | 25 ++- examples/python/drone_lidar/drone_lidar.py | 19 +-- .../incremental_logging.py | 18 +-- rerun_py/rerun_sdk/rerun/__init__.py | 1 - rerun_py/rerun_sdk/rerun/_baseclasses.py | 3 + rerun_py/rerun_sdk/rerun/_send_columns.py | 143 +----------------- .../rerun_sdk/rerun/archetypes/asset_video.py | 6 +- .../rerun_sdk/rerun/archetypes/points3d.py | 2 +- rerun_py/rerun_sdk/rerun/archetypes/scalar.py | 2 +- .../rerun/archetypes/video_frame_reference.py | 6 +- .../archetypes/video_frame_reference_ext.py | 61 ++++++++ .../rerun/datatypes/video_timestamp.py | 5 +- tests/python/chunk_zoo/chunk_zoo.py | 76 +++------- tests/python/chunked_video/chunked_video.py | 7 +- .../log_benchmark/test_log_benchmark.py | 15 +- tests/python/plot_dashboard_stress/main.py | 5 +- .../check_drag_and_drop_selection.py | 2 +- .../check_entity_drag_and_drop.py | 2 +- .../check_multi_entity_drag_and_drop.py | 2 +- tests/python/release_checklist/check_video.py | 7 +- 37 files changed, 160 insertions(+), 455 deletions(-) delete mode 100644 docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp delete mode 100644 docs/snippets/all/archetypes/points3d_partial_updates_legacy.py delete mode 100644 docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs diff --git a/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs b/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs index 37f0a24828d69..cc8158dc6adee 100644 --- a/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs +++ b/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs @@ -4,6 +4,7 @@ namespace rerun.components; /// Timestamp inside a [archetypes.AssetVideo]. struct VideoTimestamp ( "attr.arrow.transparent", + "attr.python.array_aliases": "npt.NDArray[np.int64]", "attr.rust.derive": "Copy, PartialEq, Eq, Default", "attr.rust.repr": "transparent" ) { diff --git a/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs b/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs index a62df5da7224b..7e67800ac952e 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs @@ -7,6 +7,7 @@ namespace rerun.datatypes; struct VideoTimestamp ( "attr.arrow.transparent", "attr.python.aliases": "int", + "attr.python.array_aliases": "npt.NDArray[np.int64]", "attr.rust.derive": "Default, Copy, PartialEq, Eq, PartialOrd, Ord", "attr.rust.tuple_struct" ) { diff --git a/docs/content/getting-started/data-out/analyze-and-send.md b/docs/content/getting-started/data-out/analyze-and-send.md index e27bd532741c6..39963096a1164 100644 --- a/docs/content/getting-started/data-out/analyze-and-send.md +++ b/docs/content/getting-started/data-out/analyze-and-send.md @@ -46,10 +46,8 @@ Here is how to send the data as a scalar: ```python rr.send_columns( "/jaw_open_state", - times=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], - components=[ - rr.components.ScalarBatch(df["jawOpenState"]), - ], + indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], + columns=rr.Scalar.columns(scalar=df["jawOpenState"]), ) ``` @@ -59,17 +57,15 @@ Next, let's send the same data as `Text` component: ```python target_entity = "/video/detector/faces/0/bbox" -rr.log(target_entity, [rr.components.ShowLabels(True)], static=True) +rr.log(target_entity, rr.Boxes2D.update_fields(show_labels=True), static=True) rr.send_columns( target_entity, - times=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], - components=[ - rr.components.TextBatch(np.where(df["jawOpenState"], "OPEN", "CLOSE")), - ], + indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], + columns=rr.Boxes2D.columns(labels=np.where(df["jawOpenState"], "OPEN", "CLOSE")), ) ``` -Here we first log the [`ShowLabel`](../../reference/types/components/show_labels.md) component as static to enable the display of the label. Then, we use `rr.send_column()` again to send an entire batch of text labels. We use the [`np.where()`](https://numpy.org/doc/stable/reference/generated/numpy.where.html) to produce a label matching the state for each timestamp. +Here we first log the [`ShowLabel`](../../reference/types/components/show_labels.md) component as static to enable the display of the label. Then, we use `rr.send_column()` again to send an entire batch of text labels. We use [`np.where()`](https://numpy.org/doc/stable/reference/generated/numpy.where.html) to produce a label matching the state for each timestamp. ### Final result diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index ba4ba24371559..54c37146d7148 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -68,6 +68,7 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`Boxes2D`](https://rerun.io/docs/reference/types/archetypes/boxes2d)** | `concepts⁠/⁠viscomp-component-override` | Override a component | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-component-override.py) | | | | **[`Boxes2D`](https://rerun.io/docs/reference/types/archetypes/boxes2d)** | `concepts⁠/⁠viscomp-visualizer-override` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override.py) | | | | **[`Boxes2D`](https://rerun.io/docs/reference/types/archetypes/boxes2d)** | `concepts⁠/⁠viscomp-visualizer-override-multiple` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override-multiple.py) | | | +| **[`Boxes2D`](https://rerun.io/docs/reference/types/archetypes/boxes2d)** | `tutorials⁠/⁠data_out` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/data_out.py) | | | | **[`Boxes3D`](https://rerun.io/docs/reference/types/archetypes/boxes3d)** | `archetypes⁠/⁠boxes3d_simple` | Log a single 3D Box | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/boxes3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/boxes3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/boxes3d_simple.cpp) | | **[`Boxes3D`](https://rerun.io/docs/reference/types/archetypes/boxes3d)** | `archetypes⁠/⁠boxes3d_batch` | Log a batch of oriented bounding boxes | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/boxes3d_batch.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/boxes3d_batch.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/boxes3d_batch.cpp) | | **[`Boxes3D`](https://rerun.io/docs/reference/types/archetypes/boxes3d)** | `archetypes⁠/⁠instance_poses3d_combined` | Log a simple 3D box with a regular & instance pose transform | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.cpp) | @@ -135,7 +136,6 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠points3d_simple` | Log some very simple points | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_simple.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠points3d_random` | Log some random points with color and radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_random.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_random.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_random.cpp) | -| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠annotation_context_connections` | Log annotation context with connections between keypoints | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes⁠/⁠ellipsoids3d_simple` | Log random points and the corresponding covariance ellipsoid | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/ellipsoids3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/ellipsoids3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/ellipsoids3d_simple.cpp) | diff --git a/docs/snippets/all/archetypes/image_send_columns.py b/docs/snippets/all/archetypes/image_send_columns.py index 96ddc5fd4f10f..3359fe5d7d726 100644 --- a/docs/snippets/all/archetypes/image_send_columns.py +++ b/docs/snippets/all/archetypes/image_send_columns.py @@ -17,16 +17,16 @@ # Log the ImageFormat and indicator once, as static. format_static = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8") -rr.log("images", [format_static, rr.Image.indicator()], static=True) +rr.send_columns("images", indexes=[], columns=rr.Image.columns(format=format_static)) # Send all images at once. rr.send_columns( "images", - times=[rr.TimeSequenceColumn("step", times)], - # Reshape the images so `ImageBufferBatch` can tell that this is several blobs. + indexes=[rr.TimeSequenceColumn("step", times)], + # Reshape the images so `Image` can tell that this is several blobs. # - # Note that the `ImageBufferBatch` consumes arrays of bytes, - # so if you have a different channel datatype than `U8`, you need to make sure - # that the data is converted to arrays of bytes before passing it to `ImageBufferBatch`. - components=[rr.components.ImageBufferBatch(images.reshape(len(times), -1))], + # Note that the `Image` consumes arrays of bytes, so if you have a different channel + # datatype than `U8`, you need to make sure that the data is converted to arrays of bytes + # before passing it to `Image`. + columns=rr.Image.columns(buffer=images.reshape(len(times), -1)), ) diff --git a/docs/snippets/all/archetypes/mesh3d_partial_updates.py b/docs/snippets/all/archetypes/mesh3d_partial_updates.py index e33f1e55438d5..8bc36153dcdca 100644 --- a/docs/snippets/all/archetypes/mesh3d_partial_updates.py +++ b/docs/snippets/all/archetypes/mesh3d_partial_updates.py @@ -2,7 +2,6 @@ import numpy as np import rerun as rr -from rerun.components import Position3DBatch rr.init("rerun_example_mesh3d_partial_updates", spawn=True) @@ -23,4 +22,4 @@ factors = np.abs(np.sin(np.arange(1, 300, dtype=np.float32) * 0.04)) for i, factor in enumerate(factors): rr.set_time_sequence("frame", i) - rr.log("triangle", [Position3DBatch(vertex_positions * factor)]) + rr.log("triangle", rr.Mesh3D.update_fields(vertex_positions=vertex_positions * factor)) diff --git a/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp b/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp deleted file mode 100644 index ad39a9c5cd9cb..0000000000000 --- a/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Demonstrates usage of the legacy partial updates APIs. - -#include - -#include -#include - -int main() { - const auto rec = rerun::RecordingStream("rerun_example_points3d_partial_updates_legacy"); - rec.spawn().exit_on_failure(); - - std::vector positions; - for (int i = 0; i < 10; ++i) { - positions.emplace_back(static_cast(i), 0.0f, 0.0f); - } - - rec.set_time_sequence("frame", 0); - rec.log("points", rerun::Points3D(positions)); - - for (int i = 0; i < 10; ++i) { - std::vector colors; - for (int n = 0; n < 10; ++n) { - if (n < i) { - colors.emplace_back(rerun::Color(20, 200, 20)); - } else { - colors.emplace_back(rerun::Color(200, 20, 20)); - } - } - - std::vector radii; - for (int n = 0; n < 10; ++n) { - if (n < i) { - radii.emplace_back(rerun::Radius(0.6f)); - } else { - radii.emplace_back(rerun::Radius(0.2f)); - } - } - - rec.set_time_sequence("frame", i); - rec.log("points", colors, radii); - } - - std::vector radii; - radii.emplace_back(0.3f); - - rec.set_time_sequence("frame", 20); - rec.log( - "points", - rerun::Points3D::IndicatorComponent(), - positions, - radii, - std::vector(), - std::vector(), - std::vector(), - std::vector(), - std::vector() - ); -} diff --git a/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py b/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py deleted file mode 100644 index fab36e44e771e..0000000000000 --- a/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Demonstrates usage of the new partial updates APIs.""" - -import rerun as rr - -rr.init("rerun_example_points3d_partial_updates_legacy", spawn=True) - -positions = [[i, 0, 0] for i in range(0, 10)] - -rr.set_time_sequence("frame", 0) -rr.log("points", rr.Points3D(positions)) - -for i in range(0, 10): - colors = [[20, 200, 20] if n < i else [200, 20, 20] for n in range(0, 10)] - radii = [0.6 if n < i else 0.2 for n in range(0, 10)] - - rr.set_time_sequence("frame", i) - rr.log("points", [rr.components.ColorBatch(colors), rr.components.RadiusBatch(radii)]) - -rr.set_time_sequence("frame", 20) -rr.log( - "points", - [ - rr.Points3D.indicator(), - rr.components.Position3DBatch(positions), - rr.components.RadiusBatch(0.3), - rr.components.ColorBatch([]), - rr.components.TextBatch([]), - rr.components.ShowLabelsBatch([]), - rr.components.ClassIdBatch([]), - rr.components.KeypointIdBatch([]), - ], -) diff --git a/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs b/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs deleted file mode 100644 index de4ca9f83cef2..0000000000000 --- a/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! Demonstrates usage of the legacy partial updates APIs. - -fn main() -> Result<(), Box> { - let rec = rerun::RecordingStreamBuilder::new("rerun_example_points3d_partial_updates_legacy") - .spawn()?; - - let positions = (0..10).map(|i| (i as f32, 0.0, 0.0)); - - rec.set_time_sequence("frame", 0); - rec.log("points", &rerun::Points3D::new(positions))?; - - for i in 0..10 { - let colors: Vec = (0..10) - .map(|n| { - if n < i { - rerun::Color::from_rgb(20, 200, 20) - } else { - rerun::Color::from_rgb(200, 20, 20) - } - }) - .collect(); - let radii: Vec = (0..10) - .map(|n| if n < i { 0.6 } else { 0.2 }) - .map(Into::into) - .collect(); - - rec.set_time_sequence("frame", i); - rec.log("points", &[&colors as &dyn rerun::ComponentBatch, &radii])?; - } - - use rerun::Archetype as _; - let positions: Vec = - (0..10).map(|i| (i as f32, 0.0, 0.0).into()).collect(); - - rec.set_time_sequence("frame", 20); - rec.log( - "points", - &[ - &rerun::Points3D::indicator() as &dyn rerun::ComponentBatch, - &positions, - &vec![rerun::components::Radius(0.3.into())], - &Vec::::new(), - &Vec::::new(), - &Vec::::new(), - &Vec::::new(), - &Vec::::new(), - ], - )?; - - Ok(()) -} diff --git a/docs/snippets/all/archetypes/points3d_send_columns.py b/docs/snippets/all/archetypes/points3d_send_columns.py index 5d4d90c793792..74bad5fcffbd5 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.py +++ b/docs/snippets/all/archetypes/points3d_send_columns.py @@ -23,7 +23,7 @@ colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] -rr.send_columns_v2( +rr.send_columns( "points", indexes=[rr.TimeSecondsColumn("time", times)], columns=[ diff --git a/docs/snippets/all/archetypes/scalar_send_columns.py b/docs/snippets/all/archetypes/scalar_send_columns.py index 0f1e789fe9eba..933a368d2b646 100644 --- a/docs/snippets/all/archetypes/scalar_send_columns.py +++ b/docs/snippets/all/archetypes/scalar_send_columns.py @@ -10,7 +10,7 @@ times = np.arange(0, 64) scalars = np.sin(times / 10.0) -rr.send_columns_v2( +rr.send_columns( "scalars", indexes=[rr.TimeSequenceColumn("step", times)], columns=rr.Scalar.columns(scalar=scalars), diff --git a/docs/snippets/all/archetypes/video_auto_frames.py b/docs/snippets/all/archetypes/video_auto_frames.py index 2e81fd8c42ba4..ee32fac50909b 100644 --- a/docs/snippets/all/archetypes/video_auto_frames.py +++ b/docs/snippets/all/archetypes/video_auto_frames.py @@ -1,5 +1,4 @@ """Log a video asset using automatically determined frame references.""" -# TODO(#7298): ⚠️ Video is currently only supported in the Rerun web viewer. import sys @@ -21,6 +20,6 @@ rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. - times=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], - components=[rr.VideoFrameReference.indicator(), rr.components.VideoTimestamp.nanoseconds(frame_timestamps_ns)], + indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], + columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) diff --git a/docs/snippets/all/concepts/static/send_static.py b/docs/snippets/all/concepts/static/send_static.py index befc7c9a6de5c..56d9683b2b4bf 100644 --- a/docs/snippets/all/concepts/static/send_static.py +++ b/docs/snippets/all/concepts/static/send_static.py @@ -1 +1 @@ -rr.send_columns("skybox", times=[], components=generate_skybox_mesh()) +rr.send_columns("skybox", indexes=[], columns=generate_skybox_mesh()) diff --git a/docs/snippets/all/howto/any_batch_value_send_columns.py b/docs/snippets/all/howto/any_batch_value_send_columns.py index 640cc2b03c3a3..b059d4ae27e36 100644 --- a/docs/snippets/all/howto/any_batch_value_send_columns.py +++ b/docs/snippets/all/howto/any_batch_value_send_columns.py @@ -12,7 +12,7 @@ one_per_timestamp = np.sin(timestamps / 10.0) ten_per_timestamp = np.cos(np.arange(0, N * 10) / 100.0) -rr.send_columns_v2( +rr.send_columns( "/", indexes=[rr.TimeSequenceColumn("step", timestamps)], columns=[ diff --git a/docs/snippets/all/howto/any_values_send_columns.py b/docs/snippets/all/howto/any_values_send_columns.py index 369b7ef2d25b3..36d381fd62b0d 100644 --- a/docs/snippets/all/howto/any_values_send_columns.py +++ b/docs/snippets/all/howto/any_values_send_columns.py @@ -10,7 +10,7 @@ timestamps = np.arange(0, 64) # Log two component columns, named "sin" and "cos", with the corresponding values -rr.send_columns_v2( +rr.send_columns( "/", indexes=[rr.TimeSequenceColumn("step", timestamps)], columns=rr.AnyValues.columns(sin=np.sin(timestamps / 10.0), cos=np.cos(timestamps / 10.0)), diff --git a/docs/snippets/all/tutorials/data_out.py b/docs/snippets/all/tutorials/data_out.py index f95a3ae939e54..da003cdb2312e 100644 --- a/docs/snippets/all/tutorials/data_out.py +++ b/docs/snippets/all/tutorials/data_out.py @@ -32,19 +32,15 @@ # log the jaw open state signal as a scalar rr.send_columns( "/jaw_open_state", - times=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], - components=[ - rr.components.ScalarBatch(df["jawOpenState"]), - ], + indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], + columns=rr.Scalar.columns(scalar=df["jawOpenState"]), ) # log a `Label` component to the face bounding box entity target_entity = "/video/detector/faces/0/bbox" -rr.log(target_entity, [rr.components.ShowLabels(True)], static=True) +rr.log(target_entity, rr.Boxes2D.update_fields(show_labels=True), static=True) rr.send_columns( target_entity, - times=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], - components=[ - rr.components.TextBatch(np.where(df["jawOpenState"], "OPEN", "CLOSE")), - ], + indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], + columns=rr.Boxes2D.columns(labels=np.where(df["jawOpenState"], "OPEN", "CLOSE")), ) diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index d50f28be5316c..83fa22a045d4a 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -279,7 +279,6 @@ quick_start = [ # These examples don't have exactly the same implementation. ] "archetypes/image_send_columns" = [ # This mixes `log` and `send_columns`. Since `log` is suspect to delays by the batcher, this test gets flaky. "cpp", - "py", "rust", ] "archetypes/mesh3d_instancing" = [ # TODO(#3235): Slight floating point differences in deg to rad conversion. diff --git a/examples/python/air_traffic_data/air_traffic_data.py b/examples/python/air_traffic_data/air_traffic_data.py index 2e2352e0ef0c0..5ce87efc8dbc0 100644 --- a/examples/python/air_traffic_data/air_traffic_data.py +++ b/examples/python/air_traffic_data/air_traffic_data.py @@ -318,17 +318,16 @@ def log_position_and_altitude(self, df: polars.DataFrame, icao_id: str) -> None: color = rr.components.Color.from_string(entity_path) rr.log( entity_path, - [rr.archetypes.Points3D.indicator(), rr.archetypes.GeoPoints.indicator(), color], + rr.Points3D.update_fields(colors=color), + # TODO(cmc): That would be UB right now (and doesn't matter as long as we are on the untagged index). + # rr.GeoPoints.update_fields(colors=color), static=True, ) - rr.log(entity_path + "/barometric_altitude", [rr.archetypes.SeriesLine.indicator(), color], static=True) + rr.log(entity_path + "/barometric_altitude", rr.SeriesLine.update_fields(color=color), static=True) self._position_indicators.add(icao_id) timestamps = rr.TimeSecondsColumn("unix_time", df["timestamp"].to_numpy()) pos = self._proj.transform(df["longitude"], df["latitude"], df["barometric_altitude"]) - positions = rr.components.Position3DBatch(np.vstack(pos).T) - - lat_lon = rr.components.LatLonBatch(np.vstack((df["latitude"], df["longitude"])).T) raw_coordinates = rr.AnyValues( latitude=df["latitude"].to_numpy(), @@ -340,16 +339,16 @@ def log_position_and_altitude(self, df: polars.DataFrame, icao_id: str) -> None: entity_path, [timestamps], [ - positions, - lat_lon, - *raw_coordinates.as_component_batches(), + *rr.Points3D.columns(positions=np.vstack(pos).T), + *rr.GeoPoints.columns(positions=np.vstack((df["latitude"], df["longitude"])).T), + *raw_coordinates.columns(), ], ) rr.send_columns( entity_path + "/barometric_altitude", [timestamps], - [rr.components.ScalarBatch(df["barometric_altitude"].to_numpy())], + rr.Scalar.columns(scalar=df["barometric_altitude"].to_numpy()), ) def log_ground_status(self, df: polars.DataFrame, icao_id: str) -> None: @@ -357,15 +356,15 @@ def log_ground_status(self, df: polars.DataFrame, icao_id: str) -> None: df = df["timestamp", "ground_status"].drop_nulls() timestamps = rr.TimeSecondsColumn("unix_time", df["timestamp"].to_numpy()) - batches = rr.AnyValues(ground_status=df["ground_status"].to_numpy()) + columns = rr.AnyValues.columns(ground_status=df["ground_status"].to_numpy()) - rr.send_columns(entity_path, [timestamps], batches.as_component_batches()) + rr.send_columns(entity_path, [timestamps], columns) def log_metadata(self, df: polars.DataFrame, icao_id: str) -> None: entity_path = f"aircraft/{icao_id}" df = df["timestamp", "course", "ground_speed", "vertical_speed"].drop_nulls() - metadata = rr.AnyValues( + metadata = rr.AnyValues.columns( course=df["course"].to_numpy(), ground_speed=df["ground_speed"].to_numpy(), vertical_speed=df["vertical_speed"].to_numpy(), @@ -374,7 +373,7 @@ def log_metadata(self, df: polars.DataFrame, icao_id: str) -> None: rr.send_columns( entity_path, [rr.TimeSecondsColumn("unix_time", df["timestamp"].to_numpy())], - metadata.component_batches, + metadata, ) diff --git a/examples/python/drone_lidar/drone_lidar.py b/examples/python/drone_lidar/drone_lidar.py index a59f75cdfecd9..36594fce8073f 100644 --- a/examples/python/drone_lidar/drone_lidar.py +++ b/examples/python/drone_lidar/drone_lidar.py @@ -113,17 +113,13 @@ def log_lidar_data() -> None: rr.send_columns( "/lidar", [rr.TimeSecondsColumn("time", non_repeating_times)], - [rr.components.Position3DBatch(positions).partition(partitions)], + rr.Points3D.columns(positions=positions).partition(partitions), ) rr.log( "/lidar", - [ - # TODO(#6889): indicator component no longer needed not needed when we have tagged components - rr.Points3D.indicator(), - rr.components.Radius(-0.1), # negative radii are interpreted in UI units (instead of scene units) - rr.components.Color((128, 128, 255)), - ], + # negative radii are interpreted in UI units (instead of scene units) + rr.Points3D.update_fields(colors=(128, 128, 255), radii=-0.1), static=True, ) @@ -136,17 +132,12 @@ def log_drone_trajectory() -> None: rr.send_columns( "/drone", [rr.TimeSecondsColumn("time", timestamp)], - [rr.components.Position3DBatch(positions)], + rr.Points3D.columns(positions=positions), ) rr.log( "/drone", - [ - # TODO(#6889): indicator component no longer needed not needed when we have tagged components - rr.Points3D.indicator(), - rr.components.Radius(0.5), - rr.components.Color([255, 0, 0]), - ], + rr.Points3D.update_fields(colors=(255, 0, 0), radii=0.5), static=True, ) diff --git a/examples/python/incremental_logging/incremental_logging.py b/examples/python/incremental_logging/incremental_logging.py index 9ff3f99ce6441..26c707d224a50 100755 --- a/examples/python/incremental_logging/incremental_logging.py +++ b/examples/python/incremental_logging/incremental_logging.py @@ -20,12 +20,10 @@ It was logged with the following code: ```python -colors = rr.components.ColorBatch(np.repeat(0xFF0000FF, 10)) -radii = rr.components.RadiusBatch(np.repeat(0.1, 10)) - # Only log colors and radii once. +# Logging as static would also work (i.e. `static=True`). rr.set_time_sequence("frame_nr", 0) -rr.log("points", [colors, radii]) +rr.log("points", rr.Points3D.update_fields(colors=0xFF0000FF, radii=0.1)) rng = default_rng(12345) @@ -34,7 +32,7 @@ # They will automatically re-use the colors and radii logged at the beginning. for i in range(10): rr.set_time_sequence("frame_nr", i) - rr.log("points", rr.Points3D(rng.uniform(-5, 5, size=[10, 3]))) + rr.log("points", rr.Points3D.update_fields(positions=rng.uniform(-5, 5, size=[10, 3]))) ``` Move the time cursor around, and notice how the colors and radii from frame 0 are still picked up by later frames, while the points themselves keep changing every frame. @@ -46,14 +44,10 @@ rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) -colors = rr.components.ColorBatch(0xFF0000FF) -radii = rr.components.RadiusBatch(0.1) - # Only log colors and radii once. +# Logging as static would also work (i.e. `static=True`). rr.set_time_sequence("frame_nr", 0) -rr.log("points", [colors, radii]) -# Logging as static would also work. -# rr.log("points", [colors, radii], static=True) +rr.log("points", rr.Points3D.update_fields(colors=0xFF0000FF, radii=0.1)) rng = default_rng(12345) @@ -62,6 +56,6 @@ # They will automatically re-use the colors and radii logged at the beginning. for i in range(10): rr.set_time_sequence("frame_nr", i) - rr.log("points", rr.Points3D(rng.uniform(-5, 5, size=[10, 3]))) + rr.log("points", rr.Points3D.update_fields(positions=rng.uniform(-5, 5, size=[10, 3]))) rr.script_teardown(args) diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index ad113ae3e63d1..c9bb5414cb4c3 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -59,7 +59,6 @@ TimeSecondsColumn as TimeSecondsColumn, TimeSequenceColumn as TimeSequenceColumn, send_columns as send_columns, - send_columns_v2 as send_columns_v2, ) from .any_value import ( AnyBatchValue as AnyBatchValue, diff --git a/rerun_py/rerun_sdk/rerun/_baseclasses.py b/rerun_py/rerun_sdk/rerun/_baseclasses.py index e07e4853ab0de..10b57f3668a33 100644 --- a/rerun_py/rerun_sdk/rerun/_baseclasses.py +++ b/rerun_py/rerun_sdk/rerun/_baseclasses.py @@ -450,6 +450,9 @@ def __init__(self, columns: Iterable[ComponentColumn]): def __iter__(self) -> Iterator[ComponentColumn]: return iter(self._columns) + def __len__(self) -> int: + return len(self._columns) + def partition(self, lengths: npt.ArrayLike) -> ComponentColumnList: """ (Re)Partitions the columns. diff --git a/rerun_py/rerun_sdk/rerun/_send_columns.py b/rerun_py/rerun_sdk/rerun/_send_columns.py index 24ad6e7fb3045..9682cc3a8178b 100644 --- a/rerun_py/rerun_sdk/rerun/_send_columns.py +++ b/rerun_py/rerun_sdk/rerun/_send_columns.py @@ -5,8 +5,7 @@ import pyarrow as pa import rerun_bindings as bindings -from ._baseclasses import Archetype, ComponentBatchLike, ComponentBatchMixin, ComponentColumn, ComponentDescriptor -from ._log import IndicatorComponentBatch +from ._baseclasses import Archetype, ComponentColumn, ComponentDescriptor from .error_utils import catch_and_log_exceptions from .recording_stream import RecordingStream @@ -118,146 +117,6 @@ def as_arrow_array(self) -> pa.Array: @catch_and_log_exceptions() def send_columns( - entity_path: str, - times: Iterable[TimeColumnLike], - components: Iterable[ComponentBatchLike], - recording: RecordingStream | None = None, - strict: bool | None = None, -) -> None: - r""" - Send columnar data to Rerun. - - Unlike the regular `log` API, which is row-oriented, this API lets you submit the data - in a columnar form. Each `TimeColumnLike` and `ComponentColumnLike` object represents a column - of data that will be sent to Rerun. The lengths of all of these columns must match, and all - data that shares the same index across the different columns will act as a single logical row, - equivalent to a single call to `rr.log()`. - - Note that this API ignores any stateful time set on the log stream via the `rerun.set_time_*` APIs. - Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns. - - When using a regular `ComponentBatch` input, the batch data will map to single-valued component - instances at each timepoint. - - For example, scalars would be logged as: - ```py - times = np.arange(0, 64) - scalars = np.sin(times / 10.0) - - rr.send_columns( - "scalars", - times=[rr.TimeSequenceColumn("step", times)], - components=[rr.components.ScalarBatch(scalars)], - ) - ``` - In the viewer this will show up as 64 individual scalar values, one for each timepoint. - - However, it is still possible to send temporal batches of batch data. To do this the source data first must - be created as a single contiguous batch, and can then be partitioned using the `.partition()` helper on the - `ComponentBatch` objects. - - For example, to log 5 batches of 20 point clouds, first create a batch of 100 (20 * 5) point clouds and then - partition it into 5 batches of 20 point clouds: - ```py - times = np.arange(0, 5) - positions = rng.uniform(-5, 5, size=[100, 3]) - - rr.send_columns( - "points", - times=[rr.TimeSequenceColumn("step", times)], - components=[ - rr.Points3D.indicator(), - rr.components.Position3DBatch(positions).partition([20, 20, 20, 20, 20]), - ], - ) - ``` - In the viewer this will show up as 5 individual point clouds, one for each timepoint. - - Parameters - ---------- - entity_path: - Path to the entity in the space hierarchy. - - See for more on entity paths. - times: - The time values of this batch of data. Each `TimeColumnLike` object represents a single column - of timestamps. Generally, you should use one of the provided classes: [`TimeSequenceColumn`][rerun.TimeSequenceColumn], - [`TimeSecondsColumn`][rerun.TimeSecondsColumn], or [`TimeNanosColumn`][rerun.TimeNanosColumn]. - components: - The columns of components to log. Each object represents a single column of data. - - If a batch of components is passed, it will be partitioned with one element per timepoint. - In order to send multiple components per time value, explicitly create a [`ComponentColumn`][rerun.ComponentColumn] - either by constructing it directly, or by calling the `.partition()` method on a `ComponentBatch` type. - recording: - Specifies the [`rerun.RecordingStream`][] to use. - If left unspecified, defaults to the current active data recording, if there is one. - See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. - strict: - If True, raise exceptions on non-loggable data. - If False, warn on non-loggable data. - if None, use the global default from `rerun.strict_mode()` - - """ - expected_length = None - - timelines_args = {} - for t in times: - timeline_name = t.timeline_name() - time_column = t.as_arrow_array() - if expected_length is None: - expected_length = len(time_column) - elif len(time_column) != expected_length: - raise ValueError( - f"All times and components in a column must have the same length. Expected length: {expected_length} but got: {len(time_column)} for timeline: {timeline_name}" - ) - - timelines_args[timeline_name] = time_column - - indicators = [] - - components_args: dict[ComponentDescriptor, pa.Array] = {} - for c in components: - if isinstance(c, IndicatorComponentBatch): - indicators.append(c) - continue - component_descr = c.component_descriptor() - - if isinstance(c, ComponentColumn): - component_column = c - elif isinstance(c, ComponentBatchMixin): - component_column = c.partition([1] * len(c)) # type: ignore[arg-type] - else: - raise TypeError( - f"Expected either a type that implements the `ComponentMixin` or a `ComponentColumn`, got: {type(c)}" - ) - arrow_list_array = component_column.as_arrow_array() - - if expected_length is None: - expected_length = len(arrow_list_array) - elif len(arrow_list_array) != expected_length: - raise ValueError( - f"All times and components in a batch must have the same length. Expected length: {expected_length} but got: {len(arrow_list_array)} for component: {component_descr}" - ) - - components_args[component_descr] = arrow_list_array - - for i in indicators: - if expected_length is None: - expected_length = 1 - - components_args[i.component_descriptor()] = pa.nulls(expected_length, type=pa.null()) - - bindings.send_arrow_chunk( - entity_path, - timelines={t.timeline_name(): t.as_arrow_array() for t in times}, - components=components_args, - recording=recording.to_native() if recording is not None else None, - ) - - -@catch_and_log_exceptions() -def send_columns_v2( entity_path: str, indexes: Iterable[TimeColumnLike], columns: Iterable[ComponentColumn], diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index 4d022fedb5c2a..8f1895bd90ca2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -36,8 +36,6 @@ class AssetVideo(AssetVideoExt, Archetype): -------- ### Video with automatically determined frames: ```python - # TODO(#7298): ⚠️ Video is currently only supported in the Rerun web viewer. - import sys import rerun as rr @@ -58,8 +56,8 @@ class AssetVideo(AssetVideoExt, Archetype): rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. - times=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], - components=[rr.VideoFrameReference.indicator(), rr.components.VideoTimestamp.nanoseconds(frame_timestamps_ns)], + indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], + columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index 04ec5bd6f5378..ea1f29ee05948 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -116,7 +116,7 @@ class Points3D(Points3DExt, Archetype): colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] - rr.send_columns_v2( + rr.send_columns( "points", indexes=[rr.TimeSecondsColumn("time", times)], columns=[ diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index ba0cba02fbfbf..ca0a0374231a3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -71,7 +71,7 @@ class Scalar(Archetype): times = np.arange(0, 64) scalars = np.sin(times / 10.0) - rr.send_columns_v2( + rr.send_columns( "scalars", indexes=[rr.TimeSequenceColumn("step", times)], columns=rr.Scalar.columns(scalar=scalars), diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index 7bb69322323f0..45edb81db5dc4 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -34,8 +34,6 @@ class VideoFrameReference(VideoFrameReferenceExt, Archetype): -------- ### Video with automatically determined frames: ```python - # TODO(#7298): ⚠️ Video is currently only supported in the Rerun web viewer. - import sys import rerun as rr @@ -56,8 +54,8 @@ class VideoFrameReference(VideoFrameReferenceExt, Archetype): rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. - times=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], - components=[rr.VideoFrameReference.indicator(), rr.components.VideoTimestamp.nanoseconds(frame_timestamps_ns)], + indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], + columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference_ext.py index 864e7c1afc785..114d137f90616 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference_ext.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference_ext.py @@ -2,7 +2,11 @@ from typing import Any +import numpy as np +import numpy.typing as npt + from .. import components, datatypes +from .._baseclasses import ComponentColumnList from ..error_utils import _send_warning_or_raise, catch_and_log_exceptions @@ -67,3 +71,60 @@ def __init__( return self.__attrs_clear__() + + @classmethod + def columns_seconds( + cls, + seconds: npt.ArrayLike, + ) -> ComponentColumnList: + """ + Helper for `VideoFrameReference.columns` with seconds-based `timestamp`. + + Parameters + ---------- + seconds: + Timestamp values in seconds since video start. + + """ + from .. import VideoFrameReference + + nanoseconds = np.asarray(seconds, dtype=np.int64) * int(1e9) + return VideoFrameReference.columns(timestamp=nanoseconds) + + @classmethod + def columns_milliseconds( + cls, + milliseconds: npt.ArrayLike, + ) -> ComponentColumnList: + """ + Helper for `VideoFrameReference.columns` with milliseconds-based `timestamp`. + + Parameters + ---------- + milliseconds: + Timestamp values in milliseconds since video start. + + """ + from .. import VideoFrameReference + + nanoseconds = np.asarray(milliseconds, dtype=np.int64) * int(1e6) + return VideoFrameReference.columns(timestamp=nanoseconds) + + @classmethod + def columns_nanoseconds( + cls, + nanoseconds: npt.ArrayLike, + ) -> ComponentColumnList: + """ + Helper for `VideoFrameReference.columns` with nanoseconds-based `timestamp`. + + Parameters + ---------- + nanoseconds: + Timestamp values in nanoseconds since video start. + + """ + from .. import VideoFrameReference + + nanoseconds = np.asarray(nanoseconds, dtype=np.int64) + return VideoFrameReference.columns(timestamp=nanoseconds) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py b/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py index 1228f3e7fd40f..52a4ef07230cf 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py @@ -63,10 +63,7 @@ def __hash__(self) -> int: else: VideoTimestampLike = Any -VideoTimestampArrayLike = Union[ - VideoTimestamp, - Sequence[VideoTimestampLike], -] +VideoTimestampArrayLike = Union[VideoTimestamp, Sequence[VideoTimestampLike], npt.NDArray[np.int64]] class VideoTimestampBatch(BaseBatch[VideoTimestampArrayLike]): diff --git a/tests/python/chunk_zoo/chunk_zoo.py b/tests/python/chunk_zoo/chunk_zoo.py index 50867a6e41af5..1dc93bc42db37 100644 --- a/tests/python/chunk_zoo/chunk_zoo.py +++ b/tests/python/chunk_zoo/chunk_zoo.py @@ -33,39 +33,17 @@ def set_frame_time(t: int) -> None: def specimen_two_rows_span_two_chunks(): """Two rows spanning two chunks.""" - rr.send_columns( - "/rows_span_two_chunks", - frame_times(0, 2), - [ - rrc.Position2DBatch([(0, 1), (2, 3)]), - ], - ) - rr.send_columns( - "/rows_span_two_chunks", - frame_times(0, 2), - [ - rrc.RadiusBatch([10, 11]), - ], - ) + rr.send_columns("/rows_span_two_chunks", frame_times(0, 2), rr.Points2D.columns(positions=[(0, 1), (2, 3)])) + rr.send_columns("/rows_span_two_chunks", frame_times(0, 2), rr.Points2D.columns(radii=[10, 11])) def specimen_two_rows_span_two_chunks_sparse(): """Two rows spanning two chunks with partially matching timestamps (so sparse results).""" rr.send_columns( - "/rows_span_two_chunks_sparse", - frame_times(0, 2, 3), - [ - rrc.Position2DBatch([(0, 1), (2, 3), (4, 5)]), - ], - ) - rr.send_columns( - "/rows_span_two_chunks_sparse", - frame_times(0, 2, 4), - [ - rrc.RadiusBatch([10, 11, 12]), - ], + "/rows_span_two_chunks_sparse", frame_times(0, 2, 3), rr.Points2D.columns(positions=[(0, 1), (2, 3), (4, 5)]) ) + rr.send_columns("/rows_span_two_chunks_sparse", frame_times(0, 2, 4), rr.Points2D.columns(radii=[10, 11, 12])) def specimen_archetype_with_clamp_join_semantics(): @@ -74,9 +52,8 @@ def specimen_archetype_with_clamp_join_semantics(): "/archetype_with_clamp_join_semantics", frame_times(0), [ - rrc.Position2DBatch([(i, i) for i in range(10)]).partition([10]), - rrc.RadiusBatch([2]), - rr.Points2D.indicator(), + *rr.Points2D.columns(positions=[(i, i) for i in range(10)], _lengths=[10]), + *rr.Points2D.columns(radii=2), ], ) @@ -86,10 +63,7 @@ def specimen_archetype_with_latest_at_semantics(): rr.send_columns( "/archetype_chunk_with_latest_at_semantics", frame_times(range(10)), - [ - rrc.Position2DBatch([(i, i) for i in range(10)]), - rrc.ClassIdBatch(range(10)), - ], + rr.Points2D.columns(positions=[(i, i) for i in range(10)], class_ids=range(10)), ) set_frame_time(0) @@ -104,18 +78,13 @@ def specimen_archetype_with_clamp_join_semantics_two_chunks(): rr.send_columns( "/archetype_with_clamp_join_semantics_two_batches", frame_times(0), - [ - rrc.Position2DBatch([(i, i) for i in range(10)]).partition([10]), - ], + rr.Points2D.columns(positions=[(i, i) for i in range(10)], _lengths=[10]), ) rr.send_columns( "/archetype_with_clamp_join_semantics_two_batches", frame_times(0), - [ - rrc.RadiusBatch([2]), - rr.Points2D.indicator(), - ], + rr.Points2D.columns(radii=2), ) @@ -125,10 +94,12 @@ def specimen_archetype_without_clamp_join_semantics(): "/archetype_without_clamp_join_semantics", frame_times(0), [ - rrc.Position3DBatch([(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)]).partition([4]), - rrc.TriangleIndicesBatch([(0, 1, 2), (0, 2, 3)]).partition([2]), - rrc.ColorBatch([(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0)]).partition([4]), - rr.Mesh3D.indicator(), + *rr.Mesh3D.columns( + vertex_positions=[(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)], + vertex_colors=[(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0)], + _lengths=[4], + ), + *rr.Mesh3D.columns(triangle_indices=[(0, 1, 2), (0, 2, 3)], _lengths=[2]), ], ) @@ -157,8 +128,8 @@ def specimen_many_rows_with_mismatched_instance_count(): "/many_rows_with_mismatched_instance_count", frame_times(range(len(positions_partitions))), [ - rrc.Position2DBatch(positions).partition(positions_partitions), - rrc.ColorBatch(colors).partition(colors_partitions), + *rr.Points2D.columns(positions=positions, _lengths=positions_partitions), + *rr.Points2D.columns(colors=colors, _lengths=colors_partitions), ], ) rr.log("/many_rows_with_mismatched_instance_count", [rr.Points2D.indicator()], static=True) @@ -170,16 +141,12 @@ def specimen_scalars_interlaced_in_two_chunks(): rr.send_columns( "/scalars_interlaced_in_two_chunks", frame_times(0, 2, 5, 6, 8), - [ - rrc.ScalarBatch([0, 2, 5, 6, 8]), - ], + rr.Scalar.columns(scalar=[0, 2, 5, 6, 8]), ) rr.send_columns( "/scalars_interlaced_in_two_chunks", frame_times(1, 3, 7), - [ - rrc.ScalarBatch([1, 3, 7]), - ], + rr.Scalar.columns(scalar=[1, 3, 7]), ) @@ -188,10 +155,7 @@ def specimen_archetype_chunk_with_clear(): rr.send_columns( "/archetype_chunk_with_clear", frame_times(range(10)), - [ - rrc.Position2DBatch([(i, i) for i in range(10)]), - rrc.ClassIdBatch(range(10)), - ], + rr.Points2D.columns(positions=[(i, i) for i in range(10)], class_ids=range(10)), ) set_frame_time(0) diff --git a/tests/python/chunked_video/chunked_video.py b/tests/python/chunked_video/chunked_video.py index f54d9f86504c7..7f9263b3f7213 100644 --- a/tests/python/chunked_video/chunked_video.py +++ b/tests/python/chunked_video/chunked_video.py @@ -51,11 +51,8 @@ def main() -> None: rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. - times=[rr.TimeNanosColumn("video_time", frame_timestamps_ns + last_time_ns)], - components=[ - rr.VideoFrameReference.indicator(), - rr.components.VideoTimestamp.nanoseconds(frame_timestamps_ns), - ], + indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns + last_time_ns)], + columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) last_time_ns += frame_timestamps_ns[-1] diff --git a/tests/python/log_benchmark/test_log_benchmark.py b/tests/python/log_benchmark/test_log_benchmark.py index a54d53ed59d11..d9d0b8b0245ea 100644 --- a/tests/python/log_benchmark/test_log_benchmark.py +++ b/tests/python/log_benchmark/test_log_benchmark.py @@ -51,7 +51,7 @@ def log_image(image: np.ndarray, num_log_calls: int) -> None: # create a new, empty memory sink for the current recording rr.memory_recording() - for i in range(num_log_calls): + for _ in range(num_log_calls): rr.log("test_image", rr.Tensor(image)) @@ -96,13 +96,12 @@ def test_bench_transforms_over_time_batched( rr.send_columns( "test_transform", - times=[rr.TimeSequenceBatch("frame", times)], - components=[ - rr.Transform3D.indicator(), - rr.components.Translation3DBatch(rand_trans[start:end]), - rr.components.RotationQuatBatch(rand_quats[start:end]), - rr.components.Scale3DBatch(rand_scales[start:end]), - ], + indexes=[rr.TimeSequenceColumn("frame", times)], + columns=rr.Transform3D.columns( + translation=rand_trans[start:end], + quaternion=rand_quats[start:end], + scale=rand_scales[start:end], + ), ) diff --git a/tests/python/plot_dashboard_stress/main.py b/tests/python/plot_dashboard_stress/main.py index 0e0b2876dd727..6f08cd8ea5dd0 100755 --- a/tests/python/plot_dashboard_stress/main.py +++ b/tests/python/plot_dashboard_stress/main.py @@ -182,11 +182,10 @@ def main() -> None: rr.log(f"{plot_path}/{series_path}", rr.Scalar(value)) else: value_index = slice(index, index + args.temporal_batch_size) - value_batch = rr.components.ScalarBatch(values[value_index, plot_idx, series_idx]) rr.send_columns( f"{plot_path}/{series_path}", - times=[time_column], - components=[value_batch], + indexes=[time_column], + columns=rr.Scalar.columns(scalar=values[value_index, plot_idx, series_idx]), ) # Measure how long this took and how high the load was. diff --git a/tests/python/release_checklist/check_drag_and_drop_selection.py b/tests/python/release_checklist/check_drag_and_drop_selection.py index 1c1f90ce5fcc3..90b8754aef4bb 100644 --- a/tests/python/release_checklist/check_drag_and_drop_selection.py +++ b/tests/python/release_checklist/check_drag_and_drop_selection.py @@ -59,7 +59,7 @@ def log_some_scalar_entities() -> None: time_column = rr.TimeSequenceColumn("frame", times) for path, curve in curves: - rr.send_columns(path, times=[time_column], components=[rr.components.ScalarBatch(curve)]) + rr.send_columns(path, indexes=[time_column], columns=rr.Scalar.columns(scalar=curve)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_entity_drag_and_drop.py b/tests/python/release_checklist/check_entity_drag_and_drop.py index 85439d8cf03bc..f05d9ded543be 100644 --- a/tests/python/release_checklist/check_entity_drag_and_drop.py +++ b/tests/python/release_checklist/check_entity_drag_and_drop.py @@ -75,7 +75,7 @@ def log_some_scalar_entities() -> None: time_column = rr.TimeSequenceColumn("frame", times) for path, curve in curves: - rr.send_columns(path, times=[time_column], components=[rr.components.ScalarBatch(curve)]) + rr.send_columns(path, indexes=[time_column], columns=rr.Scalar.columns(scalar=curve)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_multi_entity_drag_and_drop.py b/tests/python/release_checklist/check_multi_entity_drag_and_drop.py index e541458b38818..8a51ba07f2e70 100644 --- a/tests/python/release_checklist/check_multi_entity_drag_and_drop.py +++ b/tests/python/release_checklist/check_multi_entity_drag_and_drop.py @@ -40,7 +40,7 @@ def log_some_scalar_entities() -> None: time_column = rr.TimeSequenceColumn("frame", times) for path, curve in curves: - rr.send_columns(path, times=[time_column], components=[rr.components.ScalarBatch(curve)]) + rr.send_columns(path, indexes=[time_column], columns=rr.Scalar.columns(scalar=curve)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_video.py b/tests/python/release_checklist/check_video.py index 8ccfe072e5fb8..0307a1ae960bb 100644 --- a/tests/python/release_checklist/check_video.py +++ b/tests/python/release_checklist/check_video.py @@ -41,11 +41,8 @@ def run(args: Namespace) -> None: rr.send_columns( codec, # Note timeline values don't have to be the same as the video timestamps. - times=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], - components=[ - rr.VideoFrameReference.indicator(), - rr.components.VideoTimestamp.nanoseconds(frame_timestamps_ns), - ], + indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], + columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) # Use the av1 also in a 3D context From c8d00f2ceb76e5b8254221b8bf01c80fb81c82cb Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 28 Jan 2025 12:11:09 +0100 Subject: [PATCH 18/43] Python: updated partial APIs naming (#8826) * `update_fields(clear: bool, ...)` -> `from_fields(clear_unset: bool, ...)` * `clear_fields()` -> `cleared()` * `cleared()` is not implemented by forwarding to `from_fields(clear_unset=True)` This does not cover implementing the constructors in terms of `from_fields()`. If that happens at all, this will be in one or more follow-ups. --- * Part of https://github.com/rerun-io/rerun/issues/8822 --- .../src/codegen/python/mod.rs | 27 ++++---------- .../all/archetypes/mesh3d_partial_updates.py | 2 +- .../archetypes/points3d_partial_updates.py | 4 +-- .../archetypes/transform3d_partial_updates.py | 8 ++--- docs/snippets/all/tutorials/data_out.py | 2 +- .../air_traffic_data/air_traffic_data.py | 6 ++-- .../detect_and_track_objects.py | 2 +- examples/python/drone_lidar/drone_lidar.py | 4 +-- .../incremental_logging.py | 8 ++--- .../rerun/archetypes/annotation_context.py | 16 ++++----- .../rerun_sdk/rerun/archetypes/arrows2d.py | 23 ++++-------- .../rerun_sdk/rerun/archetypes/arrows3d.py | 22 ++++-------- .../rerun_sdk/rerun/archetypes/asset3d.py | 18 ++++------ .../rerun_sdk/rerun/archetypes/asset_video.py | 17 ++++----- .../rerun_sdk/rerun/archetypes/bar_chart.py | 17 ++++----- .../rerun_sdk/rerun/archetypes/boxes2d.py | 23 ++++-------- .../rerun_sdk/rerun/archetypes/boxes3d.py | 25 ++++--------- .../rerun_sdk/rerun/archetypes/capsules3d.py | 24 ++++--------- rerun_py/rerun_sdk/rerun/archetypes/clear.py | 14 +++----- .../rerun_sdk/rerun/archetypes/depth_image.py | 22 ++++-------- .../rerun/archetypes/ellipsoids3d.py | 25 ++++--------- .../rerun/archetypes/encoded_image.py | 19 ++++------ .../rerun/archetypes/geo_line_strings.py | 18 ++++------ .../rerun_sdk/rerun/archetypes/geo_points.py | 19 ++++------ .../rerun_sdk/rerun/archetypes/graph_edges.py | 17 ++++----- .../rerun_sdk/rerun/archetypes/graph_nodes.py | 21 ++++------- rerun_py/rerun_sdk/rerun/archetypes/image.py | 19 ++++------ .../rerun/archetypes/instance_poses3d.py | 20 ++++------- .../rerun/archetypes/line_strips2d.py | 22 ++++-------- .../rerun/archetypes/line_strips3d.py | 21 ++++------- rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py | 24 ++++--------- .../rerun_sdk/rerun/archetypes/pinhole.py | 19 ++++------ .../rerun_sdk/rerun/archetypes/points2d.py | 23 ++++-------- .../rerun_sdk/rerun/archetypes/points3d.py | 22 ++++-------- rerun_py/rerun_sdk/rerun/archetypes/scalar.py | 16 ++++----- .../rerun/archetypes/segmentation_image.py | 19 ++++------ .../rerun_sdk/rerun/archetypes/series_line.py | 19 ++++------ .../rerun/archetypes/series_point.py | 19 ++++------ rerun_py/rerun_sdk/rerun/archetypes/tensor.py | 17 ++++----- .../rerun/archetypes/text_document.py | 17 ++++----- .../rerun_sdk/rerun/archetypes/text_log.py | 18 ++++------ .../rerun_sdk/rerun/archetypes/transform3d.py | 22 ++++-------- .../rerun/archetypes/video_frame_reference.py | 17 ++++----- .../rerun/archetypes/view_coordinates.py | 16 ++++----- .../rerun/blueprint/archetypes/background.py | 17 ++++----- .../archetypes/container_blueprint.py | 23 ++++-------- .../blueprint/archetypes/dataframe_query.py | 20 ++++------- .../blueprint/archetypes/force_center.py | 17 ++++----- .../archetypes/force_collision_radius.py | 18 ++++------ .../rerun/blueprint/archetypes/force_link.py | 18 ++++------ .../blueprint/archetypes/force_many_body.py | 17 ++++----- .../blueprint/archetypes/force_position.py | 18 ++++------ .../rerun/blueprint/archetypes/line_grid3d.py | 20 ++++------- .../blueprint/archetypes/map_background.py | 16 ++++----- .../rerun/blueprint/archetypes/map_zoom.py | 16 ++++----- .../blueprint/archetypes/near_clip_plane.py | 16 ++++----- .../blueprint/archetypes/panel_blueprint.py | 16 ++++----- .../rerun/blueprint/archetypes/plot_legend.py | 17 ++++----- .../rerun/blueprint/archetypes/scalar_axis.py | 17 ++++----- .../archetypes/tensor_scalar_mapping.py | 18 ++++------ .../archetypes/tensor_slice_selection.py | 19 ++++------ .../blueprint/archetypes/tensor_view_fit.py | 16 ++++----- .../blueprint/archetypes/view_blueprint.py | 19 ++++------ .../blueprint/archetypes/view_contents.py | 16 ++++----- .../archetypes/viewport_blueprint.py | 20 ++++------- .../archetypes/visible_time_ranges.py | 16 ++++----- .../blueprint/archetypes/visual_bounds2d.py | 16 ++++----- .../test_types/archetypes/affix_fuzzer1.py | 35 +++---------------- .../test_types/archetypes/affix_fuzzer2.py | 32 +++-------------- .../test_types/archetypes/affix_fuzzer3.py | 31 +++------------- .../test_types/archetypes/affix_fuzzer4.py | 31 +++------------- 71 files changed, 391 insertions(+), 897 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/python/mod.rs b/crates/build/re_types_builder/src/codegen/python/mod.rs index 7fcbd82ec0ccb..0c87fe0ffe30d 100644 --- a/crates/build/re_types_builder/src/codegen/python/mod.rs +++ b/crates/build/re_types_builder/src/codegen/python/mod.rs @@ -2537,7 +2537,7 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj doc_string_lines.push("\n".to_owned()); doc_string_lines.push("Parameters".to_owned()); doc_string_lines.push("----------".to_owned()); - doc_string_lines.push("clear:".to_owned()); + doc_string_lines.push("clear_unset:".to_owned()); doc_string_lines .push(" If true, all unspecified fields will be explicitly cleared.".to_owned()); for doc in parameter_docs { @@ -2546,24 +2546,13 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj }; let doc_block = indent::indent_by(12, quote_doc_lines(doc_string_lines)); - let field_clears = obj - .fields - .iter() - .map(|field| { - let field_name = field.snake_case_name(); - format!("{field_name}=[],") - }) - .collect_vec() - .join("\n"); - let field_clears = indent::indent_by(12, field_clears); - unindent(&format!( r#" @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, {parameters}, ) -> {name}: {doc_block} @@ -2573,7 +2562,7 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj {kwargs}, }} - if clear: + if clear_unset: kwargs = {{k: v if v is not None else [] for k, v in kwargs.items()}} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -2583,13 +2572,9 @@ fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Obj return inst @classmethod - def clear_fields(cls) -> {name}: + def cleared(cls) -> {name}: """Clear all the fields of a `{name}`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - {field_clears} - ) - return inst + return cls.from_fields(clear_unset=True) "# )) } diff --git a/docs/snippets/all/archetypes/mesh3d_partial_updates.py b/docs/snippets/all/archetypes/mesh3d_partial_updates.py index 8bc36153dcdca..1d74d1ff32e06 100644 --- a/docs/snippets/all/archetypes/mesh3d_partial_updates.py +++ b/docs/snippets/all/archetypes/mesh3d_partial_updates.py @@ -22,4 +22,4 @@ factors = np.abs(np.sin(np.arange(1, 300, dtype=np.float32) * 0.04)) for i, factor in enumerate(factors): rr.set_time_sequence("frame", i) - rr.log("triangle", rr.Mesh3D.update_fields(vertex_positions=vertex_positions * factor)) + rr.log("triangle", rr.Mesh3D.from_fields(vertex_positions=vertex_positions * factor)) diff --git a/docs/snippets/all/archetypes/points3d_partial_updates.py b/docs/snippets/all/archetypes/points3d_partial_updates.py index f97d4b766b06a..2e071f5a94ba5 100644 --- a/docs/snippets/all/archetypes/points3d_partial_updates.py +++ b/docs/snippets/all/archetypes/points3d_partial_updates.py @@ -14,7 +14,7 @@ radii = [0.6 if n < i else 0.2 for n in range(0, 10)] rr.set_time_sequence("frame", i) - rr.log("points", rr.Points3D.update_fields(radii=radii, colors=colors)) + rr.log("points", rr.Points3D.from_fields(radii=radii, colors=colors)) rr.set_time_sequence("frame", 20) -rr.log("points", rr.Points3D.update_fields(clear=True, positions=positions, radii=0.3)) +rr.log("points", rr.Points3D.from_fields(clear_unset=True, positions=positions, radii=0.3)) diff --git a/docs/snippets/all/archetypes/transform3d_partial_updates.py b/docs/snippets/all/archetypes/transform3d_partial_updates.py index fba4a436cd495..ab61babe62ae0 100644 --- a/docs/snippets/all/archetypes/transform3d_partial_updates.py +++ b/docs/snippets/all/archetypes/transform3d_partial_updates.py @@ -23,7 +23,7 @@ def truncated_radians(deg: float) -> float: rad = truncated_radians(deg * 4) rr.log( "box", - rr.Transform3D.update_fields( + rr.Transform3D.from_fields( # TODO(cmc): we should have access to all the fields of the extended constructor too. rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), @@ -33,7 +33,7 @@ def truncated_radians(deg: float) -> float: for t in range(51): rr.log( "box", - rr.Transform3D.update_fields(translation=[0, 0, t / 10.0]), + rr.Transform3D.from_fields(translation=[0, 0, t / 10.0]), ) # Update only the rotation of the box. @@ -41,7 +41,7 @@ def truncated_radians(deg: float) -> float: rad = truncated_radians((deg + 45) * 4) rr.log( "box", - rr.Transform3D.update_fields( + rr.Transform3D.from_fields( # TODO(cmc): we should have access to all the fields of the extended constructor too. rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), @@ -50,5 +50,5 @@ def truncated_radians(deg: float) -> float: # Clear all of the box's attributes, and reset its axis length. rr.log( "box", - rr.Transform3D.update_fields(clear=True, axis_length=15), + rr.Transform3D.from_fields(clear_unset=True, axis_length=15), ) diff --git a/docs/snippets/all/tutorials/data_out.py b/docs/snippets/all/tutorials/data_out.py index da003cdb2312e..b0a81fabd0ce5 100644 --- a/docs/snippets/all/tutorials/data_out.py +++ b/docs/snippets/all/tutorials/data_out.py @@ -38,7 +38,7 @@ # log a `Label` component to the face bounding box entity target_entity = "/video/detector/faces/0/bbox" -rr.log(target_entity, rr.Boxes2D.update_fields(show_labels=True), static=True) +rr.log(target_entity, rr.Boxes2D.from_fields(show_labels=True), static=True) rr.send_columns( target_entity, indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], diff --git a/examples/python/air_traffic_data/air_traffic_data.py b/examples/python/air_traffic_data/air_traffic_data.py index 5ce87efc8dbc0..294e2d3b2ea5c 100644 --- a/examples/python/air_traffic_data/air_traffic_data.py +++ b/examples/python/air_traffic_data/air_traffic_data.py @@ -318,12 +318,12 @@ def log_position_and_altitude(self, df: polars.DataFrame, icao_id: str) -> None: color = rr.components.Color.from_string(entity_path) rr.log( entity_path, - rr.Points3D.update_fields(colors=color), + rr.Points3D.from_fields(colors=color), # TODO(cmc): That would be UB right now (and doesn't matter as long as we are on the untagged index). - # rr.GeoPoints.update_fields(colors=color), + # rr.GeoPoints.from_fields(colors=color), static=True, ) - rr.log(entity_path + "/barometric_altitude", rr.SeriesLine.update_fields(color=color), static=True) + rr.log(entity_path + "/barometric_altitude", rr.SeriesLine.from_fields(color=color), static=True) self._position_indicators.add(icao_id) timestamps = rr.TimeSecondsColumn("unix_time", df["timestamp"].to_numpy()) diff --git a/examples/python/detect_and_track_objects/detect_and_track_objects.py b/examples/python/detect_and_track_objects/detect_and_track_objects.py index e609fd731b335..d08a615569c23 100755 --- a/examples/python/detect_and_track_objects/detect_and_track_objects.py +++ b/examples/python/detect_and_track_objects/detect_and_track_objects.py @@ -213,7 +213,7 @@ def log_tracked(self) -> None: ), ) else: - rr.log(f"video/tracked/{self.tracking_id}", rr.Boxes2D.clear_fields()) + rr.log(f"video/tracked/{self.tracking_id}", rr.Boxes2D.cleared()) def update_with_detection(self, detection: Detection, bgr: cv2.typing.MatLike) -> None: self.num_recent_undetected_frames = 0 diff --git a/examples/python/drone_lidar/drone_lidar.py b/examples/python/drone_lidar/drone_lidar.py index 36594fce8073f..6e5d047a810de 100644 --- a/examples/python/drone_lidar/drone_lidar.py +++ b/examples/python/drone_lidar/drone_lidar.py @@ -119,7 +119,7 @@ def log_lidar_data() -> None: rr.log( "/lidar", # negative radii are interpreted in UI units (instead of scene units) - rr.Points3D.update_fields(colors=(128, 128, 255), radii=-0.1), + rr.Points3D.from_fields(colors=(128, 128, 255), radii=-0.1), static=True, ) @@ -137,7 +137,7 @@ def log_drone_trajectory() -> None: rr.log( "/drone", - rr.Points3D.update_fields(colors=(255, 0, 0), radii=0.5), + rr.Points3D.from_fields(colors=(255, 0, 0), radii=0.5), static=True, ) diff --git a/examples/python/incremental_logging/incremental_logging.py b/examples/python/incremental_logging/incremental_logging.py index 26c707d224a50..37cf2cf34f070 100755 --- a/examples/python/incremental_logging/incremental_logging.py +++ b/examples/python/incremental_logging/incremental_logging.py @@ -23,7 +23,7 @@ # Only log colors and radii once. # Logging as static would also work (i.e. `static=True`). rr.set_time_sequence("frame_nr", 0) -rr.log("points", rr.Points3D.update_fields(colors=0xFF0000FF, radii=0.1)) +rr.log("points", rr.Points3D.from_fields(colors=0xFF0000FF, radii=0.1)) rng = default_rng(12345) @@ -32,7 +32,7 @@ # They will automatically re-use the colors and radii logged at the beginning. for i in range(10): rr.set_time_sequence("frame_nr", i) - rr.log("points", rr.Points3D.update_fields(positions=rng.uniform(-5, 5, size=[10, 3]))) + rr.log("points", rr.Points3D.from_fields(positions=rng.uniform(-5, 5, size=[10, 3]))) ``` Move the time cursor around, and notice how the colors and radii from frame 0 are still picked up by later frames, while the points themselves keep changing every frame. @@ -47,7 +47,7 @@ # Only log colors and radii once. # Logging as static would also work (i.e. `static=True`). rr.set_time_sequence("frame_nr", 0) -rr.log("points", rr.Points3D.update_fields(colors=0xFF0000FF, radii=0.1)) +rr.log("points", rr.Points3D.from_fields(colors=0xFF0000FF, radii=0.1)) rng = default_rng(12345) @@ -56,6 +56,6 @@ # They will automatically re-use the colors and radii logged at the beginning. for i in range(10): rr.set_time_sequence("frame_nr", i) - rr.log("points", rr.Points3D.update_fields(positions=rng.uniform(-5, 5, size=[10, 3]))) + rr.log("points", rr.Points3D.from_fields(positions=rng.uniform(-5, 5, size=[10, 3]))) rr.script_teardown(args) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py index 3a009614ed8a0..0dbc49759503f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py @@ -96,10 +96,10 @@ def _clear(cls) -> AnnotationContext: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, context: components.AnnotationContextLike | None = None, ) -> AnnotationContext: """ @@ -107,7 +107,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. context: List of class descriptions, mapping class indices to class names, colors etc. @@ -120,7 +120,7 @@ def update_fields( "context": context, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -130,13 +130,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> AnnotationContext: + def cleared(cls) -> AnnotationContext: """Clear all the fields of a `AnnotationContext`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - context=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py index 7091a03863e0e..67c699e5d1a66 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py @@ -79,10 +79,10 @@ def _clear(cls) -> Arrows2D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, vectors: datatypes.Vec2DArrayLike | None = None, origins: datatypes.Vec2DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, @@ -97,7 +97,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. vectors: All the vectors for each arrow in the batch. @@ -143,7 +143,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -153,20 +153,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Arrows2D: + def cleared(cls) -> Arrows2D: """Clear all the fields of a `Arrows2D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - vectors=[], - origins=[], - radii=[], - colors=[], - labels=[], - show_labels=[], - draw_order=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py index dd32eb582cc68..46fbb6b3908d2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py @@ -78,10 +78,10 @@ def _clear(cls) -> Arrows3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, vectors: datatypes.Vec3DArrayLike | None = None, origins: datatypes.Vec3DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, @@ -95,7 +95,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. vectors: All the vectors for each arrow in the batch. @@ -136,7 +136,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -146,19 +146,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Arrows3D: + def cleared(cls) -> Arrows3D: """Clear all the fields of a `Arrows3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - vectors=[], - origins=[], - radii=[], - colors=[], - labels=[], - show_labels=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py index b97a91e6b3149..a79de5417499f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py @@ -77,10 +77,10 @@ def _clear(cls) -> Asset3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, blob: datatypes.BlobLike | None = None, media_type: datatypes.Utf8Like | None = None, albedo_factor: datatypes.Rgba32Like | None = None, @@ -90,7 +90,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. blob: The asset's bytes. @@ -121,7 +121,7 @@ def update_fields( "albedo_factor": albedo_factor, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -131,15 +131,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Asset3D: + def cleared(cls) -> Asset3D: """Clear all the fields of a `Asset3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - blob=[], - media_type=[], - albedo_factor=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index 8f1895bd90ca2..cc562db11e5ea 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -131,10 +131,10 @@ def _clear(cls) -> AssetVideo: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, blob: datatypes.BlobLike | None = None, media_type: datatypes.Utf8Like | None = None, ) -> AssetVideo: @@ -143,7 +143,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. blob: The asset's bytes. @@ -165,7 +165,7 @@ def update_fields( "media_type": media_type, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -175,14 +175,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> AssetVideo: + def cleared(cls) -> AssetVideo: """Clear all the fields of a `AssetVideo`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - blob=[], - media_type=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py index a5967dcb63d6c..c2fd31202688f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py @@ -84,10 +84,10 @@ def _clear(cls) -> BarChart: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, values: datatypes.TensorDataLike | None = None, color: datatypes.Rgba32Like | None = None, ) -> BarChart: @@ -96,7 +96,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. values: The values. Should always be a 1-dimensional tensor (i.e. a vector). @@ -112,7 +112,7 @@ def update_fields( "color": color, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -122,14 +122,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> BarChart: + def cleared(cls) -> BarChart: """Clear all the fields of a `BarChart`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - values=[], - color=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index f4d1c2f42aab1..1a9d3544b18a6 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -70,10 +70,10 @@ def _clear(cls) -> Boxes2D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, half_sizes: datatypes.Vec2DArrayLike | None = None, centers: datatypes.Vec2DArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -88,7 +88,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. half_sizes: All half-extents that make up the batch of boxes. @@ -131,7 +131,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -141,20 +141,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Boxes2D: + def cleared(cls) -> Boxes2D: """Clear all the fields of a `Boxes2D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - half_sizes=[], - centers=[], - colors=[], - radii=[], - labels=[], - show_labels=[], - draw_order=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py index 8c87e43d4366c..a52824abe62f5 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py @@ -90,10 +90,10 @@ def _clear(cls) -> Boxes3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, half_sizes: datatypes.Vec3DArrayLike | None = None, centers: datatypes.Vec3DArrayLike | None = None, rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, @@ -110,7 +110,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. half_sizes: All half-extents that make up the batch of boxes. @@ -164,7 +164,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -174,22 +174,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Boxes3D: + def cleared(cls) -> Boxes3D: """Clear all the fields of a `Boxes3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - half_sizes=[], - centers=[], - rotation_axis_angles=[], - quaternions=[], - colors=[], - radii=[], - fill_mode=[], - labels=[], - show_labels=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py index 6ccebaf4cfbb2..451187d2c8050 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py @@ -103,10 +103,10 @@ def _clear(cls) -> Capsules3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, lengths: datatypes.Float32ArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, translations: datatypes.Vec3DArrayLike | None = None, @@ -122,7 +122,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. lengths: Lengths of the capsules, defined as the distance between the centers of the endcaps. @@ -170,7 +170,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -180,21 +180,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Capsules3D: + def cleared(cls) -> Capsules3D: """Clear all the fields of a `Capsules3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - lengths=[], - radii=[], - translations=[], - rotation_axis_angles=[], - quaternions=[], - colors=[], - labels=[], - show_labels=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/clear.py b/rerun_py/rerun_sdk/rerun/archetypes/clear.py index 4adc9f758a22b..aa3df34320738 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/clear.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/clear.py @@ -83,10 +83,10 @@ def _clear(cls) -> Clear: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, is_recursive: datatypes.BoolLike | None = None, ) -> Clear: """Update only some specific fields of a `Clear`.""" @@ -97,7 +97,7 @@ def update_fields( "is_recursive": is_recursive, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -107,13 +107,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Clear: + def cleared(cls) -> Clear: """Clear all the fields of a `Clear`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - is_recursive=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py index d31440c57ce9f..edc3caa9a0ab0 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py @@ -87,10 +87,10 @@ def _clear(cls) -> DepthImage: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, buffer: datatypes.BlobLike | None = None, format: datatypes.ImageFormatLike | None = None, meter: datatypes.Float32Like | None = None, @@ -104,7 +104,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. buffer: The raw depth image data. @@ -161,7 +161,7 @@ def update_fields( "draw_order": draw_order, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -171,19 +171,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> DepthImage: + def cleared(cls) -> DepthImage: """Clear all the fields of a `DepthImage`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - buffer=[], - format=[], - meter=[], - colormap=[], - depth_range=[], - point_fill_ratio=[], - draw_order=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py index dc06213618fb8..9c1cc1c9fadce 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py @@ -93,10 +93,10 @@ def _clear(cls) -> Ellipsoids3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, half_sizes: datatypes.Vec3DArrayLike | None = None, centers: datatypes.Vec3DArrayLike | None = None, rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, @@ -113,7 +113,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. half_sizes: For each ellipsoid, half of its size on its three axes. @@ -166,7 +166,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -176,22 +176,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Ellipsoids3D: + def cleared(cls) -> Ellipsoids3D: """Clear all the fields of a `Ellipsoids3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - half_sizes=[], - centers=[], - rotation_axis_angles=[], - quaternions=[], - colors=[], - line_radii=[], - fill_mode=[], - labels=[], - show_labels=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py index 89e54fac1c13f..fc5a335e6977c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py @@ -66,10 +66,10 @@ def _clear(cls) -> EncodedImage: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, blob: datatypes.BlobLike | None = None, media_type: datatypes.Utf8Like | None = None, opacity: datatypes.Float32Like | None = None, @@ -80,7 +80,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. blob: The encoded content of some image file, e.g. a PNG or JPEG. @@ -113,7 +113,7 @@ def update_fields( "draw_order": draw_order, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -123,16 +123,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> EncodedImage: + def cleared(cls) -> EncodedImage: """Clear all the fields of a `EncodedImage`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - blob=[], - media_type=[], - opacity=[], - draw_order=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py index f6197a784b449..5dcec3aca6194 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py @@ -80,10 +80,10 @@ def _clear(cls) -> GeoLineStrings: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, line_strings: components.GeoLineStringArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -93,7 +93,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. line_strings: The line strings, expressed in [EPSG:4326](https://epsg.io/4326) coordinates (North/East-positive degrees). @@ -118,7 +118,7 @@ def update_fields( "colors": colors, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -128,15 +128,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> GeoLineStrings: + def cleared(cls) -> GeoLineStrings: """Clear all the fields of a `GeoLineStrings`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - line_strings=[], - radii=[], - colors=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py index 64e455edafd4c..12448bdae4334 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py @@ -73,10 +73,10 @@ def _clear(cls) -> GeoPoints: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, positions: datatypes.DVec2DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -87,7 +87,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. positions: The [EPSG:4326](https://epsg.io/4326) coordinates for the points (North/East-positive degrees). @@ -116,7 +116,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -126,16 +126,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> GeoPoints: + def cleared(cls) -> GeoPoints: """Clear all the fields of a `GeoPoints`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - positions=[], - radii=[], - colors=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py index 30449bb1b0eb5..971521785ce39 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py @@ -92,10 +92,10 @@ def _clear(cls) -> GraphEdges: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, edges: datatypes.Utf8PairArrayLike | None = None, graph_type: components.GraphTypeLike | None = None, ) -> GraphEdges: @@ -104,7 +104,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. edges: A list of node tuples. @@ -122,7 +122,7 @@ def update_fields( "graph_type": graph_type, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -132,14 +132,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> GraphEdges: + def cleared(cls) -> GraphEdges: """Clear all the fields of a `GraphEdges`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - edges=[], - graph_type=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py index c69317e5e3eac..6fb1b80fafb60 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py @@ -116,10 +116,10 @@ def _clear(cls) -> GraphNodes: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, node_ids: datatypes.Utf8ArrayLike | None = None, positions: datatypes.Vec2DArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -132,7 +132,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. node_ids: A list of node IDs. @@ -160,7 +160,7 @@ def update_fields( "radii": radii, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -170,18 +170,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> GraphNodes: + def cleared(cls) -> GraphNodes: """Clear all the fields of a `GraphNodes`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - node_ids=[], - positions=[], - colors=[], - labels=[], - show_labels=[], - radii=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py index bb34b368324fc..676732732eec3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py @@ -110,10 +110,10 @@ def _clear(cls) -> Image: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, buffer: datatypes.BlobLike | None = None, format: datatypes.ImageFormatLike | None = None, opacity: datatypes.Float32Like | None = None, @@ -124,7 +124,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. buffer: The raw image data. @@ -150,7 +150,7 @@ def update_fields( "draw_order": draw_order, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -160,16 +160,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Image: + def cleared(cls) -> Image: """Clear all the fields of a `Image`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - buffer=[], - format=[], - opacity=[], - draw_order=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py index d6a65ff127cf1..d1eabfed421cc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py @@ -132,10 +132,10 @@ def _clear(cls) -> InstancePoses3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, translations: datatypes.Vec3DArrayLike | None = None, rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, quaternions: datatypes.QuaternionArrayLike | None = None, @@ -147,7 +147,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. translations: Translation vectors. @@ -172,7 +172,7 @@ def update_fields( "mat3x3": mat3x3, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -182,17 +182,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> InstancePoses3D: + def cleared(cls) -> InstancePoses3D: """Clear all the fields of a `InstancePoses3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - translations=[], - rotation_axis_angles=[], - quaternions=[], - scales=[], - mat3x3=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index f9298fc3bf283..1a227a10f75f3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -174,10 +174,10 @@ def _clear(cls) -> LineStrips2D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, strips: components.LineStrip2DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -191,7 +191,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. strips: All the actual 2D line strips that make up the batch. @@ -229,7 +229,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -239,19 +239,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> LineStrips2D: + def cleared(cls) -> LineStrips2D: """Clear all the fields of a `LineStrips2D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - strips=[], - radii=[], - colors=[], - labels=[], - show_labels=[], - draw_order=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py index 886f397ae6880..6d6c7eb87349e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py @@ -177,10 +177,10 @@ def _clear(cls) -> LineStrips3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, strips: components.LineStrip3DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -193,7 +193,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. strips: All the actual 3D line strips that make up the batch. @@ -226,7 +226,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -236,18 +236,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> LineStrips3D: + def cleared(cls) -> LineStrips3D: """Clear all the fields of a `LineStrips3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - strips=[], - radii=[], - colors=[], - labels=[], - show_labels=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py index 51d644bb3920f..9642cc8945ccb 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py @@ -125,10 +125,10 @@ def _clear(cls) -> Mesh3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, vertex_positions: datatypes.Vec3DArrayLike | None = None, triangle_indices: datatypes.UVec3DArrayLike | None = None, vertex_normals: datatypes.Vec3DArrayLike | None = None, @@ -144,7 +144,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. vertex_positions: The positions of each vertex. @@ -190,7 +190,7 @@ def update_fields( "class_ids": class_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -200,21 +200,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Mesh3D: + def cleared(cls) -> Mesh3D: """Clear all the fields of a `Mesh3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - vertex_positions=[], - triangle_indices=[], - vertex_normals=[], - vertex_colors=[], - vertex_texcoords=[], - albedo_factor=[], - albedo_texture_buffer=[], - albedo_texture_format=[], - class_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py index 1ee90beb91e1c..8dfb85e263489 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py @@ -93,10 +93,10 @@ def _clear(cls) -> Pinhole: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, image_from_camera: datatypes.Mat3x3Like | None = None, resolution: datatypes.Vec2DLike | None = None, camera_xyz: datatypes.ViewCoordinatesLike | None = None, @@ -107,7 +107,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. image_from_camera: Camera projection, from image coordinates to view coordinates. @@ -164,7 +164,7 @@ def update_fields( "image_plane_distance": image_plane_distance, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -174,16 +174,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Pinhole: + def cleared(cls) -> Pinhole: """Clear all the fields of a `Pinhole`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - image_from_camera=[], - resolution=[], - camera_xyz=[], - image_plane_distance=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index 2af4801c7e3bb..597b2f1f456a3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -124,10 +124,10 @@ def _clear(cls) -> Points2D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, positions: datatypes.Vec2DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -142,7 +142,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. positions: All the 2D positions at which the point cloud shows points. @@ -193,7 +193,7 @@ def update_fields( "keypoint_ids": keypoint_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -203,20 +203,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Points2D: + def cleared(cls) -> Points2D: """Clear all the fields of a `Points2D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - positions=[], - radii=[], - colors=[], - labels=[], - show_labels=[], - draw_order=[], - class_ids=[], - keypoint_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index ea1f29ee05948..93877ff3f4acc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -159,10 +159,10 @@ def _clear(cls) -> Points3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, positions: datatypes.Vec3DArrayLike | None = None, radii: datatypes.Float32ArrayLike | None = None, colors: datatypes.Rgba32ArrayLike | None = None, @@ -176,7 +176,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. positions: All the 3D positions at which the point cloud shows points. @@ -222,7 +222,7 @@ def update_fields( "keypoint_ids": keypoint_ids, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -232,19 +232,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Points3D: + def cleared(cls) -> Points3D: """Clear all the fields of a `Points3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - positions=[], - radii=[], - colors=[], - labels=[], - show_labels=[], - class_ids=[], - keypoint_ids=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index ca0a0374231a3..0935a5449b8a3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -120,10 +120,10 @@ def _clear(cls) -> Scalar: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, scalar: datatypes.Float64Like | None = None, ) -> Scalar: """ @@ -131,7 +131,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. scalar: The scalar value to log. @@ -144,7 +144,7 @@ def update_fields( "scalar": scalar, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -154,13 +154,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Scalar: + def cleared(cls) -> Scalar: """Clear all the fields of a `Scalar`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - scalar=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py index 1a15736d377f9..59069ba65891b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py @@ -82,10 +82,10 @@ def _clear(cls) -> SegmentationImage: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, buffer: datatypes.BlobLike | None = None, format: datatypes.ImageFormatLike | None = None, opacity: datatypes.Float32Like | None = None, @@ -96,7 +96,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. buffer: The raw image data. @@ -122,7 +122,7 @@ def update_fields( "draw_order": draw_order, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -132,16 +132,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> SegmentationImage: + def cleared(cls) -> SegmentationImage: """Clear all the fields of a `SegmentationImage`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - buffer=[], - format=[], - opacity=[], - draw_order=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index c2d8a4cc3c170..176c0d0c8d882 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -118,10 +118,10 @@ def _clear(cls) -> SeriesLine: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, color: datatypes.Rgba32Like | None = None, width: datatypes.Float32Like | None = None, name: datatypes.Utf8Like | None = None, @@ -132,7 +132,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. color: Color for the corresponding series. @@ -160,7 +160,7 @@ def update_fields( "aggregation_policy": aggregation_policy, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -170,16 +170,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> SeriesLine: + def cleared(cls) -> SeriesLine: """Clear all the fields of a `SeriesLine`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - color=[], - width=[], - name=[], - aggregation_policy=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index ccfd7d809ea4c..3cade8565bcb5 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -132,10 +132,10 @@ def _clear(cls) -> SeriesPoint: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, color: datatypes.Rgba32Like | None = None, marker: components.MarkerShapeLike | None = None, name: datatypes.Utf8Like | None = None, @@ -146,7 +146,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. color: Color for the corresponding series. @@ -170,7 +170,7 @@ def update_fields( "marker_size": marker_size, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -180,16 +180,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> SeriesPoint: + def cleared(cls) -> SeriesPoint: """Clear all the fields of a `SeriesPoint`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - color=[], - marker=[], - name=[], - marker_size=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py index 2e30eee8337c8..7920f6d050237 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py @@ -72,10 +72,10 @@ def _clear(cls) -> Tensor: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, data: datatypes.TensorDataLike | None = None, value_range: datatypes.Range1DLike | None = None, ) -> Tensor: @@ -84,7 +84,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. data: The tensor data @@ -110,7 +110,7 @@ def update_fields( "value_range": value_range, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -120,14 +120,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Tensor: + def cleared(cls) -> Tensor: """Clear all the fields of a `Tensor`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - data=[], - value_range=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py index 24c93d2a0e0a1..b223747a0fe9b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py @@ -132,10 +132,10 @@ def _clear(cls) -> TextDocument: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, text: datatypes.Utf8Like | None = None, media_type: datatypes.Utf8Like | None = None, ) -> TextDocument: @@ -144,7 +144,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. text: Contents of the text document. @@ -166,7 +166,7 @@ def update_fields( "media_type": media_type, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -176,14 +176,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> TextDocument: + def cleared(cls) -> TextDocument: """Clear all the fields of a `TextDocument`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - text=[], - media_type=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py index 099999bc45a99..076e4f286e622 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py @@ -101,10 +101,10 @@ def _clear(cls) -> TextLog: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, text: datatypes.Utf8Like | None = None, level: datatypes.Utf8Like | None = None, color: datatypes.Rgba32Like | None = None, @@ -114,7 +114,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. text: The body of the message. @@ -135,7 +135,7 @@ def update_fields( "color": color, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -145,15 +145,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> TextLog: + def cleared(cls) -> TextLog: """Clear all the fields of a `TextLog`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - text=[], - level=[], - color=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index 638f69854b81a..cc9ce26b45cb6 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -161,10 +161,10 @@ def _clear(cls) -> Transform3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, translation: datatypes.Vec3DLike | None = None, rotation_axis_angle: datatypes.RotationAxisAngleLike | None = None, quaternion: datatypes.QuaternionLike | None = None, @@ -178,7 +178,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. translation: Translation vector. @@ -212,7 +212,7 @@ def update_fields( "axis_length": axis_length, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -222,19 +222,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Transform3D: + def cleared(cls) -> Transform3D: """Clear all the fields of a `Transform3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - translation=[], - rotation_axis_angle=[], - quaternion=[], - scale=[], - mat3x3=[], - relation=[], - axis_length=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index 45edb81db5dc4..1151f796679de 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -129,10 +129,10 @@ def _clear(cls) -> VideoFrameReference: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, timestamp: datatypes.VideoTimestampLike | None = None, video_reference: datatypes.EntityPathLike | None = None, ) -> VideoFrameReference: @@ -141,7 +141,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. timestamp: References the closest video frame to this timestamp. @@ -172,7 +172,7 @@ def update_fields( "video_reference": video_reference, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -182,14 +182,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> VideoFrameReference: + def cleared(cls) -> VideoFrameReference: """Clear all the fields of a `VideoFrameReference`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - timestamp=[], - video_reference=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 4627eb8bb1037..754e6cd15b887 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -98,10 +98,10 @@ def _clear(cls) -> ViewCoordinates: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, xyz: datatypes.ViewCoordinatesLike | None = None, ) -> ViewCoordinates: """ @@ -109,7 +109,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. xyz: The directions of the [x, y, z] axes. @@ -122,7 +122,7 @@ def update_fields( "xyz": xyz, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -132,13 +132,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ViewCoordinates: + def cleared(cls) -> ViewCoordinates: """Clear all the fields of a `ViewCoordinates`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - xyz=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py index f2595b02b7e15..7bba8fd592da5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py @@ -39,10 +39,10 @@ def _clear(cls) -> Background: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, kind: blueprint_components.BackgroundKindLike | None = None, color: datatypes.Rgba32Like | None = None, ) -> Background: @@ -51,7 +51,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. kind: The type of the background. @@ -67,7 +67,7 @@ def update_fields( "color": color, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -77,14 +77,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> Background: + def cleared(cls) -> Background: """Clear all the fields of a `Background`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - kind=[], - color=[], - ) - return inst + return cls.from_fields(clear_unset=True) kind: blueprint_components.BackgroundKindBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py index e5970123ebae6..870bab5461215 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py @@ -111,10 +111,10 @@ def _clear(cls) -> ContainerBlueprint: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, container_kind: blueprint_components.ContainerKindLike | None = None, display_name: datatypes.Utf8Like | None = None, contents: datatypes.EntityPathArrayLike | None = None, @@ -129,7 +129,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. container_kind: The class of the view. @@ -179,7 +179,7 @@ def update_fields( "grid_columns": grid_columns, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -189,20 +189,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ContainerBlueprint: + def cleared(cls) -> ContainerBlueprint: """Clear all the fields of a `ContainerBlueprint`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - container_kind=[], - display_name=[], - contents=[], - col_shares=[], - row_shares=[], - active_tab=[], - visible=[], - grid_columns=[], - ) - return inst + return cls.from_fields(clear_unset=True) container_kind: blueprint_components.ContainerKindBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py index 5e41b02d27af1..4402ed7053d94 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py @@ -42,10 +42,10 @@ def _clear(cls) -> DataframeQuery: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, timeline: datatypes.Utf8Like | None = None, filter_by_range: blueprint_datatypes.FilterByRangeLike | None = None, filter_is_not_null: blueprint_datatypes.FilterIsNotNullLike | None = None, @@ -57,7 +57,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. timeline: The timeline for this query. @@ -86,7 +86,7 @@ def update_fields( "select": select, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -96,17 +96,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> DataframeQuery: + def cleared(cls) -> DataframeQuery: """Clear all the fields of a `DataframeQuery`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - timeline=[], - filter_by_range=[], - filter_is_not_null=[], - apply_latest_at=[], - select=[], - ) - return inst + return cls.from_fields(clear_unset=True) timeline: blueprint_components.TimelineNameBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py index f708724dbaa13..63e6ca730209a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py @@ -61,10 +61,10 @@ def _clear(cls) -> ForceCenter: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, enabled: datatypes.BoolLike | None = None, strength: datatypes.Float64Like | None = None, ) -> ForceCenter: @@ -73,7 +73,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. enabled: Whether the center force is enabled. @@ -91,7 +91,7 @@ def update_fields( "strength": strength, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -101,14 +101,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ForceCenter: + def cleared(cls) -> ForceCenter: """Clear all the fields of a `ForceCenter`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - enabled=[], - strength=[], - ) - return inst + return cls.from_fields(clear_unset=True) enabled: blueprint_components.EnabledBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py index 5c2e3f83d7e20..0bfd97ce2b457 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py @@ -70,10 +70,10 @@ def _clear(cls) -> ForceCollisionRadius: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, enabled: datatypes.BoolLike | None = None, strength: datatypes.Float64Like | None = None, iterations: datatypes.UInt64Like | None = None, @@ -83,7 +83,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. enabled: Whether the collision force is enabled. @@ -106,7 +106,7 @@ def update_fields( "iterations": iterations, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -116,15 +116,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ForceCollisionRadius: + def cleared(cls) -> ForceCollisionRadius: """Clear all the fields of a `ForceCollisionRadius`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - enabled=[], - strength=[], - iterations=[], - ) - return inst + return cls.from_fields(clear_unset=True) enabled: blueprint_components.EnabledBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py index f93e9c6fcf468..c797cde38bb97 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py @@ -70,10 +70,10 @@ def _clear(cls) -> ForceLink: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, enabled: datatypes.BoolLike | None = None, distance: datatypes.Float64Like | None = None, iterations: datatypes.UInt64Like | None = None, @@ -83,7 +83,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. enabled: Whether the link force is enabled. @@ -106,7 +106,7 @@ def update_fields( "iterations": iterations, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -116,15 +116,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ForceLink: + def cleared(cls) -> ForceLink: """Clear all the fields of a `ForceLink`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - enabled=[], - distance=[], - iterations=[], - ) - return inst + return cls.from_fields(clear_unset=True) enabled: blueprint_components.EnabledBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py index 34592296ee552..f2becef2f4e38 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py @@ -68,10 +68,10 @@ def _clear(cls) -> ForceManyBody: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, enabled: datatypes.BoolLike | None = None, strength: datatypes.Float64Like | None = None, ) -> ForceManyBody: @@ -80,7 +80,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. enabled: Whether the many body force is enabled. @@ -101,7 +101,7 @@ def update_fields( "strength": strength, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -111,14 +111,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ForceManyBody: + def cleared(cls) -> ForceManyBody: """Clear all the fields of a `ForceManyBody`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - enabled=[], - strength=[], - ) - return inst + return cls.from_fields(clear_unset=True) enabled: blueprint_components.EnabledBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py index e717533ffafef..e5d8742f6af08 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py @@ -68,10 +68,10 @@ def _clear(cls) -> ForcePosition: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, enabled: datatypes.BoolLike | None = None, strength: datatypes.Float64Like | None = None, position: datatypes.Vec2DLike | None = None, @@ -81,7 +81,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. enabled: Whether the position force is enabled. @@ -102,7 +102,7 @@ def update_fields( "position": position, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -112,15 +112,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ForcePosition: + def cleared(cls) -> ForcePosition: """Clear all the fields of a `ForcePosition`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - enabled=[], - strength=[], - position=[], - ) - return inst + return cls.from_fields(clear_unset=True) enabled: blueprint_components.EnabledBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py index 185931a38ed35..ab13c16be6a48 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py @@ -86,10 +86,10 @@ def _clear(cls) -> LineGrid3D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, visible: datatypes.BoolLike | None = None, spacing: datatypes.Float32Like | None = None, plane: datatypes.Plane3DLike | None = None, @@ -101,7 +101,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. visible: Whether the grid is visible. @@ -138,7 +138,7 @@ def update_fields( "color": color, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -148,17 +148,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> LineGrid3D: + def cleared(cls) -> LineGrid3D: """Clear all the fields of a `LineGrid3D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - visible=[], - spacing=[], - plane=[], - stroke_width=[], - color=[], - ) - return inst + return cls.from_fields(clear_unset=True) visible: blueprint_components.VisibleBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py index a769a61eccce4..f435774bdb159 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py @@ -55,10 +55,10 @@ def _clear(cls) -> MapBackground: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, provider: blueprint_components.MapProviderLike | None = None, ) -> MapBackground: """ @@ -66,7 +66,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. provider: Map provider and style to use. @@ -81,7 +81,7 @@ def update_fields( "provider": provider, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -91,13 +91,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> MapBackground: + def cleared(cls) -> MapBackground: """Clear all the fields of a `MapBackground`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - provider=[], - ) - return inst + return cls.from_fields(clear_unset=True) provider: blueprint_components.MapProviderBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py index c299108f602f8..ab24360333526 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py @@ -56,10 +56,10 @@ def _clear(cls) -> MapZoom: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, zoom: datatypes.Float64Like | None = None, ) -> MapZoom: """ @@ -67,7 +67,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. zoom: Zoom level for the map. @@ -82,7 +82,7 @@ def update_fields( "zoom": zoom, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -92,13 +92,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> MapZoom: + def cleared(cls) -> MapZoom: """Clear all the fields of a `MapZoom`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - zoom=[], - ) - return inst + return cls.from_fields(clear_unset=True) zoom: blueprint_components.ZoomLevelBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py index dd4bf470bc5e8..ff0b64701e246 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py @@ -56,10 +56,10 @@ def _clear(cls) -> NearClipPlane: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, near_clip_plane: datatypes.Float32Like | None = None, ) -> NearClipPlane: """ @@ -67,7 +67,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. near_clip_plane: Controls the distance to the near clip plane in 3D scene units. @@ -82,7 +82,7 @@ def update_fields( "near_clip_plane": near_clip_plane, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -92,13 +92,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> NearClipPlane: + def cleared(cls) -> NearClipPlane: """Clear all the fields of a `NearClipPlane`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - near_clip_plane=[], - ) - return inst + return cls.from_fields(clear_unset=True) near_clip_plane: blueprint_components.NearClipPlaneBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py index 12ac91c7680bc..fb08133c30513 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py @@ -53,10 +53,10 @@ def _clear(cls) -> PanelBlueprint: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, state: blueprint_components.PanelStateLike | None = None, ) -> PanelBlueprint: """ @@ -64,7 +64,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. state: Current state of the panels. @@ -77,7 +77,7 @@ def update_fields( "state": state, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -87,13 +87,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> PanelBlueprint: + def cleared(cls) -> PanelBlueprint: """Clear all the fields of a `PanelBlueprint`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - state=[], - ) - return inst + return cls.from_fields(clear_unset=True) state: blueprint_components.PanelStateBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py index c035b1ba751af..fdee4f7ed747e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py @@ -39,10 +39,10 @@ def _clear(cls) -> PlotLegend: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, corner: blueprint_components.Corner2DLike | None = None, visible: datatypes.BoolLike | None = None, ) -> PlotLegend: @@ -51,7 +51,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. corner: To what corner the legend is aligned. @@ -71,7 +71,7 @@ def update_fields( "visible": visible, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -81,14 +81,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> PlotLegend: + def cleared(cls) -> PlotLegend: """Clear all the fields of a `PlotLegend`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - corner=[], - visible=[], - ) - return inst + return cls.from_fields(clear_unset=True) corner: blueprint_components.Corner2DBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py index 72ebe55abf4dd..0687af983f978 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py @@ -59,10 +59,10 @@ def _clear(cls) -> ScalarAxis: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, range: datatypes.Range1DLike | None = None, zoom_lock: datatypes.BoolLike | None = None, ) -> ScalarAxis: @@ -71,7 +71,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. range: The range of the axis. @@ -89,7 +89,7 @@ def update_fields( "zoom_lock": zoom_lock, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -99,14 +99,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ScalarAxis: + def cleared(cls) -> ScalarAxis: """Clear all the fields of a `ScalarAxis`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - range=[], - zoom_lock=[], - ) - return inst + return cls.from_fields(clear_unset=True) range: components.Range1DBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py index 3ac46c4cd514d..78a6ef8f86575 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py @@ -73,10 +73,10 @@ def _clear(cls) -> TensorScalarMapping: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, mag_filter: components.MagnificationFilterLike | None = None, colormap: components.ColormapLike | None = None, gamma: datatypes.Float32Like | None = None, @@ -86,7 +86,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. mag_filter: Filter used when zooming in on the tensor. @@ -113,7 +113,7 @@ def update_fields( "gamma": gamma, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -123,15 +123,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> TensorScalarMapping: + def cleared(cls) -> TensorScalarMapping: """Clear all the fields of a `TensorScalarMapping`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - mag_filter=[], - colormap=[], - gamma=[], - ) - return inst + return cls.from_fields(clear_unset=True) mag_filter: components.MagnificationFilterBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py index 8f940ff38a27f..ddb241492b0e6 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py @@ -80,10 +80,10 @@ def _clear(cls) -> TensorSliceSelection: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, width: datatypes.TensorDimensionSelectionLike | None = None, height: datatypes.TensorDimensionSelectionLike | None = None, indices: datatypes.TensorDimensionIndexSelectionArrayLike | None = None, @@ -94,7 +94,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. width: Which dimension to map to width. @@ -126,7 +126,7 @@ def update_fields( "slider": slider, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -136,16 +136,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> TensorSliceSelection: + def cleared(cls) -> TensorSliceSelection: """Clear all the fields of a `TensorSliceSelection`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - width=[], - height=[], - indices=[], - slider=[], - ) - return inst + return cls.from_fields(clear_unset=True) width: components.TensorWidthDimensionBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py index 17497eca5fd75..befe7178bfe23 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py @@ -37,10 +37,10 @@ def _clear(cls) -> TensorViewFit: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, scaling: blueprint_components.ViewFitLike | None = None, ) -> TensorViewFit: """ @@ -48,7 +48,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. scaling: How the image is scaled to fit the view. @@ -61,7 +61,7 @@ def update_fields( "scaling": scaling, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -71,13 +71,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> TensorViewFit: + def cleared(cls) -> TensorViewFit: """Clear all the fields of a `TensorViewFit`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - scaling=[], - ) - return inst + return cls.from_fields(clear_unset=True) scaling: blueprint_components.ViewFitBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py index 013cb30bd5fd1..05c9b750231a3 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py @@ -80,10 +80,10 @@ def _clear(cls) -> ViewBlueprint: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, class_identifier: datatypes.Utf8Like | None = None, display_name: datatypes.Utf8Like | None = None, space_origin: datatypes.EntityPathLike | None = None, @@ -94,7 +94,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. class_identifier: The class of the view. @@ -124,7 +124,7 @@ def update_fields( "visible": visible, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -134,16 +134,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ViewBlueprint: + def cleared(cls) -> ViewBlueprint: """Clear all the fields of a `ViewBlueprint`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - class_identifier=[], - display_name=[], - space_origin=[], - visible=[], - ) - return inst + return cls.from_fields(clear_unset=True) class_identifier: blueprint_components.ViewClassBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py index 2f9d6b2184faf..5ea20fbeabc89 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py @@ -95,10 +95,10 @@ def _clear(cls) -> ViewContents: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, query: datatypes.Utf8ArrayLike | None = None, ) -> ViewContents: """ @@ -106,7 +106,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. query: The `QueryExpression` that populates the contents for the view. @@ -121,7 +121,7 @@ def update_fields( "query": query, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -131,13 +131,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ViewContents: + def cleared(cls) -> ViewContents: """Clear all the fields of a `ViewContents`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - query=[], - ) - return inst + return cls.from_fields(clear_unset=True) query: blueprint_components.QueryExpressionBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py index 3fe08aea0b651..5afda719bc25b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py @@ -92,10 +92,10 @@ def _clear(cls) -> ViewportBlueprint: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, root_container: datatypes.UuidLike | None = None, maximized: datatypes.UuidLike | None = None, auto_layout: datatypes.BoolLike | None = None, @@ -107,7 +107,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. root_container: The layout of the views @@ -144,7 +144,7 @@ def update_fields( "past_viewer_recommendations": past_viewer_recommendations, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -154,17 +154,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> ViewportBlueprint: + def cleared(cls) -> ViewportBlueprint: """Clear all the fields of a `ViewportBlueprint`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - root_container=[], - maximized=[], - auto_layout=[], - auto_views=[], - past_viewer_recommendations=[], - ) - return inst + return cls.from_fields(clear_unset=True) root_container: blueprint_components.RootContainerBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py index 3101d9f5dfb53..764efe8d613f8 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py @@ -48,10 +48,10 @@ def _clear(cls) -> VisibleTimeRanges: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, ranges: datatypes.VisibleTimeRangeArrayLike | None = None, ) -> VisibleTimeRanges: """ @@ -59,7 +59,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. ranges: The time ranges to show for each timeline unless specified otherwise on a per-entity basis. @@ -74,7 +74,7 @@ def update_fields( "ranges": ranges, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -84,13 +84,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> VisibleTimeRanges: + def cleared(cls) -> VisibleTimeRanges: """Clear all the fields of a `VisibleTimeRanges`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - ranges=[], - ) - return inst + return cls.from_fields(clear_unset=True) ranges: blueprint_components.VisibleTimeRangeBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py index 16444fb54aa19..8e686a92b9022 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py @@ -46,10 +46,10 @@ def _clear(cls) -> VisualBounds2D: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, range: datatypes.Range2DLike | None = None, ) -> VisualBounds2D: """ @@ -57,7 +57,7 @@ def update_fields( Parameters ---------- - clear: + clear_unset: If true, all unspecified fields will be explicitly cleared. range: Controls the visible range of a 2D view. @@ -72,7 +72,7 @@ def update_fields( "range": range, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -82,13 +82,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> VisualBounds2D: + def cleared(cls) -> VisualBounds2D: """Clear all the fields of a `VisualBounds2D`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - range=[], - ) - return inst + return cls.from_fields(clear_unset=True) range: blueprint_components.VisualBounds2DBatch | None = field( metadata={"component": True}, diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py index 4fc7517a9d9b6..79ceb0c878b35 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py @@ -114,10 +114,10 @@ def _clear(cls) -> AffixFuzzer1: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, fuzz1001: datatypes.AffixFuzzer1Like | None = None, fuzz1002: datatypes.AffixFuzzer1Like | None = None, fuzz1003: datatypes.AffixFuzzer1Like | None = None, @@ -170,7 +170,7 @@ def update_fields( "fuzz1022": fuzz1022, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -180,34 +180,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> AffixFuzzer1: + def cleared(cls) -> AffixFuzzer1: """Clear all the fields of a `AffixFuzzer1`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - fuzz1001=[], - fuzz1002=[], - fuzz1003=[], - fuzz1004=[], - fuzz1005=[], - fuzz1006=[], - fuzz1007=[], - fuzz1008=[], - fuzz1009=[], - fuzz1010=[], - fuzz1011=[], - fuzz1012=[], - fuzz1013=[], - fuzz1014=[], - fuzz1015=[], - fuzz1016=[], - fuzz1017=[], - fuzz1018=[], - fuzz1019=[], - fuzz1020=[], - fuzz1021=[], - fuzz1022=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py index 6d26d193206af..8c0a406757f05 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py @@ -105,10 +105,10 @@ def _clear(cls) -> AffixFuzzer2: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, fuzz1101: datatypes.AffixFuzzer1ArrayLike | None = None, fuzz1102: datatypes.AffixFuzzer1ArrayLike | None = None, fuzz1103: datatypes.AffixFuzzer1ArrayLike | None = None, @@ -155,7 +155,7 @@ def update_fields( "fuzz1122": fuzz1122, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -165,31 +165,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> AffixFuzzer2: + def cleared(cls) -> AffixFuzzer2: """Clear all the fields of a `AffixFuzzer2`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - fuzz1101=[], - fuzz1102=[], - fuzz1103=[], - fuzz1104=[], - fuzz1105=[], - fuzz1106=[], - fuzz1107=[], - fuzz1108=[], - fuzz1109=[], - fuzz1110=[], - fuzz1111=[], - fuzz1112=[], - fuzz1113=[], - fuzz1114=[], - fuzz1115=[], - fuzz1116=[], - fuzz1117=[], - fuzz1118=[], - fuzz1122=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py index 4498bfa257672..a80bcc258c747 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py @@ -103,10 +103,10 @@ def _clear(cls) -> AffixFuzzer3: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, fuzz2001: datatypes.AffixFuzzer1Like | None = None, fuzz2002: datatypes.AffixFuzzer1Like | None = None, fuzz2003: datatypes.AffixFuzzer1Like | None = None, @@ -151,7 +151,7 @@ def update_fields( "fuzz2018": fuzz2018, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -161,30 +161,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> AffixFuzzer3: + def cleared(cls) -> AffixFuzzer3: """Clear all the fields of a `AffixFuzzer3`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - fuzz2001=[], - fuzz2002=[], - fuzz2003=[], - fuzz2004=[], - fuzz2005=[], - fuzz2006=[], - fuzz2007=[], - fuzz2008=[], - fuzz2009=[], - fuzz2010=[], - fuzz2011=[], - fuzz2012=[], - fuzz2013=[], - fuzz2014=[], - fuzz2015=[], - fuzz2016=[], - fuzz2017=[], - fuzz2018=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py index 57f86b92ba500..c82c67cff9762 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py @@ -103,10 +103,10 @@ def _clear(cls) -> AffixFuzzer4: return inst @classmethod - def update_fields( + def from_fields( cls, *, - clear: bool = False, + clear_unset: bool = False, fuzz2101: datatypes.AffixFuzzer1ArrayLike | None = None, fuzz2102: datatypes.AffixFuzzer1ArrayLike | None = None, fuzz2103: datatypes.AffixFuzzer1ArrayLike | None = None, @@ -151,7 +151,7 @@ def update_fields( "fuzz2118": fuzz2118, } - if clear: + if clear_unset: kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] inst.__attrs_init__(**kwargs) @@ -161,30 +161,9 @@ def update_fields( return inst @classmethod - def clear_fields(cls) -> AffixFuzzer4: + def cleared(cls) -> AffixFuzzer4: """Clear all the fields of a `AffixFuzzer4`.""" - inst = cls.__new__(cls) - inst.__attrs_init__( - fuzz2101=[], - fuzz2102=[], - fuzz2103=[], - fuzz2104=[], - fuzz2105=[], - fuzz2106=[], - fuzz2107=[], - fuzz2108=[], - fuzz2109=[], - fuzz2110=[], - fuzz2111=[], - fuzz2112=[], - fuzz2113=[], - fuzz2114=[], - fuzz2115=[], - fuzz2116=[], - fuzz2117=[], - fuzz2118=[], - ) - return inst + return cls.from_fields(clear_unset=True) @classmethod def columns( From fd5628ef0339f63dff8bda091141bab585b122c6 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Jan 2025 12:43:24 +0100 Subject: [PATCH 19/43] Use Arrow IPC to encode the column schema (#8821) ### Related * Part of https://github.com/rerun-io/rerun/issues/8744 * Sibling PR: https://github.com/rerun-io/dataplatform/pull/154 --- Cargo.lock | 11 +- Cargo.toml | 1 - crates/store/re_chunk_store/Cargo.toml | 8 - crates/store/re_chunk_store/src/dataframe.rs | 61 +- crates/store/re_chunk_store/src/lib.rs | 6 +- .../src/protobuf_conversions.rs | 163 +--- ..._query__tests__async_barebones_static.snap | 36 +- ...uery__tests__async_barebones_temporal.snap | 60 +- ..._dataframe__query__tests__barebones-2.snap | 60 +- ...re_dataframe__query__tests__barebones.snap | 36 +- .../re_dataframe__query__tests__clears-2.snap | 64 +- .../re_dataframe__query__tests__clears.snap | 64 +- ...e__query__tests__filtered_index_range.snap | 48 +- ...__query__tests__filtered_index_values.snap | 40 +- ..._query__tests__filtered_is_not_null-2.snap | 23 +- ..._query__tests__filtered_is_not_null-3.snap | 60 +- ..._query__tests__filtered_is_not_null-4.snap | 48 +- ...e__query__tests__filtered_is_not_null.snap | 23 +- ..._dataframe__query__tests__selection-2.snap | 55 +- ..._dataframe__query__tests__selection-3.snap | 58 +- ..._dataframe__query__tests__selection-4.snap | 20 +- ...__sparse_fill_strategy_latestatglobal.snap | 60 +- ...e__query__tests__using_index_values-2.snap | 60 +- ...ame__query__tests__using_index_values.snap | 60 +- ...aframe__query__tests__view_contents-2.snap | 47 +- ...ataframe__query__tests__view_contents.snap | 19 +- ...y__tests__view_contents_and_selection.snap | 48 +- crates/store/re_log_types/Cargo.toml | 1 - crates/store/re_log_types/src/lib.rs | 2 - .../re_log_types/src/protobuf_conversions.rs | 698 ------------------ crates/store/re_protos/Cargo.toml | 5 + crates/store/re_protos/README.md | 2 + .../re_protos/proto/rerun/v0/common.proto | 39 - .../proto/rerun/v0/remote_store.proto | 2 +- crates/store/re_protos/src/lib.rs | 3 +- .../src/protobuf_conversions/arrow.rs | 21 + .../src/protobuf_conversions/log_types.rs | 688 +++++++++++++++++ .../re_protos/src/protobuf_conversions/mod.rs | 3 + .../src/protobuf_conversions/tuid.rs | 25 + .../store/re_protos/src/v0/rerun.common.v0.rs | 89 --- .../re_protos/src/v0/rerun.remote_store.v0.rs | 4 +- crates/store/re_sorbet/src/chunk_batch.rs | 108 +++ crates/store/re_sorbet/src/column_schema.rs | 140 ++++ .../store/re_sorbet/src/data_column_schema.rs | 44 +- .../re_sorbet/src/index_column_schema.rs | 13 +- crates/store/re_sorbet/src/ipc.rs | 21 + crates/store/re_sorbet/src/lib.rs | 6 +- crates/utils/re_tuid/Cargo.toml | 1 - crates/utils/re_tuid/src/lib.rs | 2 - .../utils/re_tuid/src/protobuf_conversions.rs | 28 - rerun_py/Cargo.toml | 2 +- rerun_py/rerun_sdk/rerun/dataframe.py | 12 +- rerun_py/src/remote.rs | 17 +- rerun_py/tests/unit/test_dataframe.py | 8 + 54 files changed, 1564 insertions(+), 1659 deletions(-) delete mode 100644 crates/store/re_log_types/src/protobuf_conversions.rs create mode 100644 crates/store/re_protos/src/protobuf_conversions/arrow.rs create mode 100644 crates/store/re_protos/src/protobuf_conversions/log_types.rs create mode 100644 crates/store/re_protos/src/protobuf_conversions/mod.rs create mode 100644 crates/store/re_protos/src/protobuf_conversions/tuid.rs create mode 100644 crates/store/re_sorbet/src/chunk_batch.rs create mode 100644 crates/store/re_sorbet/src/column_schema.rs create mode 100644 crates/store/re_sorbet/src/ipc.rs delete mode 100644 crates/utils/re_tuid/src/protobuf_conversions.rs diff --git a/Cargo.lock b/Cargo.lock index e42a06badff99..1c4309d97405a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -508,7 +508,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9579b9d8bce47aa41389fe344f2c6758279983b7c0ebb4013e283e3e91bb450e" dependencies = [ "bitflags 2.8.0", - "serde", ] [[package]] @@ -5790,7 +5789,6 @@ dependencies = [ "ahash", "anyhow", "arrow", - "arrow-schema", "criterion", "document-features", "indent", @@ -5813,7 +5811,6 @@ dependencies = [ "re_tracing", "re_types", "re_types_core", - "serde_json", "similar-asserts", "thiserror 1.0.65", "tinyvec", @@ -6217,7 +6214,6 @@ dependencies = [ "re_byte_size", "re_format", "re_log", - "re_protos", "re_string_interner", "re_tracing", "re_tuid", @@ -6282,8 +6278,13 @@ dependencies = [ name = "re_protos" version = "0.22.0-alpha.1+dev" dependencies = [ + "arrow", "prost", + "re_build_info", "re_byte_size", + "re_log_types", + "re_sorbet", + "re_tuid", "thiserror 1.0.65", "tonic", "tonic-web-wasm-client", @@ -6592,7 +6593,6 @@ dependencies = [ "getrandom", "once_cell", "re_byte_size", - "re_protos", "serde", "web-time", ] @@ -7510,6 +7510,7 @@ dependencies = [ "re_memory", "re_protos", "re_sdk", + "re_sorbet", "re_video", "re_web_viewer_server", "re_ws_comms", diff --git a/Cargo.toml b/Cargo.toml index e685969997115..78489b7c0eb5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -155,7 +155,6 @@ anyhow = { version = "1.0", default-features = false } argh = "0.1.12" array-init = "2.1" arrow = { version = "53.4", default-features = false } -arrow-schema = { version = "53.4", default-features = false } arrow2 = { package = "re_arrow2", version = "0.18.2", features = ["arrow"] } async-executor = "1.0" async-stream = "0.3" diff --git a/crates/store/re_chunk_store/Cargo.toml b/crates/store/re_chunk_store/Cargo.toml index f57eda12dbaf2..08786983e2afa 100644 --- a/crates/store/re_chunk_store/Cargo.toml +++ b/crates/store/re_chunk_store/Cargo.toml @@ -18,12 +18,6 @@ workspace = true [package.metadata.docs.rs] all-features = true -[package.metadata.cargo-machete] -ignored = [ - # Needed to enable the serde feature of arrow `Datatype` - "arrow-schema", -] - [features] default = [] @@ -50,14 +44,12 @@ re_types_core.workspace = true ahash.workspace = true anyhow.workspace = true arrow.workspace = true -arrow-schema = { workspace = true, features = ["serde"] } document-features.workspace = true indent.workspace = true itertools.workspace = true nohash-hasher.workspace = true once_cell.workspace = true parking_lot = { workspace = true, features = ["arc_lock"] } -serde_json.workspace = true thiserror.workspace = true web-time.workspace = true diff --git a/crates/store/re_chunk_store/src/dataframe.rs b/crates/store/re_chunk_store/src/dataframe.rs index 61c4fb96650b6..ab0a82c56f65e 100644 --- a/crates/store/re_chunk_store/src/dataframe.rs +++ b/crates/store/re_chunk_store/src/dataframe.rs @@ -13,70 +13,11 @@ use itertools::Itertools; use re_chunk::TimelineName; use re_log_types::{EntityPath, ResolvedTimeRange, TimeInt, Timeline}; -use re_sorbet::{ComponentColumnDescriptor, TimeColumnDescriptor}; +use re_sorbet::{ColumnDescriptor, ComponentColumnDescriptor, TimeColumnDescriptor}; use re_types_core::ComponentName; use crate::{ChunkStore, ColumnMetadata}; -// --- Descriptors --- - -// TODO(#6889): At some point all these descriptors needs to be interned and have handles or -// something. And of course they need to be codegen. But we'll get there once we're back to -// natively tagged components. - -// Describes any kind of column. -// -// See: -// * [`TimeColumnDescriptor`] -// * [`ComponentColumnDescriptor`] -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum ColumnDescriptor { - Time(TimeColumnDescriptor), - Component(ComponentColumnDescriptor), -} - -impl ColumnDescriptor { - #[inline] - pub fn entity_path(&self) -> Option<&EntityPath> { - match self { - Self::Time(_) => None, - Self::Component(descr) => Some(&descr.entity_path), - } - } - - #[inline] - pub fn arrow_datatype(&self) -> ArrowDatatype { - match self { - Self::Time(descr) => descr.datatype.clone(), - Self::Component(descr) => descr.returned_datatype(), - } - } - - #[inline] - pub fn to_arrow_field(&self) -> ArrowField { - match self { - Self::Time(descr) => descr.to_arrow_field(), - Self::Component(descr) => descr.to_arrow_field(), - } - } - - #[inline] - pub fn short_name(&self) -> String { - match self { - Self::Time(descr) => descr.timeline.name().to_string(), - Self::Component(descr) => descr.component_name.short_name().to_owned(), - } - } - - #[inline] - pub fn is_static(&self) -> bool { - match self { - Self::Time(_) => false, - Self::Component(descr) => descr.is_static, - } - } -} - // --- Selectors --- /// Describes a column selection to return as part of a query. diff --git a/crates/store/re_chunk_store/src/lib.rs b/crates/store/re_chunk_store/src/lib.rs index 3bb2dcb85f7aa..69b1d3bedcb51 100644 --- a/crates/store/re_chunk_store/src/lib.rs +++ b/crates/store/re_chunk_store/src/lib.rs @@ -28,8 +28,8 @@ mod protobuf_conversions; pub use self::{ dataframe::{ - ColumnDescriptor, ColumnSelector, ComponentColumnSelector, Index, IndexRange, IndexValue, - QueryExpression, SparseFillStrategy, TimeColumnSelector, ViewContentsSelector, + ColumnSelector, ComponentColumnSelector, Index, IndexRange, IndexValue, QueryExpression, + SparseFillStrategy, TimeColumnSelector, ViewContentsSelector, }, events::{ChunkCompactionReport, ChunkStoreDiff, ChunkStoreDiffKind, ChunkStoreEvent}, gc::{GarbageCollectionOptions, GarbageCollectionTarget}, @@ -37,7 +37,7 @@ pub use self::{ store::{ChunkStore, ChunkStoreConfig, ChunkStoreGeneration, ChunkStoreHandle, ColumnMetadata}, subscribers::{ChunkStoreSubscriber, ChunkStoreSubscriberHandle, PerStoreChunkSubscriber}, }; -pub use re_sorbet::{ComponentColumnDescriptor, TimeColumnDescriptor}; +pub use re_sorbet::{ColumnDescriptor, ComponentColumnDescriptor, TimeColumnDescriptor}; pub(crate) use self::store::ColumnMetadataState; diff --git a/crates/store/re_chunk_store/src/protobuf_conversions.rs b/crates/store/re_chunk_store/src/protobuf_conversions.rs index c0a22234925f0..3d593b6993fd9 100644 --- a/crates/store/re_chunk_store/src/protobuf_conversions.rs +++ b/crates/store/re_chunk_store/src/protobuf_conversions.rs @@ -1,8 +1,6 @@ -use re_protos::invalid_field; -use re_protos::missing_field; -use re_protos::TypeConversionError; -use std::collections::BTreeMap; -use std::collections::BTreeSet; +use std::collections::{BTreeMap, BTreeSet}; + +use re_protos::{missing_field, TypeConversionError}; impl TryFrom for crate::ComponentColumnSelector { type Error = TypeConversionError; @@ -258,112 +256,6 @@ impl From for re_protos::common::v0::Query { } } -impl TryFrom for re_protos::common::v0::ColumnDescriptor { - type Error = TypeConversionError; - - fn try_from(value: crate::ColumnDescriptor) -> Result { - match value { - crate::ColumnDescriptor::Time(time_descriptor) => Ok(Self { - descriptor_type: Some( - re_protos::common::v0::column_descriptor::DescriptorType::TimeColumn( - re_protos::common::v0::TimeColumnDescriptor { - timeline: Some(re_protos::common::v0::Timeline { - name: time_descriptor.timeline.name().to_string(), - }), - datatype: serde_json::to_string(&time_descriptor.datatype).map_err( - |err| invalid_field!(Self, "time column descriptor", err), - )?, - }, - ), - ), - }), - crate::ColumnDescriptor::Component(component_descriptor) => Ok(Self { - descriptor_type: Some( - re_protos::common::v0::column_descriptor::DescriptorType::ComponentColumn( - re_protos::common::v0::ComponentColumnDescriptor { - entity_path: Some(component_descriptor.entity_path.into()), - archetype_name: component_descriptor - .archetype_name - .map(|an| an.to_string()), - archetype_field_name: component_descriptor - .archetype_field_name - .map(|afn| afn.to_string()), - component_name: component_descriptor.component_name.to_string(), - datatype: serde_json::to_string(&component_descriptor.store_datatype) - .map_err(|err| { - invalid_field!(Self, "component column descriptor", err) - })?, - is_static: component_descriptor.is_static, - is_tombstone: component_descriptor.is_tombstone, - is_semantically_empty: component_descriptor.is_semantically_empty, - is_indicator: component_descriptor.is_indicator, - }, - ), - ), - }), - } - } -} - -impl TryFrom for crate::ColumnDescriptor { - type Error = TypeConversionError; - - fn try_from(value: re_protos::common::v0::ColumnDescriptor) -> Result { - let descriptor = value.descriptor_type.ok_or(missing_field!( - re_protos::common::v0::ColumnDescriptor, - "descriptor_type", - ))?; - - match descriptor { - re_protos::common::v0::column_descriptor::DescriptorType::TimeColumn( - time_descriptor, - ) => Ok(Self::Time(crate::TimeColumnDescriptor { - timeline: time_descriptor - .timeline - .ok_or(missing_field!( - re_protos::common::v0::TimeColumnDescriptor, - "timeline", - ))? - .into(), - datatype: serde_json::from_str(&time_descriptor.datatype).map_err(|err| { - invalid_field!( - re_protos::common::v0::ColumnDescriptor, - "time column descriptor", - err - ) - })?, - })), - re_protos::common::v0::column_descriptor::DescriptorType::ComponentColumn( - component_descriptor, - ) => Ok(Self::Component(crate::ComponentColumnDescriptor { - entity_path: component_descriptor - .entity_path - .ok_or(missing_field!( - re_protos::common::v0::ComponentColumnDescriptor, - "entity_path", - ))? - .try_into()?, - archetype_name: component_descriptor.archetype_name.map(Into::into), - archetype_field_name: component_descriptor.archetype_field_name.map(Into::into), - component_name: component_descriptor.component_name.into(), - store_datatype: serde_json::from_str(&component_descriptor.datatype).map_err( - |err| { - invalid_field!( - re_protos::common::v0::ColumnDescriptor, - "component column descriptor", - err - ) - }, - )?, - is_static: component_descriptor.is_static, - is_tombstone: component_descriptor.is_tombstone, - is_semantically_empty: component_descriptor.is_semantically_empty, - is_indicator: component_descriptor.is_indicator, - })), - } - } -} - #[cfg(test)] mod tests { use re_protos::common::v0::{ @@ -442,53 +334,4 @@ mod tests { assert_eq!(grpc_query_before, grpc_query_after); } - - #[test] - fn test_time_column_descriptor_conversion() { - let time_descriptor = crate::TimeColumnDescriptor { - timeline: crate::Timeline::log_time(), - datatype: arrow::datatypes::DataType::Timestamp( - arrow::datatypes::TimeUnit::Nanosecond, - None, - ), - }; - - let descriptor = crate::ColumnDescriptor::Time(time_descriptor.clone()); - - let proto_descriptor: re_protos::common::v0::ColumnDescriptor = - descriptor.try_into().unwrap(); - let descriptor_after = proto_descriptor.try_into().unwrap(); - let crate::ColumnDescriptor::Time(time_descriptor_after) = descriptor_after else { - panic!("Expected TimeColumnDescriptor") - }; - - assert_eq!(time_descriptor, time_descriptor_after); - } - - #[test] - fn test_component_column_descriptor_conversion() { - let component_descriptor = crate::ComponentColumnDescriptor { - entity_path: re_log_types::EntityPath::from("/some/path"), - archetype_name: Some("archetype".to_owned().into()), - archetype_field_name: Some("field".to_owned().into()), - component_name: re_chunk::ComponentName::new("component"), - store_datatype: arrow::datatypes::DataType::Int64, - is_static: true, - is_tombstone: false, - is_semantically_empty: false, - is_indicator: true, - }; - - let descriptor = crate::ColumnDescriptor::Component(component_descriptor.clone()); - - let proto_descriptor: re_protos::common::v0::ColumnDescriptor = - descriptor.try_into().unwrap(); - let descriptor_after = proto_descriptor.try_into().unwrap(); - let crate::ColumnDescriptor::Component(component_descriptor_after) = descriptor_after - else { - panic!("Expected ComponentColumnDescriptor") - }; - - assert_eq!(component_descriptor, component_descriptor_after); - } } diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap index cbe93814410d7..bb980973fc58b 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap @@ -1,22 +1,20 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 2353 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ ┆ ┆ ┆ [c] ┆ │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ ┆ ┆ ┆ [c] ┆ │ │ +│ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap index fdade94348316..c55b7a8f8b262 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap @@ -1,34 +1,32 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 2384 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap index eca4768c64743..c55b7a8f8b262 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap @@ -1,34 +1,32 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1429 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap index aaca718fa9d24..bb980973fc58b 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap @@ -1,22 +1,20 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1408 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ ┆ ┆ ┆ [c] ┆ │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ ┆ ┆ ┆ [c] ┆ │ │ +│ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap index 8233f425b9509..4093744288f98 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap @@ -1,36 +1,34 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 2114 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ 1970-01-01T00:00:00.000000060 ┆ [] ┆ [c] ┆ [] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 65 ┆ 1970-01-01T00:00:00.000000065 ┆ [] ┆ [c] ┆ [] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ 1970-01-01T00:00:00.000000060 ┆ [] ┆ [c] ┆ [] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 65 ┆ 1970-01-01T00:00:00.000000065 ┆ [] ┆ [c] ┆ [] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap index 619d85efad1ca..4093744288f98 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap @@ -1,36 +1,34 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 2087 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ 1970-01-01T00:00:00.000000060 ┆ [] ┆ [c] ┆ [] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 65 ┆ 1970-01-01T00:00:00.000000065 ┆ [] ┆ [c] ┆ [] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ 1970-01-01T00:00:00.000000060 ┆ [] ┆ [c] ┆ [] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 65 ┆ 1970-01-01T00:00:00.000000065 ┆ [] ┆ [c] ┆ [] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap index 711f557665748..84a2766f38778 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap @@ -1,28 +1,26 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1497 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap index 281d84b9f30fe..10b1dd43ba8d9 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap @@ -1,24 +1,22 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1536 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-2.snap index a99a4c44ace70..961f4883fa04a 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-2.snap @@ -1,15 +1,14 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1675 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌───────────────────────────────┬───────────────────────────────┬─────────────────────────────────────────┬─────────────────────────────────────────┬─────────────────────────────────────────┐ -│ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ -│ --- ┆ --- ┆ --- ┆ --- ┆ --- │ -│ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ -│ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ -│ ┆ ┆ sorbet.semantic_type: "example.MyColor" ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: "example.MyPoint" │ -│ ┆ ┆ ┆ sorbet.semantic_type: "example.MyLabel" ┆ │ -╞═══════════════════════════════╪═══════════════════════════════╪═════════════════════════════════════════╪═════════════════════════════════════════╪═════════════════════════════════════════╡ -└───────────────────────────────┴───────────────────────────────┴─────────────────────────────────────────┴─────────────────────────────────────────┴─────────────────────────────────────────┘ +┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ +│ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ +│ --- ┆ --- ┆ --- ┆ --- ┆ --- │ +│ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ +│ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ +│ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ +│ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ +│ ┆ ┆ ┆ kind: "data" ┆ │ +╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ +└────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap index f7d240711e6d9..c55b7a8f8b262 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap @@ -1,34 +1,32 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1700 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap index 94729d8fa8ebf..aaf0bdc4b57de 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap @@ -1,28 +1,26 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1726 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null.snap index f3e086b9da572..961f4883fa04a 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null.snap @@ -1,15 +1,14 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1643 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌───────────────────────────────┬───────────────────────────────┬─────────────────────────────────────────┬─────────────────────────────────────────┬─────────────────────────────────────────┐ -│ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ -│ --- ┆ --- ┆ --- ┆ --- ┆ --- │ -│ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ -│ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ -│ ┆ ┆ sorbet.semantic_type: "example.MyColor" ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: "example.MyPoint" │ -│ ┆ ┆ ┆ sorbet.semantic_type: "example.MyLabel" ┆ │ -╞═══════════════════════════════╪═══════════════════════════════╪═════════════════════════════════════════╪═════════════════════════════════════════╪═════════════════════════════════════════╡ -└───────────────────────────────┴───────────────────────────────┴─────────────────────────────────────────┴─────────────────────────────────────────┴─────────────────────────────────────────┘ +┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ +│ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ +│ --- ┆ --- ┆ --- ┆ --- ┆ --- │ +│ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ +│ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ +│ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ +│ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ +│ ┆ ┆ ┆ kind: "data" ┆ │ +╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ +└────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap index e94d91a9ea027..d83074ad4d03c 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap @@ -1,31 +1,30 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1877 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬─────────────────────────────────────────────────┐ │ -│ │ frame_nr ┆ frame_nr ┆ ATimeColumnThatDoesntExist │ │ -│ │ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "i64" ┆ type: "null" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "ATimeColumnThatDoesntExist" │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪═════════════════════════════════════════════════╡ │ -│ │ 10 ┆ 10 ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ 20 ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ 30 ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ 40 ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 50 ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ 60 ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 70 ┆ │ │ -│ └───────────────────────────────┴───────────────────────────────┴─────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬──────────────────────────────────────────┐ │ +│ │ frame_nr ┆ frame_nr ┆ ATimeColumnThatDoesntExist │ │ +│ │ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "i64" ┆ type: "null" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "frame_nr" ┆ index_name: "ATimeColumnThatDoesntExist" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ kind: "index" │ │ +│ ╞════════════════════════╪════════════════════════╪══════════════════════════════════════════╡ │ +│ │ 10 ┆ 10 ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ 20 ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ 30 ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ 40 ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 50 ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ 60 ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 70 ┆ │ │ +│ └────────────────────────┴────────────────────────┴──────────────────────────────────────────┘ │ +└────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap index a958131455c49..9cf62759e3e93 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap @@ -1,33 +1,31 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1916 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌─────────────────────────────────────────┬─────────────────────────────────────────┬─────────────────────────────────────────┬────────────────────────────────────────────────┐ │ -│ │ /this/that:example.MyColor ┆ /this/that:example.MyColor ┆ /non_existing_entity:example.MyColor ┆ /this/that:AComponentColumnThatDoesntExist │ │ -│ │ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "List[u32]" ┆ type: "List[u32]" ┆ type: "null" ┆ type: "null" │ │ -│ │ sorbet.path: "/this/that" ┆ sorbet.path: "/this/that" ┆ sorbet.path: "/non_existing_entity" ┆ sorbet.path: "/this/that" │ │ -│ │ sorbet.semantic_type: "example.MyColor" ┆ sorbet.semantic_type: "example.MyColor" ┆ sorbet.semantic_type: "example.MyColor" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ ┆ "AComponentColumnThatDoesntExist" │ │ -│ ╞═════════════════════════════════════════╪═════════════════════════════════════════╪═════════════════════════════════════════╪════════════════════════════════════════════════╡ │ -│ │ ┆ ┆ ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ ┆ ┆ ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [2] ┆ [2] ┆ ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [3] ┆ [3] ┆ ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [4] ┆ [4] ┆ ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ ┆ ┆ ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [6] ┆ [6] ┆ ┆ │ │ -│ └─────────────────────────────────────────┴─────────────────────────────────────────┴─────────────────────────────────────────┴────────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌──────────────────────────────┬──────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────────────┐ │ +│ │ /this/that:example.MyColor ┆ /this/that:example.MyColor ┆ /non_existing_entity:example.MyColor ┆ /this/that:AComponentColumnThatDoesntExist │ │ +│ │ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "List[u32]" ┆ type: "List[u32]" ┆ type: "null" ┆ type: "null" │ │ +│ │ component: "example.MyColor" ┆ component: "example.MyColor" ┆ component: "example.MyColor" ┆ component: "AComponentColumnThatDoesntExist" │ │ +│ │ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/non_existing_entity" ┆ entity_path: "/this/that" │ │ +│ │ kind: "data" ┆ kind: "data" ┆ kind: "data" ┆ kind: "data" │ │ +│ ╞══════════════════════════════╪══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════════════╡ │ +│ │ ┆ ┆ ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ ┆ ┆ ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ [2] ┆ [2] ┆ ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ [3] ┆ [3] ┆ ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ [4] ┆ [4] ┆ ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ ┆ ┆ ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ [6] ┆ [6] ┆ ┆ │ │ +│ └──────────────────────────────┴──────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────────────┘ │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-4.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-4.snap index 3e33a0898bbb8..ad3cdcde7a7b8 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-4.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-4.snap @@ -1,8 +1,6 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1977 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ CHUNK METADATA: │ @@ -12,15 +10,15 @@ snapshot_kind: text │ │ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ frame_nr ┆ /this/that:exa │ │ │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ mple.MyLabel │ │ │ │ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ type: "i64" ┆ --- │ │ -│ │ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ sorbet.index_n ┆ type: │ │ -│ │ ame: ┆ ame: ┆ ame: ┆ ame: ┆ ame: ┆ ame: ┆ ame: ┆ ame: ┆ ame: ┆ ame: ┆ "List[Utf8]" │ │ -│ │ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ sorbet.is_stat │ │ -│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ic: "yes" │ │ -│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ sorbet.path: │ │ +│ │ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ index_name: ┆ type: │ │ +│ │ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "frame_nr" ┆ "List[Utf8]" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ component: "ex │ │ +│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ample.MyLabel" │ │ +│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ entity_path: │ │ │ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ "/this/that" │ │ -│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ sorbet.semanti │ │ -│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ c_type: "examp │ │ -│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ le.MyLabel" │ │ +│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ is_static: │ │ +│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ "yes" │ │ +│ │ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ kind: "data" │ │ │ ╞════════════════╪════════════════╪════════════════╪════════════════╪════════════════╪════════════════╪════════════════╪════════════════╪════════════════╪════════════════╪════════════════╡ │ │ │ 10 ┆ 10 ┆ 10 ┆ 10 ┆ 10 ┆ 10 ┆ 10 ┆ 10 ┆ 10 ┆ 10 ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap index 452615ba580bf..5383fd1d8095a 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap @@ -1,34 +1,32 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1464 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap index 389d7ae538ade..981fa36654b7f 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap @@ -1,34 +1,32 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1607 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 0 ┆ ┆ ┆ [c] ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 15 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 45 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 75 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 90 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬───────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 0 ┆ ┆ ┆ [c] ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 15 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 45 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 75 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 90 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ +│ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap index 391fe11fbf631..ae5ccead81146 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap @@ -1,34 +1,32 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1578 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ "example.MyColor" ┆ sorbet.semantic_type: ┆ "example.MyPoint" │ │ -│ │ ┆ ┆ ┆ "example.MyLabel" ┆ │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╡ │ -│ │ 0 ┆ ┆ ┆ [c] ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 15 ┆ ┆ ┆ [c] ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 45 ┆ ┆ ┆ [c] ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 75 ┆ ┆ ┆ [c] ┆ │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 90 ┆ ┆ ┆ [c] ┆ │ │ -│ └───────────────────────────────┴───────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┘ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel ┆ /this/that:example.MyPoint │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" ┆ type: "List[Struct[2]]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" ┆ component: "example.MyPoint" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ │ │ +│ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 0 ┆ ┆ ┆ [c] ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 15 ┆ ┆ ┆ [c] ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 45 ┆ ┆ ┆ [c] ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 75 ┆ ┆ ┆ [c] ┆ │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 90 ┆ ┆ ┆ [c] ┆ │ │ +│ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap index d11f263319f07..b57174058daa5 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap @@ -1,27 +1,26 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1806 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌───────────────────────────────┬───────────────────────────────┬─────────────────────────────────────────┬─────────────────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel │ │ -│ │ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" │ │ -│ │ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" │ │ -│ │ ┆ ┆ sorbet.semantic_type: "example.MyColor" ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ ┆ sorbet.semantic_type: "example.MyLabel" │ │ -│ ╞═══════════════════════════════╪═══════════════════════════════╪═════════════════════════════════════════╪═════════════════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ ┆ [4] ┆ [c] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ ┆ [6] ┆ [c] │ │ -│ └───────────────────────────────┴───────────────────────────────┴─────────────────────────────────────────┴─────────────────────────────────────────┘ │ -└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel │ │ +│ │ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "List[u32]" ┆ type: "List[Utf8]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ kind: "data" ┆ is_static: "yes" │ │ +│ │ ┆ ┆ ┆ kind: "data" │ │ +│ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 30 ┆ ┆ [2] ┆ [c] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ [3] ┆ [c] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ ┆ [4] ┆ [c] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ ┆ [6] ┆ [c] │ │ +│ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents.snap index 74ea5b40180d9..e496917e1c6d2 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents.snap @@ -1,13 +1,12 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 1763 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌───────────────────────────────┬───────────────────────────────┐ -│ frame_nr ┆ log_time │ -│ --- ┆ --- │ -│ type: "i64" ┆ type: "Timestamp(ns)" │ -│ sorbet.index_name: "frame_nr" ┆ sorbet.index_name: "log_time" │ -╞═══════════════════════════════╪═══════════════════════════════╡ -└───────────────────────────────┴───────────────────────────────┘ +┌────────────────────────┬────────────────────────┐ +│ frame_nr ┆ log_time │ +│ --- ┆ --- │ +│ type: "i64" ┆ type: "Timestamp(ns)" │ +│ index_name: "frame_nr" ┆ index_name: "log_time" │ +│ kind: "index" ┆ kind: "index" │ +╞════════════════════════╪════════════════════════╡ +└────────────────────────┴────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap index bc1e8c0b1c7c5..e86684ead8103 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap @@ -1,28 +1,26 @@ --- source: crates/store/re_dataframe/src/query.rs -assertion_line: 2047 -expression: dataframe -snapshot_kind: text +expression: "TransportChunk::from(dataframe)" --- -┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ CHUNK METADATA: │ -│ │ -├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -│ ┌──────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ -│ │ frame_nr ┆ log_time ┆ log_tick ┆ /this/that:example.MyPoint ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel │ │ -│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ -│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "null" ┆ type: "null" ┆ type: "List[u32]" ┆ type: "List[Utf8]" │ │ -│ │ sorbet.index_name: ┆ sorbet.index_name: ┆ sorbet.index_name: ┆ sorbet.path: "/this/that" ┆ sorbet.path: "/this/that" ┆ sorbet.is_static: "yes" │ │ -│ │ "frame_nr" ┆ "log_time" ┆ "log_tick" ┆ sorbet.semantic_type: ┆ sorbet.semantic_type: ┆ sorbet.path: "/this/that" │ │ -│ │ ┆ ┆ ┆ "example.MyPoint" ┆ "example.MyColor" ┆ sorbet.semantic_type: │ │ -│ │ ┆ ┆ ┆ ┆ ┆ "example.MyLabel" │ │ -│ ╞══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 30 ┆ ┆ ┆ ┆ [2] ┆ [c] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ ┆ ┆ [3] ┆ [c] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ ┆ ┆ ┆ [4] ┆ [c] │ │ -│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ ┆ ┆ ┆ [6] ┆ [c] │ │ -│ └──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ CHUNK METADATA: │ +│ │ +├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +│ ┌────────────────────────┬────────────────────────┬────────────────────────┬──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐ │ +│ │ frame_nr ┆ log_time ┆ log_tick ┆ /this/that:example.MyPoint ┆ /this/that:example.MyColor ┆ /this/that:example.MyLabel │ │ +│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ +│ │ type: "i64" ┆ type: "Timestamp(ns)" ┆ type: "null" ┆ type: "null" ┆ type: "List[u32]" ┆ type: "List[Utf8]" │ │ +│ │ index_name: "frame_nr" ┆ index_name: "log_time" ┆ index_name: "log_tick" ┆ component: "example.MyPoint" ┆ component: "example.MyColor" ┆ component: "example.MyLabel" │ │ +│ │ kind: "index" ┆ kind: "index" ┆ kind: "index" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/this/that" │ │ +│ │ ┆ ┆ ┆ kind: "data" ┆ kind: "data" ┆ is_static: "yes" │ │ +│ │ ┆ ┆ ┆ ┆ ┆ kind: "data" │ │ +│ ╞════════════════════════╪════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ +│ │ 30 ┆ ┆ ┆ ┆ [2] ┆ [c] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 40 ┆ ┆ ┆ ┆ [3] ┆ [c] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 50 ┆ ┆ ┆ ┆ [4] ┆ [c] │ │ +│ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ +│ │ 70 ┆ ┆ ┆ ┆ [6] ┆ [c] │ │ +│ └────────────────────────┴────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_log_types/Cargo.toml b/crates/store/re_log_types/Cargo.toml index 523cb1dcc68ba..e6fd00279889e 100644 --- a/crates/store/re_log_types/Cargo.toml +++ b/crates/store/re_log_types/Cargo.toml @@ -47,7 +47,6 @@ re_build_info.workspace = true re_byte_size.workspace = true re_format.workspace = true re_log.workspace = true -re_protos.workspace = true re_string_interner.workspace = true re_tracing.workspace = true re_tuid.workspace = true diff --git a/crates/store/re_log_types/src/lib.rs b/crates/store/re_log_types/src/lib.rs index 68310b0a24874..a23b2868bf2db 100644 --- a/crates/store/re_log_types/src/lib.rs +++ b/crates/store/re_log_types/src/lib.rs @@ -32,8 +32,6 @@ mod time; mod time_real; mod vec_deque_ext; -mod protobuf_conversions; - use std::sync::Arc; use re_build_info::CrateVersion; diff --git a/crates/store/re_log_types/src/protobuf_conversions.rs b/crates/store/re_log_types/src/protobuf_conversions.rs deleted file mode 100644 index aab629292512b..0000000000000 --- a/crates/store/re_log_types/src/protobuf_conversions.rs +++ /dev/null @@ -1,698 +0,0 @@ -use re_protos::TypeConversionError; -use re_protos::{invalid_field, missing_field}; -use std::sync::Arc; - -impl From for re_protos::common::v0::EntityPath { - fn from(value: crate::EntityPath) -> Self { - Self { - path: value.to_string(), - } - } -} - -impl TryFrom for crate::EntityPath { - type Error = TypeConversionError; - - fn try_from(value: re_protos::common::v0::EntityPath) -> Result { - Self::parse_strict(&value.path) - .map_err(|err| invalid_field!(re_protos::common::v0::EntityPath, "path", err)) - } -} - -impl From for crate::Time { - fn from(value: re_protos::common::v0::Time) -> Self { - Self::from_ns_since_epoch(value.nanos_since_epoch) - } -} - -impl From for re_protos::common::v0::Time { - fn from(value: crate::Time) -> Self { - Self { - nanos_since_epoch: value.nanos_since_epoch(), - } - } -} - -impl From for re_protos::common::v0::TimeInt { - fn from(value: crate::TimeInt) -> Self { - Self { - time: value.as_i64(), - } - } -} - -impl From for crate::TimeInt { - fn from(value: re_protos::common::v0::TimeInt) -> Self { - Self::new_temporal(value.time) - } -} - -impl From for re_protos::common::v0::TimeRange { - fn from(value: crate::ResolvedTimeRange) -> Self { - Self { - start: value.min().as_i64(), - end: value.max().as_i64(), - } - } -} - -impl From for crate::ResolvedTimeRange { - fn from(value: re_protos::common::v0::TimeRange) -> Self { - Self::new( - crate::TimeInt::new_temporal(value.start), - crate::TimeInt::new_temporal(value.end), - ) - } -} - -impl From for re_protos::common::v0::IndexRange { - fn from(value: crate::ResolvedTimeRange) -> Self { - Self { - time_range: Some(value.into()), - } - } -} - -impl TryFrom for crate::ResolvedTimeRange { - type Error = TypeConversionError; - - fn try_from(value: re_protos::common::v0::IndexRange) -> Result { - value - .time_range - .ok_or(missing_field!( - re_protos::common::v0::IndexRange, - "time_range" - )) - .map(|time_range| Self::new(time_range.start, time_range.end)) - } -} - -impl From for crate::Timeline { - fn from(value: re_protos::common::v0::Timeline) -> Self { - // TODO(cmc): QueryExpression::filtered_index gotta be a selector - #[allow(clippy::match_same_arms)] - match value.name.as_str() { - "log_time" => Self::new_temporal(value.name), - "log_tick" => Self::new_sequence(value.name), - "frame" => Self::new_sequence(value.name), - "frame_nr" => Self::new_sequence(value.name), - _ => Self::new_temporal(value.name), - } - } -} - -impl From for re_protos::common::v0::Timeline { - fn from(value: crate::Timeline) -> Self { - Self { - name: value.name().to_string(), - } - } -} - -impl TryFrom for crate::Timeline { - type Error = TypeConversionError; - - fn try_from(value: re_protos::common::v0::IndexColumnSelector) -> Result { - let timeline = value - .timeline - .ok_or(missing_field!( - re_protos::common::v0::IndexColumnSelector, - "timeline" - ))? - .into(); - - Ok(timeline) - } -} - -impl From for crate::ApplicationId { - #[inline] - fn from(value: re_protos::common::v0::ApplicationId) -> Self { - Self(value.id) - } -} - -impl From for re_protos::common::v0::ApplicationId { - #[inline] - fn from(value: crate::ApplicationId) -> Self { - Self { id: value.0 } - } -} - -impl From for crate::StoreKind { - #[inline] - fn from(value: re_protos::common::v0::StoreKind) -> Self { - match value { - re_protos::common::v0::StoreKind::Recording => Self::Recording, - re_protos::common::v0::StoreKind::Blueprint => Self::Blueprint, - } - } -} - -impl From for re_protos::common::v0::StoreKind { - #[inline] - fn from(value: crate::StoreKind) -> Self { - match value { - crate::StoreKind::Recording => Self::Recording, - crate::StoreKind::Blueprint => Self::Blueprint, - } - } -} - -impl From for crate::StoreId { - #[inline] - fn from(value: re_protos::common::v0::StoreId) -> Self { - Self { - kind: value.kind().into(), - id: Arc::new(value.id), - } - } -} - -impl From for re_protos::common::v0::StoreId { - #[inline] - fn from(value: crate::StoreId) -> Self { - let kind: re_protos::common::v0::StoreKind = value.kind.into(); - Self { - kind: kind as i32, - id: String::clone(&*value.id), - } - } -} - -impl From for crate::StoreId { - #[inline] - fn from(value: re_protos::common::v0::RecordingId) -> Self { - Self { - kind: crate::StoreKind::Recording, - id: Arc::new(value.id), - } - } -} - -impl From for re_protos::common::v0::RecordingId { - #[inline] - fn from(value: crate::StoreId) -> Self { - Self { - id: String::clone(&*value.id), - } - } -} - -impl From for re_protos::log_msg::v0::StoreSource { - #[inline] - fn from(value: crate::StoreSource) -> Self { - use re_protos::external::prost::Message as _; - - let (kind, payload) = match value { - crate::StoreSource::Unknown => ( - re_protos::log_msg::v0::StoreSourceKind::UnknownKind as i32, - Vec::new(), - ), - crate::StoreSource::CSdk => ( - re_protos::log_msg::v0::StoreSourceKind::CSdk as i32, - Vec::new(), - ), - crate::StoreSource::PythonSdk(python_version) => ( - re_protos::log_msg::v0::StoreSourceKind::PythonSdk as i32, - re_protos::log_msg::v0::PythonVersion::from(python_version).encode_to_vec(), - ), - crate::StoreSource::RustSdk { - rustc_version, - llvm_version, - } => ( - re_protos::log_msg::v0::StoreSourceKind::RustSdk as i32, - re_protos::log_msg::v0::CrateInfo { - rustc_version, - llvm_version, - } - .encode_to_vec(), - ), - crate::StoreSource::File { file_source } => ( - re_protos::log_msg::v0::StoreSourceKind::File as i32, - re_protos::log_msg::v0::FileSource::from(file_source).encode_to_vec(), - ), - crate::StoreSource::Viewer => ( - re_protos::log_msg::v0::StoreSourceKind::Viewer as i32, - Vec::new(), - ), - crate::StoreSource::Other(description) => ( - re_protos::log_msg::v0::StoreSourceKind::Other as i32, - description.into_bytes(), - ), - }; - - Self { - kind, - extra: Some(re_protos::log_msg::v0::StoreSourceExtra { payload }), - } - } -} - -impl TryFrom for crate::StoreSource { - type Error = TypeConversionError; - - #[inline] - fn try_from(value: re_protos::log_msg::v0::StoreSource) -> Result { - use re_protos::external::prost::Message as _; - use re_protos::log_msg::v0::StoreSourceKind; - - match value.kind() { - StoreSourceKind::UnknownKind => Ok(Self::Unknown), - StoreSourceKind::CSdk => Ok(Self::CSdk), - StoreSourceKind::PythonSdk => { - let extra = value - .extra - .ok_or(missing_field!(re_protos::log_msg::v0::StoreSource, "extra"))?; - let python_version = - re_protos::log_msg::v0::PythonVersion::decode(&mut &extra.payload[..])?; - Ok(Self::PythonSdk(crate::PythonVersion::try_from( - python_version, - )?)) - } - StoreSourceKind::RustSdk => { - let extra = value - .extra - .ok_or(missing_field!(re_protos::log_msg::v0::StoreSource, "extra"))?; - let crate_info = - re_protos::log_msg::v0::CrateInfo::decode(&mut &extra.payload[..])?; - Ok(Self::RustSdk { - rustc_version: crate_info.rustc_version, - llvm_version: crate_info.llvm_version, - }) - } - StoreSourceKind::File => { - let extra = value - .extra - .ok_or(missing_field!(re_protos::log_msg::v0::StoreSource, "extra"))?; - let file_source = - re_protos::log_msg::v0::FileSource::decode(&mut &extra.payload[..])?; - Ok(Self::File { - file_source: crate::FileSource::try_from(file_source)?, - }) - } - StoreSourceKind::Viewer => Ok(Self::Viewer), - StoreSourceKind::Other => { - let description = value - .extra - .ok_or(missing_field!(re_protos::log_msg::v0::StoreSource, "extra"))?; - let description = String::from_utf8(description.payload).map_err(|err| { - invalid_field!(re_protos::log_msg::v0::StoreSource, "extra", err) - })?; - Ok(Self::Other(description)) - } - } - } -} - -impl From for re_protos::log_msg::v0::PythonVersion { - #[inline] - fn from(value: crate::PythonVersion) -> Self { - Self { - major: value.major as i32, - minor: value.minor as i32, - patch: value.patch as i32, - suffix: value.suffix, - } - } -} - -impl TryFrom for crate::PythonVersion { - type Error = TypeConversionError; - - #[inline] - fn try_from(value: re_protos::log_msg::v0::PythonVersion) -> Result { - Ok(Self { - major: value.major as u8, - minor: value.minor as u8, - patch: value.patch as u8, - suffix: value.suffix, - }) - } -} - -impl From for re_protos::log_msg::v0::FileSource { - #[inline] - fn from(value: crate::FileSource) -> Self { - let kind = match value { - crate::FileSource::Cli => re_protos::log_msg::v0::FileSourceKind::Cli as i32, - crate::FileSource::Uri => re_protos::log_msg::v0::FileSourceKind::Uri as i32, - crate::FileSource::DragAndDrop { .. } => { - re_protos::log_msg::v0::FileSourceKind::DragAndDrop as i32 - } - crate::FileSource::FileDialog { .. } => { - re_protos::log_msg::v0::FileSourceKind::FileDialog as i32 - } - crate::FileSource::Sdk => re_protos::log_msg::v0::FileSourceKind::Sdk as i32, - }; - - Self { kind } - } -} - -impl TryFrom for crate::FileSource { - type Error = TypeConversionError; - - #[inline] - fn try_from(value: re_protos::log_msg::v0::FileSource) -> Result { - use re_protos::log_msg::v0::FileSourceKind; - - match value.kind() { - FileSourceKind::Cli => Ok(Self::Cli), - FileSourceKind::Uri => Ok(Self::Uri), - FileSourceKind::DragAndDrop => Ok(Self::DragAndDrop { - recommended_application_id: None, - recommended_recording_id: None, - force_store_info: false, - }), - FileSourceKind::FileDialog => Ok(Self::FileDialog { - recommended_application_id: None, - recommended_recording_id: None, - force_store_info: false, - }), - FileSourceKind::Sdk => Ok(Self::Sdk), - FileSourceKind::UnknownSource => Err(invalid_field!( - re_protos::log_msg::v0::FileSource, - "kind", - "unknown kind", - )), - } - } -} - -impl From for re_protos::log_msg::v0::StoreInfo { - #[inline] - fn from(value: crate::StoreInfo) -> Self { - Self { - application_id: Some(value.application_id.into()), - store_id: Some(value.store_id.into()), - is_official_example: value.is_official_example, - started: Some(value.started.into()), - store_source: Some(value.store_source.into()), - store_version: value - .store_version - .map(|v| re_protos::log_msg::v0::StoreVersion { - crate_version_bits: i32::from_le_bytes(v.to_bytes()), - }), - } - } -} - -impl TryFrom for crate::StoreInfo { - type Error = TypeConversionError; - - #[inline] - fn try_from(value: re_protos::log_msg::v0::StoreInfo) -> Result { - let application_id: crate::ApplicationId = value - .application_id - .ok_or(missing_field!( - re_protos::log_msg::v0::StoreInfo, - "application_id", - ))? - .into(); - let store_id: crate::StoreId = value - .store_id - .ok_or(missing_field!( - re_protos::log_msg::v0::StoreInfo, - "store_id", - ))? - .into(); - let is_official_example = value.is_official_example; - let started: crate::Time = value - .started - .ok_or(missing_field!(re_protos::log_msg::v0::StoreInfo, "started"))? - .into(); - let store_source: crate::StoreSource = value - .store_source - .ok_or(missing_field!( - re_protos::log_msg::v0::StoreInfo, - "store_source", - ))? - .try_into()?; - let store_version = value - .store_version - .map(|v| re_build_info::CrateVersion::from_bytes(v.crate_version_bits.to_le_bytes())); - - Ok(Self { - application_id, - store_id, - cloned_from: None, - is_official_example, - started, - store_source, - store_version, - }) - } -} - -impl From for re_protos::log_msg::v0::SetStoreInfo { - #[inline] - fn from(value: crate::SetStoreInfo) -> Self { - Self { - row_id: Some(value.row_id.into()), - info: Some(value.info.into()), - } - } -} - -impl TryFrom for crate::SetStoreInfo { - type Error = TypeConversionError; - - #[inline] - fn try_from(value: re_protos::log_msg::v0::SetStoreInfo) -> Result { - Ok(Self { - row_id: value - .row_id - .ok_or(missing_field!( - re_protos::log_msg::v0::SetStoreInfo, - "row_id", - ))? - .into(), - info: value - .info - .ok_or(missing_field!(re_protos::log_msg::v0::SetStoreInfo, "info"))? - .try_into()?, - }) - } -} - -impl From - for re_protos::log_msg::v0::BlueprintActivationCommand -{ - #[inline] - fn from(value: crate::BlueprintActivationCommand) -> Self { - Self { - blueprint_id: Some(value.blueprint_id.into()), - make_active: value.make_active, - make_default: value.make_default, - } - } -} - -impl TryFrom - for crate::BlueprintActivationCommand -{ - type Error = TypeConversionError; - - #[inline] - fn try_from( - value: re_protos::log_msg::v0::BlueprintActivationCommand, - ) -> Result { - Ok(Self { - blueprint_id: value - .blueprint_id - .ok_or(missing_field!( - re_protos::log_msg::v0::BlueprintActivationCommand, - "blueprint_id", - ))? - .into(), - make_active: value.make_active, - make_default: value.make_default, - }) - } -} - -#[cfg(test)] -mod tests { - #[test] - fn entity_path_conversion() { - let entity_path = crate::EntityPath::parse_strict("a/b/c").unwrap(); - let proto_entity_path: re_protos::common::v0::EntityPath = entity_path.clone().into(); - let entity_path2: crate::EntityPath = proto_entity_path.try_into().unwrap(); - assert_eq!(entity_path, entity_path2); - } - - #[test] - fn time_conversion() { - let time = crate::Time::from_ns_since_epoch(123456789); - let proto_time: re_protos::common::v0::Time = time.into(); - let time2: crate::Time = proto_time.into(); - assert_eq!(time, time2); - } - - #[test] - fn time_int_conversion() { - let time_int = crate::TimeInt::new_temporal(123456789); - let proto_time_int: re_protos::common::v0::TimeInt = time_int.into(); - let time_int2: crate::TimeInt = proto_time_int.into(); - assert_eq!(time_int, time_int2); - } - - #[test] - fn time_range_conversion() { - let time_range = crate::ResolvedTimeRange::new( - crate::TimeInt::new_temporal(123456789), - crate::TimeInt::new_temporal(987654321), - ); - let proto_time_range: re_protos::common::v0::TimeRange = time_range.into(); - let time_range2: crate::ResolvedTimeRange = proto_time_range.into(); - assert_eq!(time_range, time_range2); - } - - #[test] - fn index_range_conversion() { - let time_range = crate::ResolvedTimeRange::new( - crate::TimeInt::new_temporal(123456789), - crate::TimeInt::new_temporal(987654321), - ); - let proto_index_range: re_protos::common::v0::IndexRange = time_range.into(); - let time_range2: crate::ResolvedTimeRange = proto_index_range.try_into().unwrap(); - assert_eq!(time_range, time_range2); - } - - #[test] - fn index_column_selector_conversion() { - let timeline = crate::Timeline::new_temporal("log_time"); - let proto_index_column_selector: re_protos::common::v0::IndexColumnSelector = - re_protos::common::v0::IndexColumnSelector { - timeline: Some(timeline.into()), - }; - let timeline2: crate::Timeline = proto_index_column_selector.try_into().unwrap(); - assert_eq!(timeline, timeline2); - } - - #[test] - fn application_id_conversion() { - let application_id = crate::ApplicationId("test".to_owned()); - let proto_application_id: re_protos::common::v0::ApplicationId = - application_id.clone().into(); - let application_id2: crate::ApplicationId = proto_application_id.into(); - assert_eq!(application_id, application_id2); - } - - #[test] - fn store_kind_conversion() { - let store_kind = crate::StoreKind::Recording; - let proto_store_kind: re_protos::common::v0::StoreKind = store_kind.into(); - let store_kind2: crate::StoreKind = proto_store_kind.into(); - assert_eq!(store_kind, store_kind2); - } - - #[test] - fn store_id_conversion() { - let store_id = - crate::StoreId::from_string(crate::StoreKind::Recording, "test_recording".to_owned()); - let proto_store_id: re_protos::common::v0::StoreId = store_id.clone().into(); - let store_id2: crate::StoreId = proto_store_id.into(); - assert_eq!(store_id, store_id2); - } - - #[test] - fn recording_id_conversion() { - let store_id = - crate::StoreId::from_string(crate::StoreKind::Recording, "test_recording".to_owned()); - let proto_recording_id: re_protos::common::v0::RecordingId = store_id.clone().into(); - let store_id2: crate::StoreId = proto_recording_id.into(); - assert_eq!(store_id, store_id2); - } - - #[test] - fn store_source_conversion() { - let store_source = crate::StoreSource::PythonSdk(crate::PythonVersion { - major: 3, - minor: 8, - patch: 0, - suffix: "a".to_owned(), - }); - let proto_store_source: re_protos::log_msg::v0::StoreSource = store_source.clone().into(); - let store_source2: crate::StoreSource = proto_store_source.try_into().unwrap(); - assert_eq!(store_source, store_source2); - } - - #[test] - fn file_source_conversion() { - let file_source = crate::FileSource::Uri; - let proto_file_source: re_protos::log_msg::v0::FileSource = file_source.clone().into(); - let file_source2: crate::FileSource = proto_file_source.try_into().unwrap(); - assert_eq!(file_source, file_source2); - } - - #[test] - fn store_info_conversion() { - let store_info = crate::StoreInfo { - application_id: crate::ApplicationId("test".to_owned()), - store_id: crate::StoreId::from_string( - crate::StoreKind::Recording, - "test_recording".to_owned(), - ), - cloned_from: None, - is_official_example: false, - started: crate::Time::now(), - store_source: crate::StoreSource::PythonSdk(crate::PythonVersion { - major: 3, - minor: 8, - patch: 0, - suffix: "a".to_owned(), - }), - store_version: None, - }; - let proto_store_info: re_protos::log_msg::v0::StoreInfo = store_info.clone().into(); - let store_info2: crate::StoreInfo = proto_store_info.try_into().unwrap(); - assert_eq!(store_info, store_info2); - } - - #[test] - fn set_store_info_conversion() { - let set_store_info = crate::SetStoreInfo { - row_id: re_tuid::Tuid::new(), - info: crate::StoreInfo { - application_id: crate::ApplicationId("test".to_owned()), - store_id: crate::StoreId::from_string( - crate::StoreKind::Recording, - "test_recording".to_owned(), - ), - cloned_from: None, - is_official_example: false, - started: crate::Time::now(), - store_source: crate::StoreSource::PythonSdk(crate::PythonVersion { - major: 3, - minor: 8, - patch: 0, - suffix: "a".to_owned(), - }), - store_version: None, - }, - }; - let proto_set_store_info: re_protos::log_msg::v0::SetStoreInfo = - set_store_info.clone().into(); - let set_store_info2: crate::SetStoreInfo = proto_set_store_info.try_into().unwrap(); - assert_eq!(set_store_info, set_store_info2); - } - - #[test] - fn blueprint_activation_command_conversion() { - let blueprint_activation_command = crate::BlueprintActivationCommand { - blueprint_id: crate::StoreId::from_string( - crate::StoreKind::Blueprint, - "test".to_owned(), - ), - make_active: true, - make_default: false, - }; - let proto_blueprint_activation_command: re_protos::log_msg::v0::BlueprintActivationCommand = - blueprint_activation_command.clone().into(); - let blueprint_activation_command2: crate::BlueprintActivationCommand = - proto_blueprint_activation_command.try_into().unwrap(); - assert_eq!(blueprint_activation_command, blueprint_activation_command2); - } -} diff --git a/crates/store/re_protos/Cargo.toml b/crates/store/re_protos/Cargo.toml index 85b6e3b781643..b6e00108362ad 100644 --- a/crates/store/re_protos/Cargo.toml +++ b/crates/store/re_protos/Cargo.toml @@ -13,9 +13,14 @@ rust-version.workspace = true version.workspace = true [dependencies] +re_build_info.workspace = true re_byte_size.workspace = true +re_log_types.workspace = true +re_sorbet.workspace = true +re_tuid.workspace = true # External +arrow.workspace = true prost.workspace = true thiserror.workspace = true diff --git a/crates/store/re_protos/README.md b/crates/store/re_protos/README.md index e96cb055def6b..09795842cc8d6 100644 --- a/crates/store/re_protos/README.md +++ b/crates/store/re_protos/README.md @@ -12,3 +12,5 @@ Rerun remote store node gRPC API service types (client and server). This crate includes both the language-agnostic definitions (protobuf) as well as the generated code. The code is generated with `pixi run codegen-protos`. + +It also includes helpers for converting between the generated protobuf types and native Rust types. diff --git a/crates/store/re_protos/proto/rerun/v0/common.proto b/crates/store/re_protos/proto/rerun/v0/common.proto index 01c4abd1742b2..fe32374a5de12 100644 --- a/crates/store/re_protos/proto/rerun/v0/common.proto +++ b/crates/store/re_protos/proto/rerun/v0/common.proto @@ -102,45 +102,6 @@ message Query { SparseFillStrategy sparse_fill_strategy = 11; } -message ColumnDescriptor { - oneof descriptor_type { - TimeColumnDescriptor time_column = 1; - ComponentColumnDescriptor component_column = 2; - } -} - -message TimeColumnDescriptor { - // The timeline this column is associated with. - Timeline timeline = 1; - // The Arrow datatype of the column. - // - // Currently this is a JSON-encoded `arrow-rs` `DataType`. - string datatype = 2; -} - -// Describes a data/component column, such as `Position3D`. -message ComponentColumnDescriptor { - // The path of the entity. - EntityPath entity_path = 1; - // Optional name of the `Archetype` associated with this data. - optional string archetype_name = 2; - // Optional name of the field within `Archetype` associated with this data. - optional string archetype_field_name = 3; - // Semantic name associated with this data. - string component_name = 4; - // The Arrow datatype of the column. - // - // Currently this is a JSON-encoded `arrow-rs` `DataType`. - string datatype = 5; - // Whether the column is a static column. - bool is_static = 6; - // Whether the column is a tombstone column. - bool is_tombstone = 7; - // Whether the column is an indicator column. - bool is_indicator = 8; - // Whether the column is semantically empty. - bool is_semantically_empty = 9; -} message ColumnSelection { repeated ColumnSelector columns = 1; diff --git a/crates/store/re_protos/proto/rerun/v0/remote_store.proto b/crates/store/re_protos/proto/rerun/v0/remote_store.proto index 86dbdd42bb316..8d6c28f512439 100644 --- a/crates/store/re_protos/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_protos/proto/rerun/v0/remote_store.proto @@ -39,7 +39,7 @@ message GetRecordingSchemaRequest { } message GetRecordingSchemaResponse { - repeated rerun.common.v0.ColumnDescriptor column_descriptors = 1; + rerun.common.v0.Schema schema = 2; } // ---------------- RegisterRecording ------------------ diff --git a/crates/store/re_protos/src/lib.rs b/crates/store/re_protos/src/lib.rs index df3a13b66375c..4d35b2174c7df 100644 --- a/crates/store/re_protos/src/lib.rs +++ b/crates/store/re_protos/src/lib.rs @@ -4,7 +4,8 @@ //! We want clear separation between 'internal' types and gRPC types and don't want //! to use gRPC types in the rerun viewer codebase. That's why we implement all the //! necessary conversion code (in the form of `From` and `TryFrom` traits) in this crate. -//! + +mod protobuf_conversions; pub mod external { pub use prost; diff --git a/crates/store/re_protos/src/protobuf_conversions/arrow.rs b/crates/store/re_protos/src/protobuf_conversions/arrow.rs new file mode 100644 index 0000000000000..cb11f01e8e5b5 --- /dev/null +++ b/crates/store/re_protos/src/protobuf_conversions/arrow.rs @@ -0,0 +1,21 @@ +use arrow::{datatypes::Schema as ArrowSchema, error::ArrowError}; + +impl TryFrom<&crate::common::v0::Schema> for ArrowSchema { + type Error = ArrowError; + + fn try_from(value: &crate::common::v0::Schema) -> Result { + Ok(Self::clone( + re_sorbet::schema_from_ipc(&value.arrow_schema)?.as_ref(), + )) + } +} + +impl TryFrom<&ArrowSchema> for crate::common::v0::Schema { + type Error = ArrowError; + + fn try_from(value: &ArrowSchema) -> Result { + Ok(Self { + arrow_schema: re_sorbet::ipc_from_schema(value)?, + }) + } +} diff --git a/crates/store/re_protos/src/protobuf_conversions/log_types.rs b/crates/store/re_protos/src/protobuf_conversions/log_types.rs new file mode 100644 index 0000000000000..a1aa6f0df3e6f --- /dev/null +++ b/crates/store/re_protos/src/protobuf_conversions/log_types.rs @@ -0,0 +1,688 @@ +use crate::TypeConversionError; +use crate::{invalid_field, missing_field}; +use std::sync::Arc; + +impl From for crate::common::v0::EntityPath { + fn from(value: re_log_types::EntityPath) -> Self { + Self { + path: value.to_string(), + } + } +} + +impl TryFrom for re_log_types::EntityPath { + type Error = TypeConversionError; + + fn try_from(value: crate::common::v0::EntityPath) -> Result { + Self::parse_strict(&value.path) + .map_err(|err| invalid_field!(crate::common::v0::EntityPath, "path", err)) + } +} + +impl From for re_log_types::Time { + fn from(value: crate::common::v0::Time) -> Self { + Self::from_ns_since_epoch(value.nanos_since_epoch) + } +} + +impl From for crate::common::v0::Time { + fn from(value: re_log_types::Time) -> Self { + Self { + nanos_since_epoch: value.nanos_since_epoch(), + } + } +} + +impl From for crate::common::v0::TimeInt { + fn from(value: re_log_types::TimeInt) -> Self { + Self { + time: value.as_i64(), + } + } +} + +impl From for re_log_types::TimeInt { + fn from(value: crate::common::v0::TimeInt) -> Self { + Self::new_temporal(value.time) + } +} + +impl From for crate::common::v0::TimeRange { + fn from(value: re_log_types::ResolvedTimeRange) -> Self { + Self { + start: value.min().as_i64(), + end: value.max().as_i64(), + } + } +} + +impl From for re_log_types::ResolvedTimeRange { + fn from(value: crate::common::v0::TimeRange) -> Self { + Self::new( + re_log_types::TimeInt::new_temporal(value.start), + re_log_types::TimeInt::new_temporal(value.end), + ) + } +} + +impl From for crate::common::v0::IndexRange { + fn from(value: re_log_types::ResolvedTimeRange) -> Self { + Self { + time_range: Some(value.into()), + } + } +} + +impl TryFrom for re_log_types::ResolvedTimeRange { + type Error = TypeConversionError; + + fn try_from(value: crate::common::v0::IndexRange) -> Result { + value + .time_range + .ok_or(missing_field!(crate::common::v0::IndexRange, "time_range")) + .map(|time_range| Self::new(time_range.start, time_range.end)) + } +} + +impl From for re_log_types::Timeline { + fn from(value: crate::common::v0::Timeline) -> Self { + // TODO(cmc): QueryExpression::filtered_index gotta be a selector + #[allow(clippy::match_same_arms)] + match value.name.as_str() { + "log_time" => Self::new_temporal(value.name), + "log_tick" => Self::new_sequence(value.name), + "frame" => Self::new_sequence(value.name), + "frame_nr" => Self::new_sequence(value.name), + _ => Self::new_temporal(value.name), + } + } +} + +impl From for crate::common::v0::Timeline { + fn from(value: re_log_types::Timeline) -> Self { + Self { + name: value.name().to_string(), + } + } +} + +impl TryFrom for re_log_types::Timeline { + type Error = TypeConversionError; + + fn try_from(value: crate::common::v0::IndexColumnSelector) -> Result { + let timeline = value + .timeline + .ok_or(missing_field!( + crate::common::v0::IndexColumnSelector, + "timeline" + ))? + .into(); + + Ok(timeline) + } +} + +impl From for re_log_types::ApplicationId { + #[inline] + fn from(value: crate::common::v0::ApplicationId) -> Self { + Self(value.id) + } +} + +impl From for crate::common::v0::ApplicationId { + #[inline] + fn from(value: re_log_types::ApplicationId) -> Self { + Self { id: value.0 } + } +} + +impl From for re_log_types::StoreKind { + #[inline] + fn from(value: crate::common::v0::StoreKind) -> Self { + match value { + crate::common::v0::StoreKind::Recording => Self::Recording, + crate::common::v0::StoreKind::Blueprint => Self::Blueprint, + } + } +} + +impl From for crate::common::v0::StoreKind { + #[inline] + fn from(value: re_log_types::StoreKind) -> Self { + match value { + re_log_types::StoreKind::Recording => Self::Recording, + re_log_types::StoreKind::Blueprint => Self::Blueprint, + } + } +} + +impl From for re_log_types::StoreId { + #[inline] + fn from(value: crate::common::v0::StoreId) -> Self { + Self { + kind: value.kind().into(), + id: Arc::new(value.id), + } + } +} + +impl From for crate::common::v0::StoreId { + #[inline] + fn from(value: re_log_types::StoreId) -> Self { + let kind: crate::common::v0::StoreKind = value.kind.into(); + Self { + kind: kind as i32, + id: String::clone(&*value.id), + } + } +} + +impl From for re_log_types::StoreId { + #[inline] + fn from(value: crate::common::v0::RecordingId) -> Self { + Self { + kind: re_log_types::StoreKind::Recording, + id: Arc::new(value.id), + } + } +} + +impl From for crate::common::v0::RecordingId { + #[inline] + fn from(value: re_log_types::StoreId) -> Self { + Self { + id: String::clone(&*value.id), + } + } +} + +impl From for crate::log_msg::v0::StoreSource { + #[inline] + fn from(value: re_log_types::StoreSource) -> Self { + use crate::external::prost::Message as _; + + let (kind, payload) = match value { + re_log_types::StoreSource::Unknown => ( + crate::log_msg::v0::StoreSourceKind::UnknownKind as i32, + Vec::new(), + ), + re_log_types::StoreSource::CSdk => { + (crate::log_msg::v0::StoreSourceKind::CSdk as i32, Vec::new()) + } + re_log_types::StoreSource::PythonSdk(python_version) => ( + crate::log_msg::v0::StoreSourceKind::PythonSdk as i32, + crate::log_msg::v0::PythonVersion::from(python_version).encode_to_vec(), + ), + re_log_types::StoreSource::RustSdk { + rustc_version, + llvm_version, + } => ( + crate::log_msg::v0::StoreSourceKind::RustSdk as i32, + crate::log_msg::v0::CrateInfo { + rustc_version, + llvm_version, + } + .encode_to_vec(), + ), + re_log_types::StoreSource::File { file_source } => ( + crate::log_msg::v0::StoreSourceKind::File as i32, + crate::log_msg::v0::FileSource::from(file_source).encode_to_vec(), + ), + re_log_types::StoreSource::Viewer => ( + crate::log_msg::v0::StoreSourceKind::Viewer as i32, + Vec::new(), + ), + re_log_types::StoreSource::Other(description) => ( + crate::log_msg::v0::StoreSourceKind::Other as i32, + description.into_bytes(), + ), + }; + + Self { + kind, + extra: Some(crate::log_msg::v0::StoreSourceExtra { payload }), + } + } +} + +impl TryFrom for re_log_types::StoreSource { + type Error = TypeConversionError; + + #[inline] + fn try_from(value: crate::log_msg::v0::StoreSource) -> Result { + use crate::external::prost::Message as _; + use crate::log_msg::v0::StoreSourceKind; + + match value.kind() { + StoreSourceKind::UnknownKind => Ok(Self::Unknown), + StoreSourceKind::CSdk => Ok(Self::CSdk), + StoreSourceKind::PythonSdk => { + let extra = value + .extra + .ok_or(missing_field!(crate::log_msg::v0::StoreSource, "extra"))?; + let python_version = + crate::log_msg::v0::PythonVersion::decode(&mut &extra.payload[..])?; + Ok(Self::PythonSdk(re_log_types::PythonVersion::try_from( + python_version, + )?)) + } + StoreSourceKind::RustSdk => { + let extra = value + .extra + .ok_or(missing_field!(crate::log_msg::v0::StoreSource, "extra"))?; + let crate_info = crate::log_msg::v0::CrateInfo::decode(&mut &extra.payload[..])?; + Ok(Self::RustSdk { + rustc_version: crate_info.rustc_version, + llvm_version: crate_info.llvm_version, + }) + } + StoreSourceKind::File => { + let extra = value + .extra + .ok_or(missing_field!(crate::log_msg::v0::StoreSource, "extra"))?; + let file_source = crate::log_msg::v0::FileSource::decode(&mut &extra.payload[..])?; + Ok(Self::File { + file_source: re_log_types::FileSource::try_from(file_source)?, + }) + } + StoreSourceKind::Viewer => Ok(Self::Viewer), + StoreSourceKind::Other => { + let description = value + .extra + .ok_or(missing_field!(crate::log_msg::v0::StoreSource, "extra"))?; + let description = String::from_utf8(description.payload) + .map_err(|err| invalid_field!(crate::log_msg::v0::StoreSource, "extra", err))?; + Ok(Self::Other(description)) + } + } + } +} + +impl From for crate::log_msg::v0::PythonVersion { + #[inline] + fn from(value: re_log_types::PythonVersion) -> Self { + Self { + major: value.major as i32, + minor: value.minor as i32, + patch: value.patch as i32, + suffix: value.suffix, + } + } +} + +impl TryFrom for re_log_types::PythonVersion { + type Error = TypeConversionError; + + #[inline] + fn try_from(value: crate::log_msg::v0::PythonVersion) -> Result { + Ok(Self { + major: value.major as u8, + minor: value.minor as u8, + patch: value.patch as u8, + suffix: value.suffix, + }) + } +} + +impl From for crate::log_msg::v0::FileSource { + #[inline] + fn from(value: re_log_types::FileSource) -> Self { + let kind = match value { + re_log_types::FileSource::Cli => crate::log_msg::v0::FileSourceKind::Cli as i32, + re_log_types::FileSource::Uri => crate::log_msg::v0::FileSourceKind::Uri as i32, + re_log_types::FileSource::DragAndDrop { .. } => { + crate::log_msg::v0::FileSourceKind::DragAndDrop as i32 + } + re_log_types::FileSource::FileDialog { .. } => { + crate::log_msg::v0::FileSourceKind::FileDialog as i32 + } + re_log_types::FileSource::Sdk => crate::log_msg::v0::FileSourceKind::Sdk as i32, + }; + + Self { kind } + } +} + +impl TryFrom for re_log_types::FileSource { + type Error = TypeConversionError; + + #[inline] + fn try_from(value: crate::log_msg::v0::FileSource) -> Result { + use crate::log_msg::v0::FileSourceKind; + + match value.kind() { + FileSourceKind::Cli => Ok(Self::Cli), + FileSourceKind::Uri => Ok(Self::Uri), + FileSourceKind::DragAndDrop => Ok(Self::DragAndDrop { + recommended_application_id: None, + recommended_recording_id: None, + force_store_info: false, + }), + FileSourceKind::FileDialog => Ok(Self::FileDialog { + recommended_application_id: None, + recommended_recording_id: None, + force_store_info: false, + }), + FileSourceKind::Sdk => Ok(Self::Sdk), + FileSourceKind::UnknownSource => Err(invalid_field!( + crate::log_msg::v0::FileSource, + "kind", + "unknown kind", + )), + } + } +} + +impl From for crate::log_msg::v0::StoreInfo { + #[inline] + fn from(value: re_log_types::StoreInfo) -> Self { + Self { + application_id: Some(value.application_id.into()), + store_id: Some(value.store_id.into()), + is_official_example: value.is_official_example, + started: Some(value.started.into()), + store_source: Some(value.store_source.into()), + store_version: value + .store_version + .map(|v| crate::log_msg::v0::StoreVersion { + crate_version_bits: i32::from_le_bytes(v.to_bytes()), + }), + } + } +} + +impl TryFrom for re_log_types::StoreInfo { + type Error = TypeConversionError; + + #[inline] + fn try_from(value: crate::log_msg::v0::StoreInfo) -> Result { + let application_id: re_log_types::ApplicationId = value + .application_id + .ok_or(missing_field!( + crate::log_msg::v0::StoreInfo, + "application_id", + ))? + .into(); + let store_id: re_log_types::StoreId = value + .store_id + .ok_or(missing_field!(crate::log_msg::v0::StoreInfo, "store_id",))? + .into(); + let is_official_example = value.is_official_example; + let started: re_log_types::Time = value + .started + .ok_or(missing_field!(crate::log_msg::v0::StoreInfo, "started"))? + .into(); + let store_source: re_log_types::StoreSource = value + .store_source + .ok_or(missing_field!( + crate::log_msg::v0::StoreInfo, + "store_source", + ))? + .try_into()?; + let store_version = value + .store_version + .map(|v| re_build_info::CrateVersion::from_bytes(v.crate_version_bits.to_le_bytes())); + + Ok(Self { + application_id, + store_id, + cloned_from: None, + is_official_example, + started, + store_source, + store_version, + }) + } +} + +impl From for crate::log_msg::v0::SetStoreInfo { + #[inline] + fn from(value: re_log_types::SetStoreInfo) -> Self { + Self { + row_id: Some(value.row_id.into()), + info: Some(value.info.into()), + } + } +} + +impl TryFrom for re_log_types::SetStoreInfo { + type Error = TypeConversionError; + + #[inline] + fn try_from(value: crate::log_msg::v0::SetStoreInfo) -> Result { + Ok(Self { + row_id: value + .row_id + .ok_or(missing_field!(crate::log_msg::v0::SetStoreInfo, "row_id",))? + .into(), + info: value + .info + .ok_or(missing_field!(crate::log_msg::v0::SetStoreInfo, "info"))? + .try_into()?, + }) + } +} + +impl From + for crate::log_msg::v0::BlueprintActivationCommand +{ + #[inline] + fn from(value: re_log_types::BlueprintActivationCommand) -> Self { + Self { + blueprint_id: Some(value.blueprint_id.into()), + make_active: value.make_active, + make_default: value.make_default, + } + } +} + +impl TryFrom + for re_log_types::BlueprintActivationCommand +{ + type Error = TypeConversionError; + + #[inline] + fn try_from( + value: crate::log_msg::v0::BlueprintActivationCommand, + ) -> Result { + Ok(Self { + blueprint_id: value + .blueprint_id + .ok_or(missing_field!( + crate::log_msg::v0::BlueprintActivationCommand, + "blueprint_id", + ))? + .into(), + make_active: value.make_active, + make_default: value.make_default, + }) + } +} + +#[cfg(test)] +mod tests { + + #[test] + fn entity_path_conversion() { + let entity_path = re_log_types::EntityPath::parse_strict("a/b/c").unwrap(); + let proto_entity_path: crate::common::v0::EntityPath = entity_path.clone().into(); + let entity_path2: re_log_types::EntityPath = proto_entity_path.try_into().unwrap(); + assert_eq!(entity_path, entity_path2); + } + + #[test] + fn time_conversion() { + let time = re_log_types::Time::from_ns_since_epoch(123456789); + let proto_time: crate::common::v0::Time = time.into(); + let time2: re_log_types::Time = proto_time.into(); + assert_eq!(time, time2); + } + + #[test] + fn time_int_conversion() { + let time_int = re_log_types::TimeInt::new_temporal(123456789); + let proto_time_int: crate::common::v0::TimeInt = time_int.into(); + let time_int2: re_log_types::TimeInt = proto_time_int.into(); + assert_eq!(time_int, time_int2); + } + + #[test] + fn time_range_conversion() { + let time_range = re_log_types::ResolvedTimeRange::new( + re_log_types::TimeInt::new_temporal(123456789), + re_log_types::TimeInt::new_temporal(987654321), + ); + let proto_time_range: crate::common::v0::TimeRange = time_range.into(); + let time_range2: re_log_types::ResolvedTimeRange = proto_time_range.into(); + assert_eq!(time_range, time_range2); + } + + #[test] + fn index_range_conversion() { + let time_range = re_log_types::ResolvedTimeRange::new( + re_log_types::TimeInt::new_temporal(123456789), + re_log_types::TimeInt::new_temporal(987654321), + ); + let proto_index_range: crate::common::v0::IndexRange = time_range.into(); + let time_range2: re_log_types::ResolvedTimeRange = proto_index_range.try_into().unwrap(); + assert_eq!(time_range, time_range2); + } + + #[test] + fn index_column_selector_conversion() { + let timeline = re_log_types::Timeline::new_temporal("log_time"); + let proto_index_column_selector: crate::common::v0::IndexColumnSelector = + crate::common::v0::IndexColumnSelector { + timeline: Some(timeline.into()), + }; + let timeline2: re_log_types::Timeline = proto_index_column_selector.try_into().unwrap(); + assert_eq!(timeline, timeline2); + } + + #[test] + fn application_id_conversion() { + let application_id = re_log_types::ApplicationId("test".to_owned()); + let proto_application_id: crate::common::v0::ApplicationId = application_id.clone().into(); + let application_id2: re_log_types::ApplicationId = proto_application_id.into(); + assert_eq!(application_id, application_id2); + } + + #[test] + fn store_kind_conversion() { + let store_kind = re_log_types::StoreKind::Recording; + let proto_store_kind: crate::common::v0::StoreKind = store_kind.into(); + let store_kind2: re_log_types::StoreKind = proto_store_kind.into(); + assert_eq!(store_kind, store_kind2); + } + + #[test] + fn store_id_conversion() { + let store_id = re_log_types::StoreId::from_string( + re_log_types::StoreKind::Recording, + "test_recording".to_owned(), + ); + let proto_store_id: crate::common::v0::StoreId = store_id.clone().into(); + let store_id2: re_log_types::StoreId = proto_store_id.into(); + assert_eq!(store_id, store_id2); + } + + #[test] + fn recording_id_conversion() { + let store_id = re_log_types::StoreId::from_string( + re_log_types::StoreKind::Recording, + "test_recording".to_owned(), + ); + let proto_recording_id: crate::common::v0::RecordingId = store_id.clone().into(); + let store_id2: re_log_types::StoreId = proto_recording_id.into(); + assert_eq!(store_id, store_id2); + } + + #[test] + fn store_source_conversion() { + let store_source = re_log_types::StoreSource::PythonSdk(re_log_types::PythonVersion { + major: 3, + minor: 8, + patch: 0, + suffix: "a".to_owned(), + }); + let proto_store_source: crate::log_msg::v0::StoreSource = store_source.clone().into(); + let store_source2: re_log_types::StoreSource = proto_store_source.try_into().unwrap(); + assert_eq!(store_source, store_source2); + } + + #[test] + fn file_source_conversion() { + let file_source = re_log_types::FileSource::Uri; + let proto_file_source: crate::log_msg::v0::FileSource = file_source.clone().into(); + let file_source2: re_log_types::FileSource = proto_file_source.try_into().unwrap(); + assert_eq!(file_source, file_source2); + } + + #[test] + fn store_info_conversion() { + let store_info = re_log_types::StoreInfo { + application_id: re_log_types::ApplicationId("test".to_owned()), + store_id: re_log_types::StoreId::from_string( + re_log_types::StoreKind::Recording, + "test_recording".to_owned(), + ), + cloned_from: None, + is_official_example: false, + started: re_log_types::Time::now(), + store_source: re_log_types::StoreSource::PythonSdk(re_log_types::PythonVersion { + major: 3, + minor: 8, + patch: 0, + suffix: "a".to_owned(), + }), + store_version: None, + }; + let proto_store_info: crate::log_msg::v0::StoreInfo = store_info.clone().into(); + let store_info2: re_log_types::StoreInfo = proto_store_info.try_into().unwrap(); + assert_eq!(store_info, store_info2); + } + + #[test] + fn set_store_info_conversion() { + let set_store_info = re_log_types::SetStoreInfo { + row_id: re_tuid::Tuid::new(), + info: re_log_types::StoreInfo { + application_id: re_log_types::ApplicationId("test".to_owned()), + store_id: re_log_types::StoreId::from_string( + re_log_types::StoreKind::Recording, + "test_recording".to_owned(), + ), + cloned_from: None, + is_official_example: false, + started: re_log_types::Time::now(), + store_source: re_log_types::StoreSource::PythonSdk(re_log_types::PythonVersion { + major: 3, + minor: 8, + patch: 0, + suffix: "a".to_owned(), + }), + store_version: None, + }, + }; + let proto_set_store_info: crate::log_msg::v0::SetStoreInfo = set_store_info.clone().into(); + let set_store_info2: re_log_types::SetStoreInfo = proto_set_store_info.try_into().unwrap(); + assert_eq!(set_store_info, set_store_info2); + } + + #[test] + fn blueprint_activation_command_conversion() { + let blueprint_activation_command = re_log_types::BlueprintActivationCommand { + blueprint_id: re_log_types::StoreId::from_string( + re_log_types::StoreKind::Blueprint, + "test".to_owned(), + ), + make_active: true, + make_default: false, + }; + let proto_blueprint_activation_command: crate::log_msg::v0::BlueprintActivationCommand = + blueprint_activation_command.clone().into(); + let blueprint_activation_command2: re_log_types::BlueprintActivationCommand = + proto_blueprint_activation_command.try_into().unwrap(); + assert_eq!(blueprint_activation_command, blueprint_activation_command2); + } +} diff --git a/crates/store/re_protos/src/protobuf_conversions/mod.rs b/crates/store/re_protos/src/protobuf_conversions/mod.rs new file mode 100644 index 0000000000000..31bdb1b54d91a --- /dev/null +++ b/crates/store/re_protos/src/protobuf_conversions/mod.rs @@ -0,0 +1,3 @@ +mod arrow; +mod log_types; +mod tuid; diff --git a/crates/store/re_protos/src/protobuf_conversions/tuid.rs b/crates/store/re_protos/src/protobuf_conversions/tuid.rs new file mode 100644 index 0000000000000..29b8526c2cb59 --- /dev/null +++ b/crates/store/re_protos/src/protobuf_conversions/tuid.rs @@ -0,0 +1,25 @@ +impl From for re_tuid::Tuid { + fn from(value: crate::common::v0::Tuid) -> Self { + Self::from_nanos_and_inc(value.time_ns, value.inc) + } +} + +impl From for crate::common::v0::Tuid { + fn from(value: re_tuid::Tuid) -> Self { + Self { + time_ns: value.nanoseconds_since_epoch(), + inc: value.inc(), + } + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_tuid_conversion() { + let tuid = re_tuid::Tuid::new(); + let proto_tuid: crate::common::v0::Tuid = tuid.into(); + let tuid2: re_tuid::Tuid = proto_tuid.into(); + assert_eq!(tuid, tuid2); + } +} diff --git a/crates/store/re_protos/src/v0/rerun.common.v0.rs b/crates/store/re_protos/src/v0/rerun.common.v0.rs index aacd376ad62c6..806f6810ed96f 100644 --- a/crates/store/re_protos/src/v0/rerun.common.v0.rs +++ b/crates/store/re_protos/src/v0/rerun.common.v0.rs @@ -161,95 +161,6 @@ impl ::prost::Name for Query { } } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct ColumnDescriptor { - #[prost(oneof = "column_descriptor::DescriptorType", tags = "1, 2")] - pub descriptor_type: ::core::option::Option, -} -/// Nested message and enum types in `ColumnDescriptor`. -pub mod column_descriptor { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum DescriptorType { - #[prost(message, tag = "1")] - TimeColumn(super::TimeColumnDescriptor), - #[prost(message, tag = "2")] - ComponentColumn(super::ComponentColumnDescriptor), - } -} -impl ::prost::Name for ColumnDescriptor { - const NAME: &'static str = "ColumnDescriptor"; - const PACKAGE: &'static str = "rerun.common.v0"; - fn full_name() -> ::prost::alloc::string::String { - "rerun.common.v0.ColumnDescriptor".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/rerun.common.v0.ColumnDescriptor".into() - } -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TimeColumnDescriptor { - /// The timeline this column is associated with. - #[prost(message, optional, tag = "1")] - pub timeline: ::core::option::Option, - /// The Arrow datatype of the column. - /// - /// Currently this is a JSON-encoded `arrow-rs` `DataType`. - #[prost(string, tag = "2")] - pub datatype: ::prost::alloc::string::String, -} -impl ::prost::Name for TimeColumnDescriptor { - const NAME: &'static str = "TimeColumnDescriptor"; - const PACKAGE: &'static str = "rerun.common.v0"; - fn full_name() -> ::prost::alloc::string::String { - "rerun.common.v0.TimeColumnDescriptor".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/rerun.common.v0.TimeColumnDescriptor".into() - } -} -/// Describes a data/component column, such as `Position3D`. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ComponentColumnDescriptor { - /// The path of the entity. - #[prost(message, optional, tag = "1")] - pub entity_path: ::core::option::Option, - /// Optional name of the `Archetype` associated with this data. - #[prost(string, optional, tag = "2")] - pub archetype_name: ::core::option::Option<::prost::alloc::string::String>, - /// Optional name of the field within `Archetype` associated with this data. - #[prost(string, optional, tag = "3")] - pub archetype_field_name: ::core::option::Option<::prost::alloc::string::String>, - /// Semantic name associated with this data. - #[prost(string, tag = "4")] - pub component_name: ::prost::alloc::string::String, - /// The Arrow datatype of the column. - /// - /// Currently this is a JSON-encoded `arrow-rs` `DataType`. - #[prost(string, tag = "5")] - pub datatype: ::prost::alloc::string::String, - /// Whether the column is a static column. - #[prost(bool, tag = "6")] - pub is_static: bool, - /// Whether the column is a tombstone column. - #[prost(bool, tag = "7")] - pub is_tombstone: bool, - /// Whether the column is an indicator column. - #[prost(bool, tag = "8")] - pub is_indicator: bool, - /// Whether the column is semantically empty. - #[prost(bool, tag = "9")] - pub is_semantically_empty: bool, -} -impl ::prost::Name for ComponentColumnDescriptor { - const NAME: &'static str = "ComponentColumnDescriptor"; - const PACKAGE: &'static str = "rerun.common.v0"; - fn full_name() -> ::prost::alloc::string::String { - "rerun.common.v0.ComponentColumnDescriptor".into() - } - fn type_url() -> ::prost::alloc::string::String { - "/rerun.common.v0.ComponentColumnDescriptor".into() - } -} -#[derive(Clone, PartialEq, ::prost::Message)] pub struct ColumnSelection { #[prost(message, repeated, tag = "1")] pub columns: ::prost::alloc::vec::Vec, diff --git a/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs b/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs index 13a5f0d65df55..1dff9da918265 100644 --- a/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs @@ -36,8 +36,8 @@ impl ::prost::Name for GetRecordingSchemaRequest { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetRecordingSchemaResponse { - #[prost(message, repeated, tag = "1")] - pub column_descriptors: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "2")] + pub schema: ::core::option::Option, } impl ::prost::Name for GetRecordingSchemaResponse { const NAME: &'static str = "GetRecordingSchemaResponse"; diff --git a/crates/store/re_sorbet/src/chunk_batch.rs b/crates/store/re_sorbet/src/chunk_batch.rs new file mode 100644 index 0000000000000..e91d7500b835d --- /dev/null +++ b/crates/store/re_sorbet/src/chunk_batch.rs @@ -0,0 +1,108 @@ +use arrow::array::RecordBatch as ArrowRecordBatch; +use arrow::datatypes::Schema as ArrowSchema; + +use re_log_types::EntityPath; + +#[derive(thiserror::Error, Debug)] +pub enum ChunkBatchError { + #[error("Missing record batch metadata key `{0}`")] + MissingRecordBatchMetadataKey(&'static str), +} + +/// The arrow [`ArrowRecordBatch`] representation of a Rerun chunk. +/// +/// This is a wrapper around a [`ArrowRecordBatch`]. +/// +/// Each [`ChunkBatch`] contains logging data for a single [`EntityPath`]. +/// It walwyas have a [`RowId`] column. +#[derive(Debug, Clone)] +pub struct ChunkBatch { + entity_path: EntityPath, + batch: ArrowRecordBatch, +} + +impl std::fmt::Display for ChunkBatch { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + re_format_arrow::format_record_batch_with_width(self, f.width()).fmt(f) + } +} + +impl AsRef for ChunkBatch { + #[inline] + fn as_ref(&self) -> &ArrowRecordBatch { + &self.batch + } +} + +impl std::ops::Deref for ChunkBatch { + type Target = ArrowRecordBatch; + + #[inline] + fn deref(&self) -> &ArrowRecordBatch { + &self.batch + } +} + +impl From for ArrowRecordBatch { + #[inline] + fn from(chunk: ChunkBatch) -> Self { + chunk.batch + } +} + +impl TryFrom for ChunkBatch { + type Error = ChunkBatchError; + + fn try_from(batch: ArrowRecordBatch) -> Result { + let mut schema = ArrowSchema::clone(&*batch.schema()); + let metadata = &mut schema.metadata; + + { + // Verify version + if let Some(batch_version) = metadata.get(Self::CHUNK_METADATA_KEY_VERSION) { + if batch_version != Self::CHUNK_METADATA_VERSION { + re_log::warn_once!( + "ChunkBatch version mismatch. Expected {:?}, got {batch_version:?}", + Self::CHUNK_METADATA_VERSION + ); + } + } + metadata.insert( + Self::CHUNK_METADATA_KEY_VERSION.to_owned(), + Self::CHUNK_METADATA_VERSION.to_owned(), + ); + } + + let entity_path = + if let Some(entity_path) = metadata.get(Self::CHUNK_METADATA_KEY_ENTITY_PATH) { + EntityPath::parse_forgiving(entity_path) + } else { + return Err(ChunkBatchError::MissingRecordBatchMetadataKey( + Self::CHUNK_METADATA_KEY_ENTITY_PATH, + )); + }; + + Ok(Self { entity_path, batch }) + } +} + +/// ## Metadata keys for the record batch metadata +impl ChunkBatch { + /// The key used to identify the version of the Rerun schema. + const CHUNK_METADATA_KEY_VERSION: &'static str = "rerun.version"; + + /// The version of the Rerun schema. + const CHUNK_METADATA_VERSION: &'static str = "1"; + + /// The key used to identify a Rerun [`EntityPath`] in the record batch metadata. + const CHUNK_METADATA_KEY_ENTITY_PATH: &'static str = "rerun.entity_path"; +} + +impl ChunkBatch { + /// Returns the [`EntityPath`] of the batch. + #[inline] + pub fn entity_path(&self) -> &EntityPath { + &self.entity_path + } +} diff --git a/crates/store/re_sorbet/src/column_schema.rs b/crates/store/re_sorbet/src/column_schema.rs new file mode 100644 index 0000000000000..9f7cf34ac02ee --- /dev/null +++ b/crates/store/re_sorbet/src/column_schema.rs @@ -0,0 +1,140 @@ +// TODO(#6889): At some point all these descriptors needs to be interned and have handles or +// something. And of course they need to be codegen. But we'll get there once we're back to +// natively tagged components. + +use arrow::datatypes::{ + DataType as ArrowDatatype, Field as ArrowField, FieldRef as ArrowFieldRef, + Fields as ArrowFields, +}; + +use re_log_types::EntityPath; + +use crate::{ComponentColumnDescriptor, MetadataExt as _, TimeColumnDescriptor}; + +#[derive(thiserror::Error, Debug)] +pub enum ColumnError { + #[error(transparent)] + MissingFieldMetadata(#[from] crate::MissingFieldMetadata), + + #[error("Unsupported column rerun.kind: {kind:?}. Expected one of: index, data")] + UnsupportedColumnKind { kind: String }, + + #[error(transparent)] + UnsupportedTimeType(#[from] crate::UnsupportedTimeType), +} + +// Describes any kind of column. +// +// See: +// * [`TimeColumnDescriptor`] +// * [`ComponentColumnDescriptor`] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum ColumnDescriptor { + Time(TimeColumnDescriptor), + Component(ComponentColumnDescriptor), +} + +impl ColumnDescriptor { + #[inline] + pub fn entity_path(&self) -> Option<&EntityPath> { + match self { + Self::Time(_) => None, + Self::Component(descr) => Some(&descr.entity_path), + } + } + + #[inline] + pub fn short_name(&self) -> String { + match self { + Self::Time(descr) => descr.timeline.name().to_string(), + Self::Component(descr) => descr.component_name.short_name().to_owned(), + } + } + + #[inline] + pub fn is_static(&self) -> bool { + match self { + Self::Time(_) => false, + Self::Component(descr) => descr.is_static, + } + } + + #[inline] + pub fn arrow_datatype(&self) -> ArrowDatatype { + match self { + Self::Time(descr) => descr.datatype.clone(), + Self::Component(descr) => descr.returned_datatype(), + } + } + + #[inline] + pub fn to_arrow_field(&self) -> ArrowField { + match self { + Self::Time(descr) => descr.to_arrow_field(), + Self::Component(descr) => descr.to_arrow_field(), + } + } + + #[inline] + pub fn to_arrow_fields(columns: &[Self]) -> ArrowFields { + columns.iter().map(|c| c.to_arrow_field()).collect() + } + + pub fn from_arrow_fields(fields: &[ArrowFieldRef]) -> Result, ColumnError> { + fields + .iter() + .map(|field| Self::try_from(field.as_ref())) + .collect() + } +} + +impl TryFrom<&ArrowField> for ColumnDescriptor { + type Error = ColumnError; + + fn try_from(field: &ArrowField) -> Result { + let kind = field.get_or_err("rerun.kind")?; + match kind { + "index" | "time" => Ok(Self::Time(TimeColumnDescriptor::try_from(field)?)), + "data" => Ok(Self::Component(ComponentColumnDescriptor::try_from(field)?)), + _ => Err(ColumnError::UnsupportedColumnKind { + kind: kind.to_owned(), + }), + } + } +} + +#[test] +fn test_schema_over_ipc() { + #![expect(clippy::disallowed_methods)] // Schema::new + + let original_columns = [ + ColumnDescriptor::Time(TimeColumnDescriptor { + timeline: re_log_types::Timeline::log_time(), + datatype: arrow::datatypes::DataType::Timestamp( + arrow::datatypes::TimeUnit::Nanosecond, + None, + ), + }), + ColumnDescriptor::Component(ComponentColumnDescriptor { + entity_path: re_log_types::EntityPath::from("/some/path"), + archetype_name: Some("archetype".to_owned().into()), + archetype_field_name: Some("field".to_owned().into()), + component_name: re_types_core::ComponentName::new("component"), + store_datatype: arrow::datatypes::DataType::Int64, + is_static: true, + is_tombstone: false, + is_semantically_empty: false, + is_indicator: true, + }), + ]; + + let original_schema = + arrow::datatypes::Schema::new(ColumnDescriptor::to_arrow_fields(&original_columns)); + let ipc_bytes = crate::ipc_from_schema(&original_schema).unwrap(); + + let recovered_schema = crate::schema_from_ipc(&ipc_bytes).unwrap(); + assert_eq!(recovered_schema.as_ref(), &original_schema); + + let recovered_columns = ColumnDescriptor::from_arrow_fields(&recovered_schema.fields).unwrap(); + assert_eq!(recovered_columns, original_columns); +} diff --git a/crates/store/re_sorbet/src/data_column_schema.rs b/crates/store/re_sorbet/src/data_column_schema.rs index 4c8ef9811dc87..3c24c9c614948 100644 --- a/crates/store/re_sorbet/src/data_column_schema.rs +++ b/crates/store/re_sorbet/src/data_column_schema.rs @@ -170,25 +170,21 @@ impl ComponentColumnDescriptor { // TODO(#6889): This needs some proper sorbetization -- I just threw these names randomly. [ - (*is_static).then_some(("sorbet.is_static".to_owned(), "yes".to_owned())), - (*is_indicator).then_some(("sorbet.is_indicator".to_owned(), "yes".to_owned())), - (*is_tombstone).then_some(("sorbet.is_tombstone".to_owned(), "yes".to_owned())), - (*is_semantically_empty) - .then_some(("sorbet.is_semantically_empty".to_owned(), "yes".to_owned())), - Some(("sorbet.path".to_owned(), entity_path.to_string())), + Some(("rerun.kind".to_owned(), "data".to_owned())), + Some(("rerun.entity_path".to_owned(), entity_path.to_string())), + archetype_name.map(|name| ("rerun.archetype".to_owned(), name.short_name().to_owned())), + archetype_field_name + .as_ref() + .map(|name| ("rerun.archetype_field".to_owned(), name.to_string())), Some(( - "sorbet.semantic_type".to_owned(), + "rerun.component".to_owned(), component_name.short_name().to_owned(), )), - archetype_name.map(|name| { - ( - "sorbet.semantic_family".to_owned(), - name.short_name().to_owned(), - ) - }), - archetype_field_name - .as_ref() - .map(|name| ("sorbet.logical_type".to_owned(), name.to_string())), + (*is_static).then_some(("rerun.is_static".to_owned(), "yes".to_owned())), + (*is_indicator).then_some(("rerun.is_indicator".to_owned(), "yes".to_owned())), + (*is_tombstone).then_some(("rerun.is_tombstone".to_owned(), "yes".to_owned())), + (*is_semantically_empty) + .then_some(("rerun.is_semantically_empty".to_owned(), "yes".to_owned())), ] .into_iter() .flatten() @@ -228,14 +224,14 @@ impl TryFrom<&ArrowField> for ComponentColumnDescriptor { fn try_from(field: &ArrowField) -> Result { Ok(Self { store_datatype: field.data_type().clone(), - entity_path: EntityPath::parse_forgiving(field.get_or_err("sorbet.path")?), - archetype_name: field.get_opt("sorbet.semantic_family").map(|x| x.into()), - archetype_field_name: field.get_opt("sorbet.logical_type").map(|x| x.into()), - component_name: field.get_or_err("sorbet.semantic_type")?.into(), - is_static: field.get_bool("sorbet.is_static"), - is_indicator: field.get_bool("sorbet.is_indicator"), - is_tombstone: field.get_bool("sorbet.is_tombstone"), - is_semantically_empty: field.get_bool("sorbet.is_semantically_empty"), + entity_path: EntityPath::parse_forgiving(field.get_or_err("rerun.entity_path")?), + archetype_name: field.get_opt("rerun.archetype").map(|x| x.into()), + archetype_field_name: field.get_opt("rerun.archetype_field").map(|x| x.into()), + component_name: field.get_or_err("rerun.component")?.into(), + is_static: field.get_bool("rerun.is_static"), + is_indicator: field.get_bool("rerun.is_indicator"), + is_tombstone: field.get_bool("rerun.is_tombstone"), + is_semantically_empty: field.get_bool("rerun.is_semantically_empty"), }) } } diff --git a/crates/store/re_sorbet/src/index_column_schema.rs b/crates/store/re_sorbet/src/index_column_schema.rs index 255ea88578659..c782edf0ecaf4 100644 --- a/crates/store/re_sorbet/src/index_column_schema.rs +++ b/crates/store/re_sorbet/src/index_column_schema.rs @@ -73,10 +73,11 @@ impl TimeColumnDescriptor { let nullable = true; // Time column must be nullable since static data doesn't have a time. - let metadata = std::iter::once(Some(( - "sorbet.index_name".to_owned(), - timeline.name().to_string(), - ))) + let metadata = [ + Some(("rerun.kind".to_owned(), "index".to_owned())), + Some(("rerun.index_name".to_owned(), timeline.name().to_string())), + ] + .into_iter() .flatten() .collect(); @@ -98,10 +99,10 @@ impl TryFrom<&ArrowField> for TimeColumnDescriptor { type Error = UnsupportedTimeType; fn try_from(field: &ArrowField) -> Result { - let name = if let Some(name) = field.metadata().get("sorbet.index_name") { + let name = if let Some(name) = field.metadata().get("rerun.index_name") { name.to_owned() } else { - re_log::warn_once!("Timeline '{}' is missing 'sorbet.index_name' metadata. Falling back on field/column name", field.name()); + re_log::warn_once!("Timeline '{}' is missing 'rerun.index_name' metadata. Falling back on field/column name", field.name()); field.name().to_owned() }; diff --git a/crates/store/re_sorbet/src/ipc.rs b/crates/store/re_sorbet/src/ipc.rs new file mode 100644 index 0000000000000..f31e36e0cee63 --- /dev/null +++ b/crates/store/re_sorbet/src/ipc.rs @@ -0,0 +1,21 @@ +use arrow::{ + datatypes::{Schema as ArrowSchema, SchemaRef as ArrowSchemaRef}, + error::ArrowError, +}; + +/// Encode an arrow schema as IPC bytes. +pub fn ipc_from_schema(schema: &ArrowSchema) -> Result, ArrowError> { + let mut ipc_bytes = Vec::::new(); + #[allow(clippy::disallowed_types)] // We only use StreamWriter for the schema, which is fine + let mut writer = arrow::ipc::writer::StreamWriter::try_new(&mut ipc_bytes, schema)?; + // writer.write(&batch)?; // Is this needed? + writer.finish()?; + Ok(ipc_bytes) +} + +/// Decode an arrow schema from IPC bytes. +pub fn schema_from_ipc(ipc_bytes: &[u8]) -> Result { + let cursor = std::io::Cursor::new(ipc_bytes); + let stream = arrow::ipc::reader::StreamReader::try_new(cursor, None)?; + Ok(stream.schema()) +} diff --git a/crates/store/re_sorbet/src/lib.rs b/crates/store/re_sorbet/src/lib.rs index 4d2495dbb5152..adfd5c216ac33 100644 --- a/crates/store/re_sorbet/src/lib.rs +++ b/crates/store/re_sorbet/src/lib.rs @@ -2,13 +2,17 @@ //! //! Handles the structure of arrow record batches and their meta data for different use cases for Rerun. +mod column_schema; mod data_column_schema; mod index_column_schema; +mod ipc; mod metadata; pub use self::{ + column_schema::{ColumnDescriptor, ColumnError}, data_column_schema::ComponentColumnDescriptor, - index_column_schema::TimeColumnDescriptor, + index_column_schema::{TimeColumnDescriptor, UnsupportedTimeType}, + ipc::{ipc_from_schema, schema_from_ipc}, metadata::{ ArrowBatchMetadata, ArrowFieldMetadata, MetadataExt, MissingFieldMetadata, MissingMetadataKey, diff --git a/crates/utils/re_tuid/Cargo.toml b/crates/utils/re_tuid/Cargo.toml index e60a198f6f259..d9f5ed2f8e0c1 100644 --- a/crates/utils/re_tuid/Cargo.toml +++ b/crates/utils/re_tuid/Cargo.toml @@ -28,7 +28,6 @@ serde = ["dep:serde"] [dependencies] re_byte_size.workspace = true -re_protos.workspace = true document-features.workspace = true getrandom.workspace = true diff --git a/crates/utils/re_tuid/src/lib.rs b/crates/utils/re_tuid/src/lib.rs index f215f1da34773..557da26f085a9 100644 --- a/crates/utils/re_tuid/src/lib.rs +++ b/crates/utils/re_tuid/src/lib.rs @@ -6,8 +6,6 @@ #![doc = document_features::document_features!()] //! -mod protobuf_conversions; - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Tuid { diff --git a/crates/utils/re_tuid/src/protobuf_conversions.rs b/crates/utils/re_tuid/src/protobuf_conversions.rs deleted file mode 100644 index a04dba09ddbf6..0000000000000 --- a/crates/utils/re_tuid/src/protobuf_conversions.rs +++ /dev/null @@ -1,28 +0,0 @@ -impl From for crate::Tuid { - fn from(value: re_protos::common::v0::Tuid) -> Self { - Self { - time_ns: value.time_ns, - inc: value.inc, - } - } -} - -impl From for re_protos::common::v0::Tuid { - fn from(value: crate::Tuid) -> Self { - Self { - time_ns: value.time_ns, - inc: value.inc, - } - } -} - -#[cfg(test)] -mod tests { - #[test] - fn test_tuid_conversion() { - let tuid = crate::Tuid::new(); - let proto_tuid: re_protos::common::v0::Tuid = tuid.into(); - let tuid2: crate::Tuid = proto_tuid.into(); - assert_eq!(tuid, tuid2); - } -} diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml index c598fb79c3c52..dfa7be8beee1e 100644 --- a/rerun_py/Cargo.toml +++ b/rerun_py/Cargo.toml @@ -70,11 +70,11 @@ re_log_encoding = { workspace = true } re_log_types.workspace = true re_memory.workspace = true re_sdk = { workspace = true, features = ["data_loaders"] } +re_sorbet.workspace = true re_video.workspace = true re_web_viewer_server = { workspace = true, optional = true } re_ws_comms = { workspace = true, optional = true } - arrow = { workspace = true, features = ["pyarrow"] } crossbeam.workspace = true document-features.workspace = true diff --git a/rerun_py/rerun_sdk/rerun/dataframe.py b/rerun_py/rerun_sdk/rerun/dataframe.py index 777a962b6b725..89c72647e21da 100644 --- a/rerun_py/rerun_sdk/rerun/dataframe.py +++ b/rerun_py/rerun_sdk/rerun/dataframe.py @@ -28,14 +28,14 @@ from ._send_columns import TimeColumnLike, send_columns from .recording_stream import RecordingStream -SORBET_INDEX_NAME = b"sorbet.index_name" -SORBET_ENTITY_PATH = b"sorbet.path" -SORBET_ARCHETYPE_NAME = b"sorbet.semantic_family" -SORBET_ARCHETYPE_FIELD = b"sorbet.logical_type" -SORBET_COMPONENT_NAME = b"sorbet.semantic_type" +SORBET_INDEX_NAME = b"rerun.index_name" +SORBET_ENTITY_PATH = b"rerun.entity_path" +SORBET_ARCHETYPE_NAME = b"rerun.archetype" +SORBET_ARCHETYPE_FIELD = b"rerun.archetype_field" +SORBET_COMPONENT_NAME = b"rerun.component" RERUN_KIND = b"rerun.kind" RERUN_KIND_CONTROL = b"control" -RERUN_KIND_INDEX = b"time" +RERUN_KIND_INDEX = b"index" class RawIndexColumn(TimeColumnLike): diff --git a/rerun_py/src/remote.rs b/rerun_py/src/remote.rs index dd0763ac8e0c7..6670e4455cd32 100644 --- a/rerun_py/src/remote.rs +++ b/rerun_py/src/remote.rs @@ -30,7 +30,6 @@ use re_protos::{ FetchRecordingRequest, GetRecordingSchemaRequest, QueryCatalogRequest, QueryRequest, RecordingType, RegisterRecordingRequest, UpdateCatalogRequest, }, - TypeConversionError, }; use re_sdk::{ApplicationId, ComponentName, StoreId, StoreKind, Time, Timeline}; @@ -272,17 +271,21 @@ impl PyStorageNodeClient { recording_id: Some(RecordingId { id }), }; - let column_descriptors = self + let schema = self .client .get_recording_schema(request) .await .map_err(|err| PyRuntimeError::new_err(err.to_string()))? .into_inner() - .column_descriptors - .into_iter() - .map(|cd| cd.try_into()) - .collect::, _>>() - .map_err(|err: TypeConversionError| PyRuntimeError::new_err(err.to_string()))?; + .schema + .ok_or_else(|| PyRuntimeError::new_err("Missing shcema"))?; + + let arrow_schema = ArrowSchema::try_from(&schema) + .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; + + let column_descriptors = + re_sorbet::ColumnDescriptor::from_arrow_fields(&arrow_schema.fields) + .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; Ok(PySchema { schema: column_descriptors, diff --git a/rerun_py/tests/unit/test_dataframe.py b/rerun_py/tests/unit/test_dataframe.py index b4961debe61f2..705845ef66c62 100644 --- a/rerun_py/tests/unit/test_dataframe.py +++ b/rerun_py/tests/unit/test_dataframe.py @@ -398,4 +398,12 @@ def test_roundtrip_send(self) -> None: df_round_trip = round_trip_recording.view(index="my_index", contents="/**").select().read_all() + print("df:") + print(df) + print() + + print("df_round_trip:") + print(df_round_trip) + print() + assert df == df_round_trip From 424cf2e86a7fd612a93d6b40a242c3f00213b8a0 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 28 Jan 2025 13:25:00 +0100 Subject: [PATCH 20/43] `ComponentBatch` doesn't implement `AsComponents` anymore (#8820) This makes it impossible to pass something implementing `ComponentBatch` (i.e. some native data that knows how to serialized itself into arrow component data) directly to `RecordingStream::log`. This forces the caller to either..: * explicitly opt into the low-level / component-level APIs via `my_data.serialized()`, which expose further custom-tagging facilities, or * use the archetype-level APIs instead, which handle tagging automatically. Similarly, this removes all the legacy support infrastructure that was needed to carry `ComponentBatch`es all the way to the logger: * `log_component_batches` * `AsComponents::as_component_batches` * `ComponentBatchCow`, `ComponentBatchCowWithDescriptor`, ... * etc I think this is all that's needed in order to..: * fix #8757 At the very least, it makes sure that existing code that used to log `ComponentBatch`es directly breaks at compile-time. --- .../re_types_builder/src/codegen/rust/api.rs | 13 +- .../re_data_loader/src/loader_archetype.rs | 2 +- .../re_log_types/src/example_components.rs | 7 + .../src/archetypes/annotation_context.rs | 19 +-- .../store/re_types/src/archetypes/arrows2d.rs | 19 +-- .../store/re_types/src/archetypes/arrows3d.rs | 19 +-- .../store/re_types/src/archetypes/asset3d.rs | 19 +-- .../re_types/src/archetypes/asset_video.rs | 19 +-- .../re_types/src/archetypes/bar_chart.rs | 19 +-- .../store/re_types/src/archetypes/boxes2d.rs | 19 +-- .../store/re_types/src/archetypes/boxes3d.rs | 19 +-- .../re_types/src/archetypes/capsules3d.rs | 19 +-- .../re_types/src/archetypes/depth_image.rs | 19 +-- .../re_types/src/archetypes/ellipsoids3d.rs | 19 +-- .../re_types/src/archetypes/encoded_image.rs | 19 +-- .../src/archetypes/geo_line_strings.rs | 19 +-- .../re_types/src/archetypes/geo_points.rs | 19 +-- .../re_types/src/archetypes/graph_edges.rs | 19 +-- .../re_types/src/archetypes/graph_nodes.rs | 19 +-- crates/store/re_types/src/archetypes/image.rs | 19 +-- .../src/archetypes/instance_poses3d.rs | 19 +-- .../re_types/src/archetypes/line_strips2d.rs | 19 +-- .../re_types/src/archetypes/line_strips3d.rs | 19 +-- .../store/re_types/src/archetypes/mesh3d.rs | 19 +-- .../store/re_types/src/archetypes/pinhole.rs | 19 +-- .../store/re_types/src/archetypes/points2d.rs | 19 +-- .../store/re_types/src/archetypes/points3d.rs | 19 +-- .../store/re_types/src/archetypes/scalar.rs | 19 +-- .../src/archetypes/segmentation_image.rs | 19 +-- .../re_types/src/archetypes/series_line.rs | 19 +-- .../re_types/src/archetypes/series_point.rs | 19 +-- .../store/re_types/src/archetypes/tensor.rs | 19 +-- .../re_types/src/archetypes/text_document.rs | 19 +-- .../store/re_types/src/archetypes/text_log.rs | 19 +-- .../re_types/src/archetypes/transform3d.rs | 19 +-- .../src/archetypes/video_frame_reference.rs | 19 +-- .../src/archetypes/view_coordinates.rs | 19 +-- .../src/blueprint/archetypes/background.rs | 10 +- .../archetypes/container_blueprint.rs | 10 +- .../blueprint/archetypes/dataframe_query.rs | 10 +- .../src/blueprint/archetypes/force_center.rs | 10 +- .../archetypes/force_collision_radius.rs | 10 +- .../src/blueprint/archetypes/force_link.rs | 10 +- .../blueprint/archetypes/force_many_body.rs | 10 +- .../blueprint/archetypes/force_position.rs | 10 +- .../src/blueprint/archetypes/line_grid3d.rs | 10 +- .../blueprint/archetypes/map_background.rs | 10 +- .../src/blueprint/archetypes/map_zoom.rs | 10 +- .../blueprint/archetypes/near_clip_plane.rs | 10 +- .../blueprint/archetypes/panel_blueprint.rs | 10 +- .../src/blueprint/archetypes/plot_legend.rs | 10 +- .../src/blueprint/archetypes/scalar_axis.rs | 10 +- .../archetypes/tensor_scalar_mapping.rs | 10 +- .../archetypes/tensor_slice_selection.rs | 10 +- .../blueprint/archetypes/tensor_view_fit.rs | 10 +- .../blueprint/archetypes/view_blueprint.rs | 10 +- .../src/blueprint/archetypes/view_contents.rs | 10 +- .../archetypes/viewport_blueprint.rs | 10 +- .../archetypes/visible_time_ranges.rs | 10 +- .../blueprint/archetypes/visual_bounds2d.rs | 10 +- .../src/blueprint/components/active_tab.rs | 2 +- .../blueprint/components/apply_latest_at.rs | 2 +- .../src/blueprint/components/auto_layout.rs | 2 +- .../src/blueprint/components/auto_views.rs | 2 +- .../blueprint/components/background_kind.rs | 2 +- .../src/blueprint/components/column_share.rs | 2 +- .../components/component_column_selector.rs | 2 +- .../blueprint/components/container_kind.rs | 2 +- .../src/blueprint/components/corner2d.rs | 2 +- .../src/blueprint/components/enabled.rs | 2 +- .../blueprint/components/filter_by_range.rs | 2 +- .../components/filter_is_not_null.rs | 2 +- .../blueprint/components/force_distance.rs | 2 +- .../blueprint/components/force_iterations.rs | 2 +- .../blueprint/components/force_strength.rs | 2 +- .../src/blueprint/components/grid_columns.rs | 2 +- .../src/blueprint/components/grid_spacing.rs | 2 +- .../blueprint/components/included_content.rs | 2 +- .../src/blueprint/components/interactive.rs | 2 +- .../components/lock_range_during_zoom.rs | 2 +- .../src/blueprint/components/map_provider.rs | 2 +- .../blueprint/components/near_clip_plane.rs | 2 +- .../src/blueprint/components/panel_state.rs | 2 +- .../blueprint/components/query_expression.rs | 2 +- .../blueprint/components/root_container.rs | 2 +- .../src/blueprint/components/row_share.rs | 2 +- .../blueprint/components/selected_columns.rs | 2 +- .../tensor_dimension_index_slider.rs | 2 +- .../src/blueprint/components/timeline_name.rs | 2 +- .../src/blueprint/components/view_class.rs | 2 +- .../src/blueprint/components/view_fit.rs | 2 +- .../blueprint/components/view_maximized.rs | 2 +- .../src/blueprint/components/view_origin.rs | 2 +- .../components/viewer_recommendation_hash.rs | 2 +- .../src/blueprint/components/visible.rs | 2 +- .../components/visible_time_range.rs | 2 +- .../blueprint/components/visual_bounds2d.rs | 2 +- .../components/visualizer_overrides.rs | 2 +- .../src/blueprint/components/zoom_level.rs | 2 +- .../datatypes/component_column_selector.rs | 2 +- .../blueprint/datatypes/filter_by_range.rs | 2 +- .../blueprint/datatypes/filter_is_not_null.rs | 2 +- .../blueprint/datatypes/selected_columns.rs | 2 +- .../tensor_dimension_index_slider.rs | 2 +- .../src/blueprint/datatypes/utf8list.rs | 2 +- .../src/blueprint/views/bar_chart_view.rs | 2 +- .../src/blueprint/views/dataframe_view.rs | 2 +- .../src/blueprint/views/graph_view.rs | 2 +- .../re_types/src/blueprint/views/map_view.rs | 2 +- .../src/blueprint/views/spatial2d_view.rs | 2 +- .../src/blueprint/views/spatial3d_view.rs | 2 +- .../src/blueprint/views/tensor_view.rs | 2 +- .../src/blueprint/views/text_document_view.rs | 2 +- .../src/blueprint/views/text_log_view.rs | 2 +- .../src/blueprint/views/time_series_view.rs | 2 +- .../src/components/aggregation_policy.rs | 2 +- .../re_types/src/components/albedo_factor.rs | 2 +- .../src/components/annotation_context.rs | 2 +- .../re_types/src/components/axis_length.rs | 2 +- crates/store/re_types/src/components/blob.rs | 2 +- .../store/re_types/src/components/class_id.rs | 2 +- crates/store/re_types/src/components/color.rs | 2 +- .../store/re_types/src/components/colormap.rs | 2 +- .../re_types/src/components/depth_meter.rs | 2 +- .../re_types/src/components/draw_order.rs | 2 +- .../re_types/src/components/entity_path.rs | 2 +- .../re_types/src/components/fill_mode.rs | 2 +- .../re_types/src/components/fill_ratio.rs | 2 +- .../src/components/gamma_correction.rs | 2 +- .../src/components/geo_line_string.rs | 2 +- .../re_types/src/components/graph_edge.rs | 2 +- .../re_types/src/components/graph_node.rs | 2 +- .../re_types/src/components/graph_type.rs | 2 +- .../re_types/src/components/half_size2d.rs | 2 +- .../re_types/src/components/half_size3d.rs | 2 +- .../re_types/src/components/image_buffer.rs | 2 +- .../re_types/src/components/image_format.rs | 2 +- .../src/components/image_plane_distance.rs | 2 +- .../re_types/src/components/keypoint_id.rs | 2 +- .../store/re_types/src/components/lat_lon.rs | 2 +- .../store/re_types/src/components/length.rs | 2 +- .../re_types/src/components/line_strip2d.rs | 2 +- .../re_types/src/components/line_strip3d.rs | 2 +- .../src/components/magnification_filter.rs | 2 +- .../re_types/src/components/marker_shape.rs | 2 +- .../re_types/src/components/marker_size.rs | 2 +- .../re_types/src/components/media_type.rs | 2 +- crates/store/re_types/src/components/name.rs | 2 +- .../store/re_types/src/components/opacity.rs | 2 +- .../src/components/pinhole_projection.rs | 2 +- .../store/re_types/src/components/plane3d.rs | 2 +- .../components/pose_rotation_axis_angle.rs | 2 +- .../src/components/pose_rotation_quat.rs | 2 +- .../re_types/src/components/pose_scale3d.rs | 2 +- .../src/components/pose_transform_mat3x3.rs | 2 +- .../src/components/pose_translation3d.rs | 2 +- .../re_types/src/components/position2d.rs | 2 +- .../re_types/src/components/position3d.rs | 2 +- .../store/re_types/src/components/radius.rs | 2 +- .../store/re_types/src/components/range1d.rs | 2 +- .../re_types/src/components/recording_uri.rs | 2 +- .../re_types/src/components/resolution.rs | 2 +- .../src/components/rotation_axis_angle.rs | 2 +- .../re_types/src/components/rotation_quat.rs | 2 +- .../store/re_types/src/components/scalar.rs | 2 +- .../store/re_types/src/components/scale3d.rs | 2 +- .../re_types/src/components/show_labels.rs | 2 +- .../re_types/src/components/stroke_width.rs | 2 +- .../re_types/src/components/tensor_data.rs | 2 +- .../tensor_dimension_index_selection.rs | 2 +- .../src/components/tensor_height_dimension.rs | 2 +- .../src/components/tensor_width_dimension.rs | 2 +- .../re_types/src/components/texcoord2d.rs | 2 +- crates/store/re_types/src/components/text.rs | 2 +- .../re_types/src/components/text_log_level.rs | 2 +- .../src/components/transform_mat3x3.rs | 2 +- .../src/components/transform_relation.rs | 2 +- .../re_types/src/components/translation3d.rs | 2 +- .../src/components/triangle_indices.rs | 2 +- .../re_types/src/components/value_range.rs | 2 +- .../store/re_types/src/components/vector2d.rs | 2 +- .../store/re_types/src/components/vector3d.rs | 2 +- .../src/components/video_timestamp.rs | 2 +- .../src/components/view_coordinates.rs | 2 +- crates/store/re_types/src/datatypes/angle.rs | 2 +- .../re_types/src/datatypes/annotation_info.rs | 2 +- crates/store/re_types/src/datatypes/blob.rs | 2 +- .../src/datatypes/channel_datatype.rs | 2 +- .../src/datatypes/class_description.rs | 2 +- .../datatypes/class_description_map_elem.rs | 2 +- .../store/re_types/src/datatypes/class_id.rs | 2 +- .../re_types/src/datatypes/color_model.rs | 2 +- crates/store/re_types/src/datatypes/dvec2d.rs | 2 +- .../re_types/src/datatypes/image_format.rs | 2 +- .../re_types/src/datatypes/keypoint_id.rs | 2 +- .../re_types/src/datatypes/keypoint_pair.rs | 2 +- crates/store/re_types/src/datatypes/mat3x3.rs | 2 +- crates/store/re_types/src/datatypes/mat4x4.rs | 2 +- .../re_types/src/datatypes/pixel_format.rs | 2 +- .../store/re_types/src/datatypes/plane3d.rs | 2 +- .../re_types/src/datatypes/quaternion.rs | 2 +- .../store/re_types/src/datatypes/range1d.rs | 2 +- .../store/re_types/src/datatypes/range2d.rs | 2 +- crates/store/re_types/src/datatypes/rgba32.rs | 2 +- .../src/datatypes/rotation_axis_angle.rs | 2 +- .../re_types/src/datatypes/tensor_buffer.rs | 2 +- .../re_types/src/datatypes/tensor_data.rs | 2 +- .../tensor_dimension_index_selection.rs | 2 +- .../datatypes/tensor_dimension_selection.rs | 2 +- .../store/re_types/src/datatypes/utf8pair.rs | 2 +- crates/store/re_types/src/datatypes/uuid.rs | 2 +- crates/store/re_types/src/datatypes/uvec2d.rs | 2 +- crates/store/re_types/src/datatypes/uvec3d.rs | 2 +- crates/store/re_types/src/datatypes/uvec4d.rs | 2 +- crates/store/re_types/src/datatypes/vec2d.rs | 2 +- crates/store/re_types/src/datatypes/vec3d.rs | 2 +- crates/store/re_types/src/datatypes/vec4d.rs | 2 +- .../re_types/src/datatypes/video_timestamp.rs | 2 +- .../src/datatypes/view_coordinates.rs | 2 +- .../src/testing/archetypes/affix_fuzzer1.rs | 19 +-- .../src/testing/archetypes/affix_fuzzer2.rs | 19 +-- .../src/testing/archetypes/affix_fuzzer3.rs | 19 +-- .../src/testing/archetypes/affix_fuzzer4.rs | 19 +-- .../src/testing/components/affix_fuzzer1.rs | 2 +- .../src/testing/components/affix_fuzzer10.rs | 2 +- .../src/testing/components/affix_fuzzer11.rs | 2 +- .../src/testing/components/affix_fuzzer12.rs | 2 +- .../src/testing/components/affix_fuzzer13.rs | 2 +- .../src/testing/components/affix_fuzzer14.rs | 2 +- .../src/testing/components/affix_fuzzer15.rs | 2 +- .../src/testing/components/affix_fuzzer16.rs | 2 +- .../src/testing/components/affix_fuzzer17.rs | 2 +- .../src/testing/components/affix_fuzzer18.rs | 2 +- .../src/testing/components/affix_fuzzer19.rs | 2 +- .../src/testing/components/affix_fuzzer2.rs | 2 +- .../src/testing/components/affix_fuzzer20.rs | 2 +- .../src/testing/components/affix_fuzzer21.rs | 2 +- .../src/testing/components/affix_fuzzer22.rs | 2 +- .../src/testing/components/affix_fuzzer23.rs | 2 +- .../src/testing/components/affix_fuzzer3.rs | 2 +- .../src/testing/components/affix_fuzzer4.rs | 2 +- .../src/testing/components/affix_fuzzer5.rs | 2 +- .../src/testing/components/affix_fuzzer6.rs | 2 +- .../src/testing/components/affix_fuzzer7.rs | 2 +- .../src/testing/components/affix_fuzzer8.rs | 2 +- .../src/testing/components/affix_fuzzer9.rs | 2 +- .../src/testing/datatypes/affix_fuzzer1.rs | 2 +- .../src/testing/datatypes/affix_fuzzer2.rs | 2 +- .../src/testing/datatypes/affix_fuzzer20.rs | 2 +- .../src/testing/datatypes/affix_fuzzer21.rs | 2 +- .../src/testing/datatypes/affix_fuzzer22.rs | 2 +- .../src/testing/datatypes/affix_fuzzer3.rs | 2 +- .../src/testing/datatypes/affix_fuzzer4.rs | 2 +- .../src/testing/datatypes/affix_fuzzer5.rs | 2 +- .../src/testing/datatypes/enum_test.rs | 2 +- .../src/testing/datatypes/flattened_scalar.rs | 2 +- .../src/testing/datatypes/multi_enum.rs | 2 +- .../testing/datatypes/primitive_component.rs | 2 +- .../src/testing/datatypes/string_component.rs | 2 +- .../src/testing/datatypes/valued_enum.rs | 2 +- crates/store/re_types_core/src/archetype.rs | 25 +--- .../re_types_core/src/archetypes/clear.rs | 18 ++- .../store/re_types_core/src/as_components.rs | 132 ++++-------------- .../src/components/clear_is_recursive.rs | 2 +- .../store/re_types_core/src/datatypes/bool.rs | 2 +- .../src/datatypes/entity_path.rs | 2 +- .../re_types_core/src/datatypes/float32.rs | 2 +- .../re_types_core/src/datatypes/float64.rs | 2 +- .../re_types_core/src/datatypes/time_int.rs | 2 +- .../re_types_core/src/datatypes/time_range.rs | 2 +- .../src/datatypes/time_range_boundary.rs | 2 +- .../re_types_core/src/datatypes/uint16.rs | 2 +- .../re_types_core/src/datatypes/uint32.rs | 2 +- .../re_types_core/src/datatypes/uint64.rs | 2 +- .../store/re_types_core/src/datatypes/utf8.rs | 2 +- .../src/datatypes/visible_time_range.rs | 2 +- crates/store/re_types_core/src/lib.rs | 41 +++--- .../store/re_types_core/src/loggable_batch.rs | 128 ----------------- crates/top/re_sdk/src/lib.rs | 9 +- crates/top/re_sdk/src/recording_stream.rs | 76 +--------- crates/viewer/re_data_ui/src/instance_path.rs | 14 +- crates/viewer/re_view_spatial/src/view_2d.rs | 9 +- .../src/line_visualizer_system.rs | 4 +- .../src/point_visualizer_system.rs | 4 +- .../src/view/visualizer_system.rs | 9 +- .../all/archetypes/mesh3d_partial_updates.rs | 13 +- .../concepts/different_data_per_timeline.rs | 4 +- .../all/descriptors/descr_custom_archetype.rs | 14 +- .../color_coordinates_visualizer_system.rs | 6 + 289 files changed, 863 insertions(+), 1035 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/rust/api.rs b/crates/build/re_types_builder/src/codegen/rust/api.rs index cb244bd6e1a9f..4d247e695dd2e 100644 --- a/crates/build/re_types_builder/src/codegen/rust/api.rs +++ b/crates/build/re_types_builder/src/codegen/rust/api.rs @@ -185,7 +185,7 @@ fn generate_object_file( code.push_str("use ::re_types_core::SerializationResult;\n"); code.push_str("use ::re_types_core::{DeserializationResult, DeserializationError};\n"); code.push_str("use ::re_types_core::{ComponentDescriptor, ComponentName};\n"); - code.push_str("use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch};\n"); + code.push_str("use ::re_types_core::{ComponentBatch, SerializedComponentBatch};\n"); // NOTE: `TokenStream`s discard whitespacing information by definition, so we need to // inject some of our own when writing to file… while making sure that don't inject @@ -1174,7 +1174,7 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream { let all_component_batches = { std::iter::once(quote! { - Self::indicator().serialized() + Some(Self::indicator()) }) .chain(obj.fields.iter().map(|obj_field| { let field_name = format_ident!("{}", obj_field.name); @@ -1244,9 +1244,9 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: #quoted_indicator_name = #quoted_indicator_name::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] // There is no such thing as failing to serialize an indicator. + #quoted_indicator_name::DEFAULT.serialized().unwrap() } #[inline] @@ -1665,8 +1665,7 @@ fn quote_builder_from_obj(reporter: &Reporter, objects: &Objects, obj: &Object) I: IntoIterator + Clone, { let columns = [ #(#fields),* ]; - let indicator_column = #indicator_column; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns.into_iter().flatten().chain([#indicator_column])) } #columns_unary_doc diff --git a/crates/store/re_data_loader/src/loader_archetype.rs b/crates/store/re_data_loader/src/loader_archetype.rs index eed641e3a3986..26a25a8c5aaa9 100644 --- a/crates/store/re_data_loader/src/loader_archetype.rs +++ b/crates/store/re_data_loader/src/loader_archetype.rs @@ -220,7 +220,7 @@ fn load_video( std::iter::once((video_timeline, time_column)).collect(), [ ( - VideoFrameReference::indicator().descriptor().into_owned(), + VideoFrameReference::indicator().descriptor.clone(), video_frame_reference_indicators_list_array, ), ( diff --git a/crates/store/re_log_types/src/example_components.rs b/crates/store/re_log_types/src/example_components.rs index a0566ae99b49e..69e26ff560e06 100644 --- a/crates/store/re_log_types/src/example_components.rs +++ b/crates/store/re_log_types/src/example_components.rs @@ -67,6 +67,13 @@ impl MyPoints { impl re_types_core::Archetype for MyPoints { type Indicator = re_types_core::GenericIndicatorComponent; + fn indicator() -> SerializedComponentBatch { + use re_types_core::ComponentBatch as _; + // These is no such thing as failing to serialized an indicator. + #[allow(clippy::unwrap_used)] + Self::Indicator::default().serialized().unwrap() + } + fn name() -> re_types_core::ArchetypeName { "example.MyPoints".into() } diff --git a/crates/store/re_types/src/archetypes/annotation_context.rs b/crates/store/re_types/src/archetypes/annotation_context.rs index e9acbef718228..be29a0b32ebb5 100644 --- a/crates/store/re_types/src/archetypes/annotation_context.rs +++ b/crates/store/re_types/src/archetypes/annotation_context.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -136,9 +136,9 @@ impl ::re_types_core::Archetype for AnnotationContext { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: AnnotationContextIndicator = AnnotationContextIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + AnnotationContextIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -179,7 +179,7 @@ impl ::re_types_core::AsComponents for AnnotationContext { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.context.clone()] + [Some(Self::indicator()), self.context.clone()] .into_iter() .flatten() .collect() @@ -237,9 +237,12 @@ impl AnnotationContext { .context .map(|context| context.partitioned(_lengths.clone())) .transpose()?]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/arrows2d.rs b/crates/store/re_types/src/archetypes/arrows2d.rs index cbfc5d4c0ca68..314c2278a6d51 100644 --- a/crates/store/re_types/src/archetypes/arrows2d.rs +++ b/crates/store/re_types/src/archetypes/arrows2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -239,9 +239,9 @@ impl ::re_types_core::Archetype for Arrows2D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Arrows2DIndicator = Arrows2DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Arrows2DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -319,7 +319,7 @@ impl ::re_types_core::AsComponents for Arrows2D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.vectors.clone(), self.origins.clone(), self.radii.clone(), @@ -445,9 +445,12 @@ impl Arrows2D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/arrows3d.rs b/crates/store/re_types/src/archetypes/arrows3d.rs index 639cfdf98fc21..016c839f1b19a 100644 --- a/crates/store/re_types/src/archetypes/arrows3d.rs +++ b/crates/store/re_types/src/archetypes/arrows3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -235,9 +235,9 @@ impl ::re_types_core::Archetype for Arrows3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Arrows3DIndicator = Arrows3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Arrows3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -309,7 +309,7 @@ impl ::re_types_core::AsComponents for Arrows3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.vectors.clone(), self.origins.clone(), self.radii.clone(), @@ -426,9 +426,12 @@ impl Arrows3D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/asset3d.rs b/crates/store/re_types/src/archetypes/asset3d.rs index 8dd082075380e..12710e673210c 100644 --- a/crates/store/re_types/src/archetypes/asset3d.rs +++ b/crates/store/re_types/src/archetypes/asset3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -166,9 +166,9 @@ impl ::re_types_core::Archetype for Asset3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Asset3DIndicator = Asset3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Asset3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -224,7 +224,7 @@ impl ::re_types_core::AsComponents for Asset3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.blob.clone(), self.media_type.clone(), self.albedo_factor.clone(), @@ -303,9 +303,12 @@ impl Asset3D { .map(|albedo_factor| albedo_factor.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/asset_video.rs b/crates/store/re_types/src/archetypes/asset_video.rs index af28237a56632..599410bc43344 100644 --- a/crates/store/re_types/src/archetypes/asset_video.rs +++ b/crates/store/re_types/src/archetypes/asset_video.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -215,9 +215,9 @@ impl ::re_types_core::Archetype for AssetVideo { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: AssetVideoIndicator = AssetVideoIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + AssetVideoIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -264,7 +264,7 @@ impl ::re_types_core::AsComponents for AssetVideo { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.blob.clone(), self.media_type.clone(), ] @@ -334,9 +334,12 @@ impl AssetVideo { .map(|media_type| media_type.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/bar_chart.rs b/crates/store/re_types/src/archetypes/bar_chart.rs index 377d8ad291f2a..73aab4c414e98 100644 --- a/crates/store/re_types/src/archetypes/bar_chart.rs +++ b/crates/store/re_types/src/archetypes/bar_chart.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -127,9 +127,9 @@ impl ::re_types_core::Archetype for BarChart { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: BarChartIndicator = BarChartIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + BarChartIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -174,7 +174,7 @@ impl ::re_types_core::AsComponents for BarChart { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.values.clone(), self.color.clone(), ] @@ -244,9 +244,12 @@ impl BarChart { .map(|color| color.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/boxes2d.rs b/crates/store/re_types/src/archetypes/boxes2d.rs index 9bdd22e0adedf..0e522357e0983 100644 --- a/crates/store/re_types/src/archetypes/boxes2d.rs +++ b/crates/store/re_types/src/archetypes/boxes2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -232,9 +232,9 @@ impl ::re_types_core::Archetype for Boxes2D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Boxes2DIndicator = Boxes2DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Boxes2DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -314,7 +314,7 @@ impl ::re_types_core::AsComponents for Boxes2D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.half_sizes.clone(), self.centers.clone(), self.colors.clone(), @@ -440,9 +440,12 @@ impl Boxes2D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/boxes3d.rs b/crates/store/re_types/src/archetypes/boxes3d.rs index 00dbb04ac9fde..cd9985c69c990 100644 --- a/crates/store/re_types/src/archetypes/boxes3d.rs +++ b/crates/store/re_types/src/archetypes/boxes3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -286,9 +286,9 @@ impl ::re_types_core::Archetype for Boxes3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Boxes3DIndicator = Boxes3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Boxes3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -383,7 +383,7 @@ impl ::re_types_core::AsComponents for Boxes3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.half_sizes.clone(), self.centers.clone(), self.rotation_axis_angles.clone(), @@ -527,9 +527,12 @@ impl Boxes3D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/capsules3d.rs b/crates/store/re_types/src/archetypes/capsules3d.rs index 1b946d78ae3b1..041cdf719f3b3 100644 --- a/crates/store/re_types/src/archetypes/capsules3d.rs +++ b/crates/store/re_types/src/archetypes/capsules3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -280,9 +280,9 @@ impl ::re_types_core::Archetype for Capsules3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Capsules3DIndicator = Capsules3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Capsules3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -371,7 +371,7 @@ impl ::re_types_core::AsComponents for Capsules3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.lengths.clone(), self.radii.clone(), self.translations.clone(), @@ -507,9 +507,12 @@ impl Capsules3D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/depth_image.rs b/crates/store/re_types/src/archetypes/depth_image.rs index d7ea860b2011c..3f6bbcc7cb0f0 100644 --- a/crates/store/re_types/src/archetypes/depth_image.rs +++ b/crates/store/re_types/src/archetypes/depth_image.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -254,9 +254,9 @@ impl ::re_types_core::Archetype for DepthImage { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: DepthImageIndicator = DepthImageIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + DepthImageIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -330,7 +330,7 @@ impl ::re_types_core::AsComponents for DepthImage { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.buffer.clone(), self.format.clone(), self.meter.clone(), @@ -448,9 +448,12 @@ impl DepthImage { .map(|draw_order| draw_order.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/ellipsoids3d.rs b/crates/store/re_types/src/archetypes/ellipsoids3d.rs index 4a8a434469ea8..08ab7a96c9075 100644 --- a/crates/store/re_types/src/archetypes/ellipsoids3d.rs +++ b/crates/store/re_types/src/archetypes/ellipsoids3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -301,9 +301,9 @@ impl ::re_types_core::Archetype for Ellipsoids3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Ellipsoids3DIndicator = Ellipsoids3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Ellipsoids3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -400,7 +400,7 @@ impl ::re_types_core::AsComponents for Ellipsoids3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.half_sizes.clone(), self.centers.clone(), self.rotation_axis_angles.clone(), @@ -544,9 +544,12 @@ impl Ellipsoids3D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/encoded_image.rs b/crates/store/re_types/src/archetypes/encoded_image.rs index 7e09ca71787c0..07a3321613e0e 100644 --- a/crates/store/re_types/src/archetypes/encoded_image.rs +++ b/crates/store/re_types/src/archetypes/encoded_image.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -170,9 +170,9 @@ impl ::re_types_core::Archetype for EncodedImage { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: EncodedImageIndicator = EncodedImageIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + EncodedImageIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -232,7 +232,7 @@ impl ::re_types_core::AsComponents for EncodedImage { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.blob.clone(), self.media_type.clone(), self.opacity.clone(), @@ -320,9 +320,12 @@ impl EncodedImage { .map(|draw_order| draw_order.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/geo_line_strings.rs b/crates/store/re_types/src/archetypes/geo_line_strings.rs index d1d161167f57b..72c6e1bea7ca4 100644 --- a/crates/store/re_types/src/archetypes/geo_line_strings.rs +++ b/crates/store/re_types/src/archetypes/geo_line_strings.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -158,9 +158,9 @@ impl ::re_types_core::Archetype for GeoLineStrings { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: GeoLineStringsIndicator = GeoLineStringsIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + GeoLineStringsIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -214,7 +214,7 @@ impl ::re_types_core::AsComponents for GeoLineStrings { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.line_strings.clone(), self.radii.clone(), self.colors.clone(), @@ -295,9 +295,12 @@ impl GeoLineStrings { .map(|colors| colors.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/geo_points.rs b/crates/store/re_types/src/archetypes/geo_points.rs index 53e6aa5b55a6d..bd4dd0d76586a 100644 --- a/crates/store/re_types/src/archetypes/geo_points.rs +++ b/crates/store/re_types/src/archetypes/geo_points.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -165,9 +165,9 @@ impl ::re_types_core::Archetype for GeoPoints { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: GeoPointsIndicator = GeoPointsIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + GeoPointsIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -227,7 +227,7 @@ impl ::re_types_core::AsComponents for GeoPoints { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.positions.clone(), self.radii.clone(), self.colors.clone(), @@ -317,9 +317,12 @@ impl GeoPoints { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/graph_edges.rs b/crates/store/re_types/src/archetypes/graph_edges.rs index d95604aad6ea6..e884a59d97a6f 100644 --- a/crates/store/re_types/src/archetypes/graph_edges.rs +++ b/crates/store/re_types/src/archetypes/graph_edges.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -139,9 +139,9 @@ impl ::re_types_core::Archetype for GraphEdges { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: GraphEdgesIndicator = GraphEdgesIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + GraphEdgesIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -188,7 +188,7 @@ impl ::re_types_core::AsComponents for GraphEdges { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.edges.clone(), self.graph_type.clone(), ] @@ -258,9 +258,12 @@ impl GraphEdges { .map(|graph_type| graph_type.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/graph_nodes.rs b/crates/store/re_types/src/archetypes/graph_nodes.rs index c4fb5fc2559bf..c31e12399ea0c 100644 --- a/crates/store/re_types/src/archetypes/graph_nodes.rs +++ b/crates/store/re_types/src/archetypes/graph_nodes.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -194,9 +194,9 @@ impl ::re_types_core::Archetype for GraphNodes { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: GraphNodesIndicator = GraphNodesIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + GraphNodesIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -264,7 +264,7 @@ impl ::re_types_core::AsComponents for GraphNodes { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.node_ids.clone(), self.positions.clone(), self.colors.clone(), @@ -372,9 +372,12 @@ impl GraphNodes { .map(|radii| radii.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/image.rs b/crates/store/re_types/src/archetypes/image.rs index d792233455139..fdd684410c87c 100644 --- a/crates/store/re_types/src/archetypes/image.rs +++ b/crates/store/re_types/src/archetypes/image.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -239,9 +239,9 @@ impl ::re_types_core::Archetype for Image { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ImageIndicator = ImageIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ImageIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -299,7 +299,7 @@ impl ::re_types_core::AsComponents for Image { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.buffer.clone(), self.format.clone(), self.opacity.clone(), @@ -390,9 +390,12 @@ impl Image { .map(|draw_order| draw_order.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/instance_poses3d.rs b/crates/store/re_types/src/archetypes/instance_poses3d.rs index 8b555d2e12a38..2a6eaef925a9f 100644 --- a/crates/store/re_types/src/archetypes/instance_poses3d.rs +++ b/crates/store/re_types/src/archetypes/instance_poses3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -221,9 +221,9 @@ impl ::re_types_core::Archetype for InstancePoses3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: InstancePoses3DIndicator = InstancePoses3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + InstancePoses3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -292,7 +292,7 @@ impl ::re_types_core::AsComponents for InstancePoses3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.translations.clone(), self.rotation_axis_angles.clone(), self.quaternions.clone(), @@ -389,9 +389,12 @@ impl InstancePoses3D { .map(|mat3x3| mat3x3.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/line_strips2d.rs b/crates/store/re_types/src/archetypes/line_strips2d.rs index 71e22fdca3194..02aa8e385c6c9 100644 --- a/crates/store/re_types/src/archetypes/line_strips2d.rs +++ b/crates/store/re_types/src/archetypes/line_strips2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -256,9 +256,9 @@ impl ::re_types_core::Archetype for LineStrips2D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: LineStrips2DIndicator = LineStrips2DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + LineStrips2DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -332,7 +332,7 @@ impl ::re_types_core::AsComponents for LineStrips2D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.strips.clone(), self.radii.clone(), self.colors.clone(), @@ -449,9 +449,12 @@ impl LineStrips2D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/line_strips3d.rs b/crates/store/re_types/src/archetypes/line_strips3d.rs index 90acec81d27d2..2d422eb12d5c3 100644 --- a/crates/store/re_types/src/archetypes/line_strips3d.rs +++ b/crates/store/re_types/src/archetypes/line_strips3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -252,9 +252,9 @@ impl ::re_types_core::Archetype for LineStrips3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: LineStrips3DIndicator = LineStrips3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + LineStrips3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -322,7 +322,7 @@ impl ::re_types_core::AsComponents for LineStrips3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.strips.clone(), self.radii.clone(), self.colors.clone(), @@ -430,9 +430,12 @@ impl LineStrips3D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/mesh3d.rs b/crates/store/re_types/src/archetypes/mesh3d.rs index 2d29473ea15b2..311466824b9e6 100644 --- a/crates/store/re_types/src/archetypes/mesh3d.rs +++ b/crates/store/re_types/src/archetypes/mesh3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -309,9 +309,9 @@ impl ::re_types_core::Archetype for Mesh3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Mesh3DIndicator = Mesh3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Mesh3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -411,7 +411,7 @@ impl ::re_types_core::AsComponents for Mesh3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.vertex_positions.clone(), self.triangle_indices.clone(), self.vertex_normals.clone(), @@ -549,9 +549,12 @@ impl Mesh3D { .map(|class_ids| class_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/pinhole.rs b/crates/store/re_types/src/archetypes/pinhole.rs index bba51d6454bb4..0fd62f78ab678 100644 --- a/crates/store/re_types/src/archetypes/pinhole.rs +++ b/crates/store/re_types/src/archetypes/pinhole.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -240,9 +240,9 @@ impl ::re_types_core::Archetype for Pinhole { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: PinholeIndicator = PinholeIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + PinholeIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -309,7 +309,7 @@ impl ::re_types_core::AsComponents for Pinhole { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.image_from_camera.clone(), self.resolution.clone(), self.camera_xyz.clone(), @@ -400,9 +400,12 @@ impl Pinhole { .map(|image_plane_distance| image_plane_distance.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/points2d.rs b/crates/store/re_types/src/archetypes/points2d.rs index d87a3e6492e74..781d412a177c6 100644 --- a/crates/store/re_types/src/archetypes/points2d.rs +++ b/crates/store/re_types/src/archetypes/points2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -289,9 +289,9 @@ impl ::re_types_core::Archetype for Points2D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Points2DIndicator = Points2DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Points2DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -373,7 +373,7 @@ impl ::re_types_core::AsComponents for Points2D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.positions.clone(), self.radii.clone(), self.colors.clone(), @@ -499,9 +499,12 @@ impl Points2D { .map(|keypoint_ids| keypoint_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/points3d.rs b/crates/store/re_types/src/archetypes/points3d.rs index 57f9fd59cb7a0..c0c8e5fdccd0e 100644 --- a/crates/store/re_types/src/archetypes/points3d.rs +++ b/crates/store/re_types/src/archetypes/points3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -317,9 +317,9 @@ impl ::re_types_core::Archetype for Points3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Points3DIndicator = Points3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Points3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -395,7 +395,7 @@ impl ::re_types_core::AsComponents for Points3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.positions.clone(), self.radii.clone(), self.colors.clone(), @@ -512,9 +512,12 @@ impl Points3D { .map(|keypoint_ids| keypoint_ids.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/scalar.rs b/crates/store/re_types/src/archetypes/scalar.rs index 9812ab5f8c6a9..7ed63c34b3ed9 100644 --- a/crates/store/re_types/src/archetypes/scalar.rs +++ b/crates/store/re_types/src/archetypes/scalar.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -148,9 +148,9 @@ impl ::re_types_core::Archetype for Scalar { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ScalarIndicator = ScalarIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ScalarIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -191,7 +191,7 @@ impl ::re_types_core::AsComponents for Scalar { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.scalar.clone()] + [Some(Self::indicator()), self.scalar.clone()] .into_iter() .flatten() .collect() @@ -249,9 +249,12 @@ impl Scalar { .scalar .map(|scalar| scalar.partitioned(_lengths.clone())) .transpose()?]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/segmentation_image.rs b/crates/store/re_types/src/archetypes/segmentation_image.rs index d8ac15cac0e8d..4f5df593df8b9 100644 --- a/crates/store/re_types/src/archetypes/segmentation_image.rs +++ b/crates/store/re_types/src/archetypes/segmentation_image.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -187,9 +187,9 @@ impl ::re_types_core::Archetype for SegmentationImage { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: SegmentationImageIndicator = SegmentationImageIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + SegmentationImageIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -247,7 +247,7 @@ impl ::re_types_core::AsComponents for SegmentationImage { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.buffer.clone(), self.format.clone(), self.opacity.clone(), @@ -338,9 +338,12 @@ impl SegmentationImage { .map(|draw_order| draw_order.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/series_line.rs b/crates/store/re_types/src/archetypes/series_line.rs index b11c4d3e81154..dcc52534c9a00 100644 --- a/crates/store/re_types/src/archetypes/series_line.rs +++ b/crates/store/re_types/src/archetypes/series_line.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -191,9 +191,9 @@ impl ::re_types_core::Archetype for SeriesLine { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: SeriesLineIndicator = SeriesLineIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + SeriesLineIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -251,7 +251,7 @@ impl ::re_types_core::AsComponents for SeriesLine { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.color.clone(), self.width.clone(), self.name.clone(), @@ -339,9 +339,12 @@ impl SeriesLine { .map(|aggregation_policy| aggregation_policy.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/series_point.rs b/crates/store/re_types/src/archetypes/series_point.rs index a4bac5c9a415c..36dd64e8d00f9 100644 --- a/crates/store/re_types/src/archetypes/series_point.rs +++ b/crates/store/re_types/src/archetypes/series_point.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -189,9 +189,9 @@ impl ::re_types_core::Archetype for SeriesPoint { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: SeriesPointIndicator = SeriesPointIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + SeriesPointIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -249,7 +249,7 @@ impl ::re_types_core::AsComponents for SeriesPoint { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.color.clone(), self.marker.clone(), self.name.clone(), @@ -337,9 +337,12 @@ impl SeriesPoint { .map(|marker_size| marker_size.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/tensor.rs b/crates/store/re_types/src/archetypes/tensor.rs index 3dcade4ddbf41..9b6c8800fc9ae 100644 --- a/crates/store/re_types/src/archetypes/tensor.rs +++ b/crates/store/re_types/src/archetypes/tensor.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -139,9 +139,9 @@ impl ::re_types_core::Archetype for Tensor { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: TensorIndicator = TensorIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + TensorIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -188,7 +188,7 @@ impl ::re_types_core::AsComponents for Tensor { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.data.clone(), self.value_range.clone(), ] @@ -258,9 +258,12 @@ impl Tensor { .map(|value_range| value_range.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/text_document.rs b/crates/store/re_types/src/archetypes/text_document.rs index 20c17b50a235f..2a3ff730c2bc3 100644 --- a/crates/store/re_types/src/archetypes/text_document.rs +++ b/crates/store/re_types/src/archetypes/text_document.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -174,9 +174,9 @@ impl ::re_types_core::Archetype for TextDocument { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: TextDocumentIndicator = TextDocumentIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + TextDocumentIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -223,7 +223,7 @@ impl ::re_types_core::AsComponents for TextDocument { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.text.clone(), self.media_type.clone(), ] @@ -293,9 +293,12 @@ impl TextDocument { .map(|media_type| media_type.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/text_log.rs b/crates/store/re_types/src/archetypes/text_log.rs index 46760042aed4f..8486d60d5cb9d 100644 --- a/crates/store/re_types/src/archetypes/text_log.rs +++ b/crates/store/re_types/src/archetypes/text_log.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -155,9 +155,9 @@ impl ::re_types_core::Archetype for TextLog { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: TextLogIndicator = TextLogIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + TextLogIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -205,7 +205,7 @@ impl ::re_types_core::AsComponents for TextLog { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.text.clone(), self.level.clone(), self.color.clone(), @@ -284,9 +284,12 @@ impl TextLog { .map(|color| color.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/transform3d.rs b/crates/store/re_types/src/archetypes/transform3d.rs index 05750fd71694b..b6cb933da87a5 100644 --- a/crates/store/re_types/src/archetypes/transform3d.rs +++ b/crates/store/re_types/src/archetypes/transform3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -330,9 +330,9 @@ impl ::re_types_core::Archetype for Transform3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: Transform3DIndicator = Transform3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + Transform3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -408,7 +408,7 @@ impl ::re_types_core::AsComponents for Transform3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.translation.clone(), self.rotation_axis_angle.clone(), self.quaternion.clone(), @@ -509,9 +509,12 @@ impl Transform3D { .map(|axis_length| axis_length.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/video_frame_reference.rs b/crates/store/re_types/src/archetypes/video_frame_reference.rs index ba333b4b89d9b..4e154d01dd3dc 100644 --- a/crates/store/re_types/src/archetypes/video_frame_reference.rs +++ b/crates/store/re_types/src/archetypes/video_frame_reference.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -218,9 +218,9 @@ impl ::re_types_core::Archetype for VideoFrameReference { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: VideoFrameReferenceIndicator = VideoFrameReferenceIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + VideoFrameReferenceIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -272,7 +272,7 @@ impl ::re_types_core::AsComponents for VideoFrameReference { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.timestamp.clone(), self.video_reference.clone(), ] @@ -342,9 +342,12 @@ impl VideoFrameReference { .map(|video_reference| video_reference.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/archetypes/view_coordinates.rs b/crates/store/re_types/src/archetypes/view_coordinates.rs index 49611969a09de..73be7adb786f4 100644 --- a/crates/store/re_types/src/archetypes/view_coordinates.rs +++ b/crates/store/re_types/src/archetypes/view_coordinates.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -127,9 +127,9 @@ impl ::re_types_core::Archetype for ViewCoordinates { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ViewCoordinatesIndicator = ViewCoordinatesIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ViewCoordinatesIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -170,7 +170,7 @@ impl ::re_types_core::AsComponents for ViewCoordinates { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.xyz.clone()] + [Some(Self::indicator()), self.xyz.clone()] .into_iter() .flatten() .collect() @@ -228,9 +228,12 @@ impl ViewCoordinates { .xyz .map(|xyz| xyz.partitioned(_lengths.clone())) .transpose()?]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/blueprint/archetypes/background.rs b/crates/store/re_types/src/blueprint/archetypes/background.rs index edb3d0f3287d7..65f8e845b3dd7 100644 --- a/crates/store/re_types/src/blueprint/archetypes/background.rs +++ b/crates/store/re_types/src/blueprint/archetypes/background.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -100,9 +100,9 @@ impl ::re_types_core::Archetype for Background { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: BackgroundIndicator = BackgroundIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + BackgroundIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -147,7 +147,7 @@ impl ::re_types_core::AsComponents for Background { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.kind.clone(), self.color.clone(), ] diff --git a/crates/store/re_types/src/blueprint/archetypes/container_blueprint.rs b/crates/store/re_types/src/blueprint/archetypes/container_blueprint.rs index a24484a277363..dabf3d20a6ceb 100644 --- a/crates/store/re_types/src/blueprint/archetypes/container_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/container_blueprint.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -211,9 +211,9 @@ impl ::re_types_core::Archetype for ContainerBlueprint { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ContainerBlueprintIndicator = ContainerBlueprintIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ContainerBlueprintIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -297,7 +297,7 @@ impl ::re_types_core::AsComponents for ContainerBlueprint { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.container_kind.clone(), self.display_name.clone(), self.contents.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/dataframe_query.rs b/crates/store/re_types/src/blueprint/archetypes/dataframe_query.rs index ec77a32087d3f..ea3632ac58f88 100644 --- a/crates/store/re_types/src/blueprint/archetypes/dataframe_query.rs +++ b/crates/store/re_types/src/blueprint/archetypes/dataframe_query.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -154,9 +154,9 @@ impl ::re_types_core::Archetype for DataframeQuery { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: DataframeQueryIndicator = DataframeQueryIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + DataframeQueryIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -222,7 +222,7 @@ impl ::re_types_core::AsComponents for DataframeQuery { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.timeline.clone(), self.filter_by_range.clone(), self.filter_is_not_null.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/force_center.rs b/crates/store/re_types/src/blueprint/archetypes/force_center.rs index 7b59245112c90..0abf50015b416 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_center.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_center.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -107,9 +107,9 @@ impl ::re_types_core::Archetype for ForceCenter { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ForceCenterIndicator = ForceCenterIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ForceCenterIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -154,7 +154,7 @@ impl ::re_types_core::AsComponents for ForceCenter { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.enabled.clone(), self.strength.clone(), ] diff --git a/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs b/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs index 227da89c2ecab..996a3beafd679 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -125,9 +125,9 @@ impl ::re_types_core::Archetype for ForceCollisionRadius { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ForceCollisionRadiusIndicator = ForceCollisionRadiusIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ForceCollisionRadiusIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -181,7 +181,7 @@ impl ::re_types_core::AsComponents for ForceCollisionRadius { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.enabled.clone(), self.strength.clone(), self.iterations.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/force_link.rs b/crates/store/re_types/src/blueprint/archetypes/force_link.rs index b2b5dd1d045e5..9a5bc56db4c79 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_link.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_link.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -124,9 +124,9 @@ impl ::re_types_core::Archetype for ForceLink { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ForceLinkIndicator = ForceLinkIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ForceLinkIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -180,7 +180,7 @@ impl ::re_types_core::AsComponents for ForceLink { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.enabled.clone(), self.distance.clone(), self.iterations.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs b/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs index 399a1e0c98e4c..f9329cbc2ffc7 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -112,9 +112,9 @@ impl ::re_types_core::Archetype for ForceManyBody { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ForceManyBodyIndicator = ForceManyBodyIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ForceManyBodyIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -159,7 +159,7 @@ impl ::re_types_core::AsComponents for ForceManyBody { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.enabled.clone(), self.strength.clone(), ] diff --git a/crates/store/re_types/src/blueprint/archetypes/force_position.rs b/crates/store/re_types/src/blueprint/archetypes/force_position.rs index ad4a4d3360f08..9af664abb1dd9 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_position.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_position.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -122,9 +122,9 @@ impl ::re_types_core::Archetype for ForcePosition { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ForcePositionIndicator = ForcePositionIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ForcePositionIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -176,7 +176,7 @@ impl ::re_types_core::AsComponents for ForcePosition { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.enabled.clone(), self.strength.clone(), self.position.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/line_grid3d.rs b/crates/store/re_types/src/blueprint/archetypes/line_grid3d.rs index e9d5a7582e8aa..d6dacdb36c47b 100644 --- a/crates/store/re_types/src/blueprint/archetypes/line_grid3d.rs +++ b/crates/store/re_types/src/blueprint/archetypes/line_grid3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -162,9 +162,9 @@ impl ::re_types_core::Archetype for LineGrid3D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: LineGrid3DIndicator = LineGrid3DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + LineGrid3DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -226,7 +226,7 @@ impl ::re_types_core::AsComponents for LineGrid3D { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.visible.clone(), self.spacing.clone(), self.plane.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/map_background.rs b/crates/store/re_types/src/blueprint/archetypes/map_background.rs index dd19b53673ae5..4debe30e4f196 100644 --- a/crates/store/re_types/src/blueprint/archetypes/map_background.rs +++ b/crates/store/re_types/src/blueprint/archetypes/map_background.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -88,9 +88,9 @@ impl ::re_types_core::Archetype for MapBackground { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: MapBackgroundIndicator = MapBackgroundIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + MapBackgroundIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -131,7 +131,7 @@ impl ::re_types_core::AsComponents for MapBackground { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.provider.clone()] + [Some(Self::indicator()), self.provider.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/map_zoom.rs b/crates/store/re_types/src/blueprint/archetypes/map_zoom.rs index 5f8ac27146404..05ddbb94fb6c2 100644 --- a/crates/store/re_types/src/blueprint/archetypes/map_zoom.rs +++ b/crates/store/re_types/src/blueprint/archetypes/map_zoom.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -83,9 +83,9 @@ impl ::re_types_core::Archetype for MapZoom { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: MapZoomIndicator = MapZoomIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + MapZoomIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -126,7 +126,7 @@ impl ::re_types_core::AsComponents for MapZoom { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.zoom.clone()] + [Some(Self::indicator()), self.zoom.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/near_clip_plane.rs b/crates/store/re_types/src/blueprint/archetypes/near_clip_plane.rs index 8aa5043ad6437..e7ec2923170ff 100644 --- a/crates/store/re_types/src/blueprint/archetypes/near_clip_plane.rs +++ b/crates/store/re_types/src/blueprint/archetypes/near_clip_plane.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -88,9 +88,9 @@ impl ::re_types_core::Archetype for NearClipPlane { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: NearClipPlaneIndicator = NearClipPlaneIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + NearClipPlaneIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -133,7 +133,7 @@ impl ::re_types_core::AsComponents for NearClipPlane { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.near_clip_plane.clone()] + [Some(Self::indicator()), self.near_clip_plane.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/panel_blueprint.rs b/crates/store/re_types/src/blueprint/archetypes/panel_blueprint.rs index 8453243f90fef..2cf4acb73bcb8 100644 --- a/crates/store/re_types/src/blueprint/archetypes/panel_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/panel_blueprint.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -86,9 +86,9 @@ impl ::re_types_core::Archetype for PanelBlueprint { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: PanelBlueprintIndicator = PanelBlueprintIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + PanelBlueprintIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -129,7 +129,7 @@ impl ::re_types_core::AsComponents for PanelBlueprint { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.state.clone()] + [Some(Self::indicator()), self.state.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/plot_legend.rs b/crates/store/re_types/src/blueprint/archetypes/plot_legend.rs index 1182b1644874c..f4887e9cc6655 100644 --- a/crates/store/re_types/src/blueprint/archetypes/plot_legend.rs +++ b/crates/store/re_types/src/blueprint/archetypes/plot_legend.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -109,9 +109,9 @@ impl ::re_types_core::Archetype for PlotLegend { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: PlotLegendIndicator = PlotLegendIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + PlotLegendIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -156,7 +156,7 @@ impl ::re_types_core::AsComponents for PlotLegend { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.corner.clone(), self.visible.clone(), ] diff --git a/crates/store/re_types/src/blueprint/archetypes/scalar_axis.rs b/crates/store/re_types/src/blueprint/archetypes/scalar_axis.rs index 506b26ba017df..28adf811e2f82 100644 --- a/crates/store/re_types/src/blueprint/archetypes/scalar_axis.rs +++ b/crates/store/re_types/src/blueprint/archetypes/scalar_axis.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -107,9 +107,9 @@ impl ::re_types_core::Archetype for ScalarAxis { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ScalarAxisIndicator = ScalarAxisIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ScalarAxisIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -156,7 +156,7 @@ impl ::re_types_core::AsComponents for ScalarAxis { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.range.clone(), self.zoom_lock.clone(), ] diff --git a/crates/store/re_types/src/blueprint/archetypes/tensor_scalar_mapping.rs b/crates/store/re_types/src/blueprint/archetypes/tensor_scalar_mapping.rs index dc2e34caa03df..11e2b72a182a4 100644 --- a/crates/store/re_types/src/blueprint/archetypes/tensor_scalar_mapping.rs +++ b/crates/store/re_types/src/blueprint/archetypes/tensor_scalar_mapping.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -129,9 +129,9 @@ impl ::re_types_core::Archetype for TensorScalarMapping { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: TensorScalarMappingIndicator = TensorScalarMappingIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + TensorScalarMappingIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -185,7 +185,7 @@ impl ::re_types_core::AsComponents for TensorScalarMapping { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.mag_filter.clone(), self.colormap.clone(), self.gamma.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/tensor_slice_selection.rs b/crates/store/re_types/src/blueprint/archetypes/tensor_slice_selection.rs index 60ef51ce0bb47..3aa2104c64d4d 100644 --- a/crates/store/re_types/src/blueprint/archetypes/tensor_slice_selection.rs +++ b/crates/store/re_types/src/blueprint/archetypes/tensor_slice_selection.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -146,9 +146,9 @@ impl ::re_types_core::Archetype for TensorSliceSelection { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: TensorSliceSelectionIndicator = TensorSliceSelectionIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + TensorSliceSelectionIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -204,7 +204,7 @@ impl ::re_types_core::AsComponents for TensorSliceSelection { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.width.clone(), self.height.clone(), self.indices.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/tensor_view_fit.rs b/crates/store/re_types/src/blueprint/archetypes/tensor_view_fit.rs index ef0938daa70ab..95092002e6dd1 100644 --- a/crates/store/re_types/src/blueprint/archetypes/tensor_view_fit.rs +++ b/crates/store/re_types/src/blueprint/archetypes/tensor_view_fit.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -86,9 +86,9 @@ impl ::re_types_core::Archetype for TensorViewFit { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: TensorViewFitIndicator = TensorViewFitIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + TensorViewFitIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -129,7 +129,7 @@ impl ::re_types_core::AsComponents for TensorViewFit { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.scaling.clone()] + [Some(Self::indicator()), self.scaling.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/view_blueprint.rs b/crates/store/re_types/src/blueprint/archetypes/view_blueprint.rs index 21530cc8f9043..86ad19c462f46 100644 --- a/crates/store/re_types/src/blueprint/archetypes/view_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/view_blueprint.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -142,9 +142,9 @@ impl ::re_types_core::Archetype for ViewBlueprint { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ViewBlueprintIndicator = ViewBlueprintIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ViewBlueprintIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -206,7 +206,7 @@ impl ::re_types_core::AsComponents for ViewBlueprint { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.class_identifier.clone(), self.display_name.clone(), self.space_origin.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/view_contents.rs b/crates/store/re_types/src/blueprint/archetypes/view_contents.rs index 1a767693fe748..31aa8cb92a726 100644 --- a/crates/store/re_types/src/blueprint/archetypes/view_contents.rs +++ b/crates/store/re_types/src/blueprint/archetypes/view_contents.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -125,9 +125,9 @@ impl ::re_types_core::Archetype for ViewContents { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ViewContentsIndicator = ViewContentsIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ViewContentsIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -168,7 +168,7 @@ impl ::re_types_core::AsComponents for ViewContents { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.query.clone()] + [Some(Self::indicator()), self.query.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/viewport_blueprint.rs b/crates/store/re_types/src/blueprint/archetypes/viewport_blueprint.rs index cd2b1d05ee0c8..adab8ee8d0d4c 100644 --- a/crates/store/re_types/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/viewport_blueprint.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -162,9 +162,9 @@ impl ::re_types_core::Archetype for ViewportBlueprint { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ViewportBlueprintIndicator = ViewportBlueprintIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ViewportBlueprintIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -237,7 +237,7 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.root_container.clone(), self.maximized.clone(), self.auto_layout.clone(), diff --git a/crates/store/re_types/src/blueprint/archetypes/visible_time_ranges.rs b/crates/store/re_types/src/blueprint/archetypes/visible_time_ranges.rs index e55280213b662..9fee57b8e6675 100644 --- a/crates/store/re_types/src/blueprint/archetypes/visible_time_ranges.rs +++ b/crates/store/re_types/src/blueprint/archetypes/visible_time_ranges.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -96,9 +96,9 @@ impl ::re_types_core::Archetype for VisibleTimeRanges { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: VisibleTimeRangesIndicator = VisibleTimeRangesIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + VisibleTimeRangesIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -139,7 +139,7 @@ impl ::re_types_core::AsComponents for VisibleTimeRanges { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.ranges.clone()] + [Some(Self::indicator()), self.ranges.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/archetypes/visual_bounds2d.rs b/crates/store/re_types/src/blueprint/archetypes/visual_bounds2d.rs index 6efa80af2144b..cbc4537d2f759 100644 --- a/crates/store/re_types/src/blueprint/archetypes/visual_bounds2d.rs +++ b/crates/store/re_types/src/blueprint/archetypes/visual_bounds2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -94,9 +94,9 @@ impl ::re_types_core::Archetype for VisualBounds2D { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: VisualBounds2DIndicator = VisualBounds2DIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + VisualBounds2DIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -137,7 +137,7 @@ impl ::re_types_core::AsComponents for VisualBounds2D { #[inline] fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; - [Self::indicator().serialized(), self.range.clone()] + [Some(Self::indicator()), self.range.clone()] .into_iter() .flatten() .collect() diff --git a/crates/store/re_types/src/blueprint/components/active_tab.rs b/crates/store/re_types/src/blueprint/components/active_tab.rs index a81edd2c15507..3ea11f329ba95 100644 --- a/crates/store/re_types/src/blueprint/components/active_tab.rs +++ b/crates/store/re_types/src/blueprint/components/active_tab.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/apply_latest_at.rs b/crates/store/re_types/src/blueprint/components/apply_latest_at.rs index 3e58e4cc361b7..d263ea194f3b9 100644 --- a/crates/store/re_types/src/blueprint/components/apply_latest_at.rs +++ b/crates/store/re_types/src/blueprint/components/apply_latest_at.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/auto_layout.rs b/crates/store/re_types/src/blueprint/components/auto_layout.rs index ee60dab85c202..376d0e9bce8dd 100644 --- a/crates/store/re_types/src/blueprint/components/auto_layout.rs +++ b/crates/store/re_types/src/blueprint/components/auto_layout.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/auto_views.rs b/crates/store/re_types/src/blueprint/components/auto_views.rs index aaec370975f79..ac0331a5c9bd5 100644 --- a/crates/store/re_types/src/blueprint/components/auto_views.rs +++ b/crates/store/re_types/src/blueprint/components/auto_views.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/background_kind.rs b/crates/store/re_types/src/blueprint/components/background_kind.rs index 054075dff6c1f..f03d3b8d357c8 100644 --- a/crates/store/re_types/src/blueprint/components/background_kind.rs +++ b/crates/store/re_types/src/blueprint/components/background_kind.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/column_share.rs b/crates/store/re_types/src/blueprint/components/column_share.rs index 9c69baa202197..227f4b3a37aff 100644 --- a/crates/store/re_types/src/blueprint/components/column_share.rs +++ b/crates/store/re_types/src/blueprint/components/column_share.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/component_column_selector.rs b/crates/store/re_types/src/blueprint/components/component_column_selector.rs index 01d2c62c35104..23dc0bcb2f1f7 100644 --- a/crates/store/re_types/src/blueprint/components/component_column_selector.rs +++ b/crates/store/re_types/src/blueprint/components/component_column_selector.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/container_kind.rs b/crates/store/re_types/src/blueprint/components/container_kind.rs index 2851a649522fe..8575dca39f350 100644 --- a/crates/store/re_types/src/blueprint/components/container_kind.rs +++ b/crates/store/re_types/src/blueprint/components/container_kind.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/corner2d.rs b/crates/store/re_types/src/blueprint/components/corner2d.rs index 81d2daa8b81f4..01038c7c15a4c 100644 --- a/crates/store/re_types/src/blueprint/components/corner2d.rs +++ b/crates/store/re_types/src/blueprint/components/corner2d.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/enabled.rs b/crates/store/re_types/src/blueprint/components/enabled.rs index c1a1c451b7b1d..1d0194071950d 100644 --- a/crates/store/re_types/src/blueprint/components/enabled.rs +++ b/crates/store/re_types/src/blueprint/components/enabled.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/filter_by_range.rs b/crates/store/re_types/src/blueprint/components/filter_by_range.rs index 155c6cbaf25cf..346e3c2dc9c34 100644 --- a/crates/store/re_types/src/blueprint/components/filter_by_range.rs +++ b/crates/store/re_types/src/blueprint/components/filter_by_range.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/filter_is_not_null.rs b/crates/store/re_types/src/blueprint/components/filter_is_not_null.rs index 032d42d206100..5760587766277 100644 --- a/crates/store/re_types/src/blueprint/components/filter_is_not_null.rs +++ b/crates/store/re_types/src/blueprint/components/filter_is_not_null.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/force_distance.rs b/crates/store/re_types/src/blueprint/components/force_distance.rs index 3daf996ac7fcf..a9932a16a5924 100644 --- a/crates/store/re_types/src/blueprint/components/force_distance.rs +++ b/crates/store/re_types/src/blueprint/components/force_distance.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/force_iterations.rs b/crates/store/re_types/src/blueprint/components/force_iterations.rs index 2eba63afc8f08..2d85f9e7d575b 100644 --- a/crates/store/re_types/src/blueprint/components/force_iterations.rs +++ b/crates/store/re_types/src/blueprint/components/force_iterations.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/force_strength.rs b/crates/store/re_types/src/blueprint/components/force_strength.rs index 8411d02f849fb..b7826478cf968 100644 --- a/crates/store/re_types/src/blueprint/components/force_strength.rs +++ b/crates/store/re_types/src/blueprint/components/force_strength.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/grid_columns.rs b/crates/store/re_types/src/blueprint/components/grid_columns.rs index f2f634b313f6b..2e0320a3c1901 100644 --- a/crates/store/re_types/src/blueprint/components/grid_columns.rs +++ b/crates/store/re_types/src/blueprint/components/grid_columns.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/grid_spacing.rs b/crates/store/re_types/src/blueprint/components/grid_spacing.rs index 141f4fc27b5b6..a0d2cb3d6cff6 100644 --- a/crates/store/re_types/src/blueprint/components/grid_spacing.rs +++ b/crates/store/re_types/src/blueprint/components/grid_spacing.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/included_content.rs b/crates/store/re_types/src/blueprint/components/included_content.rs index 1f75942e0d7e7..b1a44078c9b6a 100644 --- a/crates/store/re_types/src/blueprint/components/included_content.rs +++ b/crates/store/re_types/src/blueprint/components/included_content.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/interactive.rs b/crates/store/re_types/src/blueprint/components/interactive.rs index cdf7a9d5901e9..f4d6a54ace486 100644 --- a/crates/store/re_types/src/blueprint/components/interactive.rs +++ b/crates/store/re_types/src/blueprint/components/interactive.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/lock_range_during_zoom.rs b/crates/store/re_types/src/blueprint/components/lock_range_during_zoom.rs index eb96ac39b8a5e..0a1ad3522f6b6 100644 --- a/crates/store/re_types/src/blueprint/components/lock_range_during_zoom.rs +++ b/crates/store/re_types/src/blueprint/components/lock_range_during_zoom.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/map_provider.rs b/crates/store/re_types/src/blueprint/components/map_provider.rs index 08a65c4b46a7f..d3a83f2b1e360 100644 --- a/crates/store/re_types/src/blueprint/components/map_provider.rs +++ b/crates/store/re_types/src/blueprint/components/map_provider.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/near_clip_plane.rs b/crates/store/re_types/src/blueprint/components/near_clip_plane.rs index 6b5e77a57289f..f18821f846824 100644 --- a/crates/store/re_types/src/blueprint/components/near_clip_plane.rs +++ b/crates/store/re_types/src/blueprint/components/near_clip_plane.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/panel_state.rs b/crates/store/re_types/src/blueprint/components/panel_state.rs index e918f1f3098b8..eff28514ebb83 100644 --- a/crates/store/re_types/src/blueprint/components/panel_state.rs +++ b/crates/store/re_types/src/blueprint/components/panel_state.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/query_expression.rs b/crates/store/re_types/src/blueprint/components/query_expression.rs index 8aba7241f6a60..c5548ac7ba60b 100644 --- a/crates/store/re_types/src/blueprint/components/query_expression.rs +++ b/crates/store/re_types/src/blueprint/components/query_expression.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/root_container.rs b/crates/store/re_types/src/blueprint/components/root_container.rs index f7fbe5fcfdb69..dc508b94ddb86 100644 --- a/crates/store/re_types/src/blueprint/components/root_container.rs +++ b/crates/store/re_types/src/blueprint/components/root_container.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/row_share.rs b/crates/store/re_types/src/blueprint/components/row_share.rs index c1bbf8bb310ba..01aff57a7952e 100644 --- a/crates/store/re_types/src/blueprint/components/row_share.rs +++ b/crates/store/re_types/src/blueprint/components/row_share.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/selected_columns.rs b/crates/store/re_types/src/blueprint/components/selected_columns.rs index 6c080b410bd40..bd3a58ab22bbd 100644 --- a/crates/store/re_types/src/blueprint/components/selected_columns.rs +++ b/crates/store/re_types/src/blueprint/components/selected_columns.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/tensor_dimension_index_slider.rs b/crates/store/re_types/src/blueprint/components/tensor_dimension_index_slider.rs index 91aee85a6997a..695cfa719cee4 100644 --- a/crates/store/re_types/src/blueprint/components/tensor_dimension_index_slider.rs +++ b/crates/store/re_types/src/blueprint/components/tensor_dimension_index_slider.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/timeline_name.rs b/crates/store/re_types/src/blueprint/components/timeline_name.rs index 8b2e3ccbac73e..2edd12f5bc36a 100644 --- a/crates/store/re_types/src/blueprint/components/timeline_name.rs +++ b/crates/store/re_types/src/blueprint/components/timeline_name.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/view_class.rs b/crates/store/re_types/src/blueprint/components/view_class.rs index 659b6728122d4..2860077f4f6e4 100644 --- a/crates/store/re_types/src/blueprint/components/view_class.rs +++ b/crates/store/re_types/src/blueprint/components/view_class.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/view_fit.rs b/crates/store/re_types/src/blueprint/components/view_fit.rs index 8dd32122f9146..72de4902c08c8 100644 --- a/crates/store/re_types/src/blueprint/components/view_fit.rs +++ b/crates/store/re_types/src/blueprint/components/view_fit.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/view_maximized.rs b/crates/store/re_types/src/blueprint/components/view_maximized.rs index afd1cdac36e19..f008104f380f8 100644 --- a/crates/store/re_types/src/blueprint/components/view_maximized.rs +++ b/crates/store/re_types/src/blueprint/components/view_maximized.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/view_origin.rs b/crates/store/re_types/src/blueprint/components/view_origin.rs index b76c3e6424468..f500625d34d37 100644 --- a/crates/store/re_types/src/blueprint/components/view_origin.rs +++ b/crates/store/re_types/src/blueprint/components/view_origin.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/viewer_recommendation_hash.rs b/crates/store/re_types/src/blueprint/components/viewer_recommendation_hash.rs index fbf037b847419..4e8d47da6f618 100644 --- a/crates/store/re_types/src/blueprint/components/viewer_recommendation_hash.rs +++ b/crates/store/re_types/src/blueprint/components/viewer_recommendation_hash.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/visible.rs b/crates/store/re_types/src/blueprint/components/visible.rs index 838565bff5e94..5b587ece4423f 100644 --- a/crates/store/re_types/src/blueprint/components/visible.rs +++ b/crates/store/re_types/src/blueprint/components/visible.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/visible_time_range.rs b/crates/store/re_types/src/blueprint/components/visible_time_range.rs index 036036aedc9d6..de3e5160b5c79 100644 --- a/crates/store/re_types/src/blueprint/components/visible_time_range.rs +++ b/crates/store/re_types/src/blueprint/components/visible_time_range.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/visual_bounds2d.rs b/crates/store/re_types/src/blueprint/components/visual_bounds2d.rs index d427f36efab93..b7f0ef651de54 100644 --- a/crates/store/re_types/src/blueprint/components/visual_bounds2d.rs +++ b/crates/store/re_types/src/blueprint/components/visual_bounds2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/visualizer_overrides.rs b/crates/store/re_types/src/blueprint/components/visualizer_overrides.rs index eda1fa427e7c9..22221e520117e 100644 --- a/crates/store/re_types/src/blueprint/components/visualizer_overrides.rs +++ b/crates/store/re_types/src/blueprint/components/visualizer_overrides.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/components/zoom_level.rs b/crates/store/re_types/src/blueprint/components/zoom_level.rs index b1feded6ebc60..e77f9beb5e774 100644 --- a/crates/store/re_types/src/blueprint/components/zoom_level.rs +++ b/crates/store/re_types/src/blueprint/components/zoom_level.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/datatypes/component_column_selector.rs b/crates/store/re_types/src/blueprint/datatypes/component_column_selector.rs index 15257961b4dda..29ee6bdea7678 100644 --- a/crates/store/re_types/src/blueprint/datatypes/component_column_selector.rs +++ b/crates/store/re_types/src/blueprint/datatypes/component_column_selector.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/datatypes/filter_by_range.rs b/crates/store/re_types/src/blueprint/datatypes/filter_by_range.rs index 696911a2c8c3b..fd38641148803 100644 --- a/crates/store/re_types/src/blueprint/datatypes/filter_by_range.rs +++ b/crates/store/re_types/src/blueprint/datatypes/filter_by_range.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/datatypes/filter_is_not_null.rs b/crates/store/re_types/src/blueprint/datatypes/filter_is_not_null.rs index ac0a5f8e0b384..5caff6e544b81 100644 --- a/crates/store/re_types/src/blueprint/datatypes/filter_is_not_null.rs +++ b/crates/store/re_types/src/blueprint/datatypes/filter_is_not_null.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/datatypes/selected_columns.rs b/crates/store/re_types/src/blueprint/datatypes/selected_columns.rs index db84346e598b6..6712d07123bd8 100644 --- a/crates/store/re_types/src/blueprint/datatypes/selected_columns.rs +++ b/crates/store/re_types/src/blueprint/datatypes/selected_columns.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/datatypes/tensor_dimension_index_slider.rs b/crates/store/re_types/src/blueprint/datatypes/tensor_dimension_index_slider.rs index d31ecd59ed568..ee5e36cfd9b0b 100644 --- a/crates/store/re_types/src/blueprint/datatypes/tensor_dimension_index_slider.rs +++ b/crates/store/re_types/src/blueprint/datatypes/tensor_dimension_index_slider.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/datatypes/utf8list.rs b/crates/store/re_types/src/blueprint/datatypes/utf8list.rs index c8a00d1be0d3f..1971c163e6762 100644 --- a/crates/store/re_types/src/blueprint/datatypes/utf8list.rs +++ b/crates/store/re_types/src/blueprint/datatypes/utf8list.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/bar_chart_view.rs b/crates/store/re_types/src/blueprint/views/bar_chart_view.rs index 29fa957fa4933..7953122e2ac44 100644 --- a/crates/store/re_types/src/blueprint/views/bar_chart_view.rs +++ b/crates/store/re_types/src/blueprint/views/bar_chart_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/dataframe_view.rs b/crates/store/re_types/src/blueprint/views/dataframe_view.rs index 3b71a7d57243b..57e71959d8717 100644 --- a/crates/store/re_types/src/blueprint/views/dataframe_view.rs +++ b/crates/store/re_types/src/blueprint/views/dataframe_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/graph_view.rs b/crates/store/re_types/src/blueprint/views/graph_view.rs index 5a99bd126e539..aaf82a894f7b3 100644 --- a/crates/store/re_types/src/blueprint/views/graph_view.rs +++ b/crates/store/re_types/src/blueprint/views/graph_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/map_view.rs b/crates/store/re_types/src/blueprint/views/map_view.rs index cd717be84a047..13e93e6be0e01 100644 --- a/crates/store/re_types/src/blueprint/views/map_view.rs +++ b/crates/store/re_types/src/blueprint/views/map_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/spatial2d_view.rs b/crates/store/re_types/src/blueprint/views/spatial2d_view.rs index 964d6a4fea08c..0c3a1f78c5b36 100644 --- a/crates/store/re_types/src/blueprint/views/spatial2d_view.rs +++ b/crates/store/re_types/src/blueprint/views/spatial2d_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/spatial3d_view.rs b/crates/store/re_types/src/blueprint/views/spatial3d_view.rs index dd967fb88bc6e..0f394ab78ff34 100644 --- a/crates/store/re_types/src/blueprint/views/spatial3d_view.rs +++ b/crates/store/re_types/src/blueprint/views/spatial3d_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/tensor_view.rs b/crates/store/re_types/src/blueprint/views/tensor_view.rs index 6d75fde69a198..1c00f4e4de19d 100644 --- a/crates/store/re_types/src/blueprint/views/tensor_view.rs +++ b/crates/store/re_types/src/blueprint/views/tensor_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/text_document_view.rs b/crates/store/re_types/src/blueprint/views/text_document_view.rs index a3508ebf93294..5cd96c47dafd3 100644 --- a/crates/store/re_types/src/blueprint/views/text_document_view.rs +++ b/crates/store/re_types/src/blueprint/views/text_document_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/text_log_view.rs b/crates/store/re_types/src/blueprint/views/text_log_view.rs index 2dacea70d7432..748e50469c561 100644 --- a/crates/store/re_types/src/blueprint/views/text_log_view.rs +++ b/crates/store/re_types/src/blueprint/views/text_log_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/blueprint/views/time_series_view.rs b/crates/store/re_types/src/blueprint/views/time_series_view.rs index 7a718eedf9938..310e0df961dfc 100644 --- a/crates/store/re_types/src/blueprint/views/time_series_view.rs +++ b/crates/store/re_types/src/blueprint/views/time_series_view.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/aggregation_policy.rs b/crates/store/re_types/src/components/aggregation_policy.rs index 19b874a919a04..7b1a138efb85a 100644 --- a/crates/store/re_types/src/components/aggregation_policy.rs +++ b/crates/store/re_types/src/components/aggregation_policy.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/albedo_factor.rs b/crates/store/re_types/src/components/albedo_factor.rs index 45cdfd75d53f1..f0cb4dbcd0cce 100644 --- a/crates/store/re_types/src/components/albedo_factor.rs +++ b/crates/store/re_types/src/components/albedo_factor.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/annotation_context.rs b/crates/store/re_types/src/components/annotation_context.rs index 31f628218df03..3e7fef65ce89d 100644 --- a/crates/store/re_types/src/components/annotation_context.rs +++ b/crates/store/re_types/src/components/annotation_context.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/axis_length.rs b/crates/store/re_types/src/components/axis_length.rs index fb016e17b256a..5aaf88578c972 100644 --- a/crates/store/re_types/src/components/axis_length.rs +++ b/crates/store/re_types/src/components/axis_length.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/blob.rs b/crates/store/re_types/src/components/blob.rs index 2148cb941c586..63da3f6bb5c6a 100644 --- a/crates/store/re_types/src/components/blob.rs +++ b/crates/store/re_types/src/components/blob.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/class_id.rs b/crates/store/re_types/src/components/class_id.rs index 020f9ed24c643..2378184ed71f4 100644 --- a/crates/store/re_types/src/components/class_id.rs +++ b/crates/store/re_types/src/components/class_id.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/color.rs b/crates/store/re_types/src/components/color.rs index 80b1a9d7ba045..5d847a32ef661 100644 --- a/crates/store/re_types/src/components/color.rs +++ b/crates/store/re_types/src/components/color.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/colormap.rs b/crates/store/re_types/src/components/colormap.rs index 969a0f62f7e62..ccfa447492b0f 100644 --- a/crates/store/re_types/src/components/colormap.rs +++ b/crates/store/re_types/src/components/colormap.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/depth_meter.rs b/crates/store/re_types/src/components/depth_meter.rs index 6580c390066b0..1aae9274c7b6f 100644 --- a/crates/store/re_types/src/components/depth_meter.rs +++ b/crates/store/re_types/src/components/depth_meter.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/draw_order.rs b/crates/store/re_types/src/components/draw_order.rs index e699b097b2a32..4a10f5c8b3640 100644 --- a/crates/store/re_types/src/components/draw_order.rs +++ b/crates/store/re_types/src/components/draw_order.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/entity_path.rs b/crates/store/re_types/src/components/entity_path.rs index eee07c4c5c86a..be5ac7c8b7554 100644 --- a/crates/store/re_types/src/components/entity_path.rs +++ b/crates/store/re_types/src/components/entity_path.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/fill_mode.rs b/crates/store/re_types/src/components/fill_mode.rs index ba6f38fa611cd..a4eb3429827ed 100644 --- a/crates/store/re_types/src/components/fill_mode.rs +++ b/crates/store/re_types/src/components/fill_mode.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/fill_ratio.rs b/crates/store/re_types/src/components/fill_ratio.rs index 8e351a5bac4dd..5aed7e721148e 100644 --- a/crates/store/re_types/src/components/fill_ratio.rs +++ b/crates/store/re_types/src/components/fill_ratio.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/gamma_correction.rs b/crates/store/re_types/src/components/gamma_correction.rs index 3ee9374feef1d..d2c86b8a68fcf 100644 --- a/crates/store/re_types/src/components/gamma_correction.rs +++ b/crates/store/re_types/src/components/gamma_correction.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/geo_line_string.rs b/crates/store/re_types/src/components/geo_line_string.rs index f22cd05ee8dcd..20f019aa700b7 100644 --- a/crates/store/re_types/src/components/geo_line_string.rs +++ b/crates/store/re_types/src/components/geo_line_string.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/graph_edge.rs b/crates/store/re_types/src/components/graph_edge.rs index 877b4815db79e..cf35c2d487f14 100644 --- a/crates/store/re_types/src/components/graph_edge.rs +++ b/crates/store/re_types/src/components/graph_edge.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/graph_node.rs b/crates/store/re_types/src/components/graph_node.rs index b2ec7be326eeb..797b8c47ba10c 100644 --- a/crates/store/re_types/src/components/graph_node.rs +++ b/crates/store/re_types/src/components/graph_node.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/graph_type.rs b/crates/store/re_types/src/components/graph_type.rs index 4f4c03f135ce6..4498b4a43e58b 100644 --- a/crates/store/re_types/src/components/graph_type.rs +++ b/crates/store/re_types/src/components/graph_type.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/half_size2d.rs b/crates/store/re_types/src/components/half_size2d.rs index b748be80fbec2..e8bfa594e937c 100644 --- a/crates/store/re_types/src/components/half_size2d.rs +++ b/crates/store/re_types/src/components/half_size2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/half_size3d.rs b/crates/store/re_types/src/components/half_size3d.rs index f64fe87bace63..7a784f2528ae7 100644 --- a/crates/store/re_types/src/components/half_size3d.rs +++ b/crates/store/re_types/src/components/half_size3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/image_buffer.rs b/crates/store/re_types/src/components/image_buffer.rs index e37bd67bf0f32..48ed12acefc42 100644 --- a/crates/store/re_types/src/components/image_buffer.rs +++ b/crates/store/re_types/src/components/image_buffer.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/image_format.rs b/crates/store/re_types/src/components/image_format.rs index 33dd4f3693122..1339610110336 100644 --- a/crates/store/re_types/src/components/image_format.rs +++ b/crates/store/re_types/src/components/image_format.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/image_plane_distance.rs b/crates/store/re_types/src/components/image_plane_distance.rs index c6c80562c4201..d486c2b03f7f5 100644 --- a/crates/store/re_types/src/components/image_plane_distance.rs +++ b/crates/store/re_types/src/components/image_plane_distance.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/keypoint_id.rs b/crates/store/re_types/src/components/keypoint_id.rs index d7ffad1f26997..fc20e728a5414 100644 --- a/crates/store/re_types/src/components/keypoint_id.rs +++ b/crates/store/re_types/src/components/keypoint_id.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/lat_lon.rs b/crates/store/re_types/src/components/lat_lon.rs index 857068d89c57c..7d72f9eee6b6a 100644 --- a/crates/store/re_types/src/components/lat_lon.rs +++ b/crates/store/re_types/src/components/lat_lon.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/length.rs b/crates/store/re_types/src/components/length.rs index 7039d630f8a5f..981c54ce971dd 100644 --- a/crates/store/re_types/src/components/length.rs +++ b/crates/store/re_types/src/components/length.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/line_strip2d.rs b/crates/store/re_types/src/components/line_strip2d.rs index 12e9afd4ff3a6..e94fae88f4430 100644 --- a/crates/store/re_types/src/components/line_strip2d.rs +++ b/crates/store/re_types/src/components/line_strip2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/line_strip3d.rs b/crates/store/re_types/src/components/line_strip3d.rs index 59c4d4b703004..c20a5779329c8 100644 --- a/crates/store/re_types/src/components/line_strip3d.rs +++ b/crates/store/re_types/src/components/line_strip3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/magnification_filter.rs b/crates/store/re_types/src/components/magnification_filter.rs index 1b4eb5ea3eb47..384713ac15f5d 100644 --- a/crates/store/re_types/src/components/magnification_filter.rs +++ b/crates/store/re_types/src/components/magnification_filter.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/marker_shape.rs b/crates/store/re_types/src/components/marker_shape.rs index cea44fe1bc5f6..a76806d2d1690 100644 --- a/crates/store/re_types/src/components/marker_shape.rs +++ b/crates/store/re_types/src/components/marker_shape.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/marker_size.rs b/crates/store/re_types/src/components/marker_size.rs index 896aa14f4d98f..b6e529aae438d 100644 --- a/crates/store/re_types/src/components/marker_size.rs +++ b/crates/store/re_types/src/components/marker_size.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/media_type.rs b/crates/store/re_types/src/components/media_type.rs index d75ef3d9a5a93..4fb5a7aba74df 100644 --- a/crates/store/re_types/src/components/media_type.rs +++ b/crates/store/re_types/src/components/media_type.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/name.rs b/crates/store/re_types/src/components/name.rs index d847bb2a55af0..6adc01da329e5 100644 --- a/crates/store/re_types/src/components/name.rs +++ b/crates/store/re_types/src/components/name.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/opacity.rs b/crates/store/re_types/src/components/opacity.rs index e40e51ae00d75..73f4c69d849ac 100644 --- a/crates/store/re_types/src/components/opacity.rs +++ b/crates/store/re_types/src/components/opacity.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/pinhole_projection.rs b/crates/store/re_types/src/components/pinhole_projection.rs index c36f0a00a6e3e..70aaf29fb2d51 100644 --- a/crates/store/re_types/src/components/pinhole_projection.rs +++ b/crates/store/re_types/src/components/pinhole_projection.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/plane3d.rs b/crates/store/re_types/src/components/plane3d.rs index d284b634c8ad2..caf4d1dc95c37 100644 --- a/crates/store/re_types/src/components/plane3d.rs +++ b/crates/store/re_types/src/components/plane3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/pose_rotation_axis_angle.rs b/crates/store/re_types/src/components/pose_rotation_axis_angle.rs index d2d06f17b9434..9385b3f171a39 100644 --- a/crates/store/re_types/src/components/pose_rotation_axis_angle.rs +++ b/crates/store/re_types/src/components/pose_rotation_axis_angle.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/pose_rotation_quat.rs b/crates/store/re_types/src/components/pose_rotation_quat.rs index 7c9c34529f8bf..cf024baa135a8 100644 --- a/crates/store/re_types/src/components/pose_rotation_quat.rs +++ b/crates/store/re_types/src/components/pose_rotation_quat.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/pose_scale3d.rs b/crates/store/re_types/src/components/pose_scale3d.rs index 38e24437323cd..afc3e4f5db60c 100644 --- a/crates/store/re_types/src/components/pose_scale3d.rs +++ b/crates/store/re_types/src/components/pose_scale3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/pose_transform_mat3x3.rs b/crates/store/re_types/src/components/pose_transform_mat3x3.rs index d870bf241669e..394cc2102df54 100644 --- a/crates/store/re_types/src/components/pose_transform_mat3x3.rs +++ b/crates/store/re_types/src/components/pose_transform_mat3x3.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/pose_translation3d.rs b/crates/store/re_types/src/components/pose_translation3d.rs index f0ecb52c00beb..dcea071125d14 100644 --- a/crates/store/re_types/src/components/pose_translation3d.rs +++ b/crates/store/re_types/src/components/pose_translation3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/position2d.rs b/crates/store/re_types/src/components/position2d.rs index 059bf4fa3dc64..5a0caa7a84ec0 100644 --- a/crates/store/re_types/src/components/position2d.rs +++ b/crates/store/re_types/src/components/position2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/position3d.rs b/crates/store/re_types/src/components/position3d.rs index be84619c40e65..09d0ca752cea8 100644 --- a/crates/store/re_types/src/components/position3d.rs +++ b/crates/store/re_types/src/components/position3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/radius.rs b/crates/store/re_types/src/components/radius.rs index 323d4c927512e..9de6b628e1ec4 100644 --- a/crates/store/re_types/src/components/radius.rs +++ b/crates/store/re_types/src/components/radius.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/range1d.rs b/crates/store/re_types/src/components/range1d.rs index 519bff1d53346..972d79fd859c9 100644 --- a/crates/store/re_types/src/components/range1d.rs +++ b/crates/store/re_types/src/components/range1d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/recording_uri.rs b/crates/store/re_types/src/components/recording_uri.rs index 2c010dbf69cab..5b96d603b8488 100644 --- a/crates/store/re_types/src/components/recording_uri.rs +++ b/crates/store/re_types/src/components/recording_uri.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/resolution.rs b/crates/store/re_types/src/components/resolution.rs index 942e8ded5d9a0..1469b3c096bbe 100644 --- a/crates/store/re_types/src/components/resolution.rs +++ b/crates/store/re_types/src/components/resolution.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/rotation_axis_angle.rs b/crates/store/re_types/src/components/rotation_axis_angle.rs index b76abaa079a22..a02ea550a8ea8 100644 --- a/crates/store/re_types/src/components/rotation_axis_angle.rs +++ b/crates/store/re_types/src/components/rotation_axis_angle.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/rotation_quat.rs b/crates/store/re_types/src/components/rotation_quat.rs index 5eb6c2773f381..bebdb6e1b6a32 100644 --- a/crates/store/re_types/src/components/rotation_quat.rs +++ b/crates/store/re_types/src/components/rotation_quat.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/scalar.rs b/crates/store/re_types/src/components/scalar.rs index 5c215db207040..1c01bad38b789 100644 --- a/crates/store/re_types/src/components/scalar.rs +++ b/crates/store/re_types/src/components/scalar.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/scale3d.rs b/crates/store/re_types/src/components/scale3d.rs index 53cf03a893052..a6bf67f4fc655 100644 --- a/crates/store/re_types/src/components/scale3d.rs +++ b/crates/store/re_types/src/components/scale3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/show_labels.rs b/crates/store/re_types/src/components/show_labels.rs index 505d7e7b4892f..4384331fddeec 100644 --- a/crates/store/re_types/src/components/show_labels.rs +++ b/crates/store/re_types/src/components/show_labels.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/stroke_width.rs b/crates/store/re_types/src/components/stroke_width.rs index a60591fd85864..9d9594fddd0f7 100644 --- a/crates/store/re_types/src/components/stroke_width.rs +++ b/crates/store/re_types/src/components/stroke_width.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/tensor_data.rs b/crates/store/re_types/src/components/tensor_data.rs index 5b012c667e142..111724f5bcee7 100644 --- a/crates/store/re_types/src/components/tensor_data.rs +++ b/crates/store/re_types/src/components/tensor_data.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/tensor_dimension_index_selection.rs b/crates/store/re_types/src/components/tensor_dimension_index_selection.rs index cb52ac4e32d48..c45952b8afa13 100644 --- a/crates/store/re_types/src/components/tensor_dimension_index_selection.rs +++ b/crates/store/re_types/src/components/tensor_dimension_index_selection.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/tensor_height_dimension.rs b/crates/store/re_types/src/components/tensor_height_dimension.rs index cfa1b1cac397d..83a8c2119d471 100644 --- a/crates/store/re_types/src/components/tensor_height_dimension.rs +++ b/crates/store/re_types/src/components/tensor_height_dimension.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/tensor_width_dimension.rs b/crates/store/re_types/src/components/tensor_width_dimension.rs index 0a395c69b217d..c6dd590111922 100644 --- a/crates/store/re_types/src/components/tensor_width_dimension.rs +++ b/crates/store/re_types/src/components/tensor_width_dimension.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/texcoord2d.rs b/crates/store/re_types/src/components/texcoord2d.rs index d01cf77aa12b4..c08acb80424b2 100644 --- a/crates/store/re_types/src/components/texcoord2d.rs +++ b/crates/store/re_types/src/components/texcoord2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/text.rs b/crates/store/re_types/src/components/text.rs index 014369c11e14e..42ed71a6a088c 100644 --- a/crates/store/re_types/src/components/text.rs +++ b/crates/store/re_types/src/components/text.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/text_log_level.rs b/crates/store/re_types/src/components/text_log_level.rs index 4fc5e833567d0..7b602e5135364 100644 --- a/crates/store/re_types/src/components/text_log_level.rs +++ b/crates/store/re_types/src/components/text_log_level.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/transform_mat3x3.rs b/crates/store/re_types/src/components/transform_mat3x3.rs index 4b22174bae9e6..5d2935bf1a07c 100644 --- a/crates/store/re_types/src/components/transform_mat3x3.rs +++ b/crates/store/re_types/src/components/transform_mat3x3.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/transform_relation.rs b/crates/store/re_types/src/components/transform_relation.rs index 9aa39cade685f..f3baed9c4277d 100644 --- a/crates/store/re_types/src/components/transform_relation.rs +++ b/crates/store/re_types/src/components/transform_relation.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/translation3d.rs b/crates/store/re_types/src/components/translation3d.rs index 30451799c04cb..452a30db6b537 100644 --- a/crates/store/re_types/src/components/translation3d.rs +++ b/crates/store/re_types/src/components/translation3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/triangle_indices.rs b/crates/store/re_types/src/components/triangle_indices.rs index 63d5316e66378..1fd44e8af27ec 100644 --- a/crates/store/re_types/src/components/triangle_indices.rs +++ b/crates/store/re_types/src/components/triangle_indices.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/value_range.rs b/crates/store/re_types/src/components/value_range.rs index ccaa552121e3c..0684716cca219 100644 --- a/crates/store/re_types/src/components/value_range.rs +++ b/crates/store/re_types/src/components/value_range.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/vector2d.rs b/crates/store/re_types/src/components/vector2d.rs index 80640d73335a3..d063653259b48 100644 --- a/crates/store/re_types/src/components/vector2d.rs +++ b/crates/store/re_types/src/components/vector2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/vector3d.rs b/crates/store/re_types/src/components/vector3d.rs index 6a5388c1da2c6..45a796c622062 100644 --- a/crates/store/re_types/src/components/vector3d.rs +++ b/crates/store/re_types/src/components/vector3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/video_timestamp.rs b/crates/store/re_types/src/components/video_timestamp.rs index 4ebc48ec98c61..c25c644bcb237 100644 --- a/crates/store/re_types/src/components/video_timestamp.rs +++ b/crates/store/re_types/src/components/video_timestamp.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/components/view_coordinates.rs b/crates/store/re_types/src/components/view_coordinates.rs index a4c317487d4c7..fa724a474a9ac 100644 --- a/crates/store/re_types/src/components/view_coordinates.rs +++ b/crates/store/re_types/src/components/view_coordinates.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/angle.rs b/crates/store/re_types/src/datatypes/angle.rs index 7602af41cd539..0af6690037e70 100644 --- a/crates/store/re_types/src/datatypes/angle.rs +++ b/crates/store/re_types/src/datatypes/angle.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/annotation_info.rs b/crates/store/re_types/src/datatypes/annotation_info.rs index 72959487214ba..3472405a821fe 100644 --- a/crates/store/re_types/src/datatypes/annotation_info.rs +++ b/crates/store/re_types/src/datatypes/annotation_info.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/blob.rs b/crates/store/re_types/src/datatypes/blob.rs index b426c434fd585..bb324b10f30b8 100644 --- a/crates/store/re_types/src/datatypes/blob.rs +++ b/crates/store/re_types/src/datatypes/blob.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/channel_datatype.rs b/crates/store/re_types/src/datatypes/channel_datatype.rs index 0889533c2e76a..eccd99f134d74 100644 --- a/crates/store/re_types/src/datatypes/channel_datatype.rs +++ b/crates/store/re_types/src/datatypes/channel_datatype.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/class_description.rs b/crates/store/re_types/src/datatypes/class_description.rs index 8a973105aaaa5..3593f555f46f6 100644 --- a/crates/store/re_types/src/datatypes/class_description.rs +++ b/crates/store/re_types/src/datatypes/class_description.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/class_description_map_elem.rs b/crates/store/re_types/src/datatypes/class_description_map_elem.rs index e44381c2480bb..132b8ac8142d7 100644 --- a/crates/store/re_types/src/datatypes/class_description_map_elem.rs +++ b/crates/store/re_types/src/datatypes/class_description_map_elem.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/class_id.rs b/crates/store/re_types/src/datatypes/class_id.rs index d9edc5920617a..c9fff0b2cbda5 100644 --- a/crates/store/re_types/src/datatypes/class_id.rs +++ b/crates/store/re_types/src/datatypes/class_id.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/color_model.rs b/crates/store/re_types/src/datatypes/color_model.rs index f7f6f68303b9c..38e1647acb0ef 100644 --- a/crates/store/re_types/src/datatypes/color_model.rs +++ b/crates/store/re_types/src/datatypes/color_model.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/dvec2d.rs b/crates/store/re_types/src/datatypes/dvec2d.rs index dca7abb60020c..fac4f8dbdf62a 100644 --- a/crates/store/re_types/src/datatypes/dvec2d.rs +++ b/crates/store/re_types/src/datatypes/dvec2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/image_format.rs b/crates/store/re_types/src/datatypes/image_format.rs index c7be2dba584e0..d61f374a29458 100644 --- a/crates/store/re_types/src/datatypes/image_format.rs +++ b/crates/store/re_types/src/datatypes/image_format.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/keypoint_id.rs b/crates/store/re_types/src/datatypes/keypoint_id.rs index c3754c32712fa..df9cccf30a687 100644 --- a/crates/store/re_types/src/datatypes/keypoint_id.rs +++ b/crates/store/re_types/src/datatypes/keypoint_id.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/keypoint_pair.rs b/crates/store/re_types/src/datatypes/keypoint_pair.rs index e7138ef83e81b..6161dd0418680 100644 --- a/crates/store/re_types/src/datatypes/keypoint_pair.rs +++ b/crates/store/re_types/src/datatypes/keypoint_pair.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/mat3x3.rs b/crates/store/re_types/src/datatypes/mat3x3.rs index 07c0f3ed03c8f..12952254237f6 100644 --- a/crates/store/re_types/src/datatypes/mat3x3.rs +++ b/crates/store/re_types/src/datatypes/mat3x3.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/mat4x4.rs b/crates/store/re_types/src/datatypes/mat4x4.rs index 9553147cdaec9..430ed5d3de004 100644 --- a/crates/store/re_types/src/datatypes/mat4x4.rs +++ b/crates/store/re_types/src/datatypes/mat4x4.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/pixel_format.rs b/crates/store/re_types/src/datatypes/pixel_format.rs index a21cec6c4e219..c52ff2cdca675 100644 --- a/crates/store/re_types/src/datatypes/pixel_format.rs +++ b/crates/store/re_types/src/datatypes/pixel_format.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/plane3d.rs b/crates/store/re_types/src/datatypes/plane3d.rs index e807be38bf010..94cc4c980a6ca 100644 --- a/crates/store/re_types/src/datatypes/plane3d.rs +++ b/crates/store/re_types/src/datatypes/plane3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/quaternion.rs b/crates/store/re_types/src/datatypes/quaternion.rs index f33e6a0aab0ed..ae36f3fb9bb1f 100644 --- a/crates/store/re_types/src/datatypes/quaternion.rs +++ b/crates/store/re_types/src/datatypes/quaternion.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/range1d.rs b/crates/store/re_types/src/datatypes/range1d.rs index 9db25bd1a9cb0..5a3a575cee5ed 100644 --- a/crates/store/re_types/src/datatypes/range1d.rs +++ b/crates/store/re_types/src/datatypes/range1d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/range2d.rs b/crates/store/re_types/src/datatypes/range2d.rs index 09bd52b0caf75..8f3e983d06c0c 100644 --- a/crates/store/re_types/src/datatypes/range2d.rs +++ b/crates/store/re_types/src/datatypes/range2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/rgba32.rs b/crates/store/re_types/src/datatypes/rgba32.rs index df5cff7bac2ec..06b1093f1c941 100644 --- a/crates/store/re_types/src/datatypes/rgba32.rs +++ b/crates/store/re_types/src/datatypes/rgba32.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/rotation_axis_angle.rs b/crates/store/re_types/src/datatypes/rotation_axis_angle.rs index 4e2efc7e17cae..893f3fe60f6f9 100644 --- a/crates/store/re_types/src/datatypes/rotation_axis_angle.rs +++ b/crates/store/re_types/src/datatypes/rotation_axis_angle.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/tensor_buffer.rs b/crates/store/re_types/src/datatypes/tensor_buffer.rs index 19df1b11c690c..834e95fdfe7fa 100644 --- a/crates/store/re_types/src/datatypes/tensor_buffer.rs +++ b/crates/store/re_types/src/datatypes/tensor_buffer.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/tensor_data.rs b/crates/store/re_types/src/datatypes/tensor_data.rs index 0c28d9ff62850..27a1b36f8dfcf 100644 --- a/crates/store/re_types/src/datatypes/tensor_data.rs +++ b/crates/store/re_types/src/datatypes/tensor_data.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/tensor_dimension_index_selection.rs b/crates/store/re_types/src/datatypes/tensor_dimension_index_selection.rs index b344d5477865d..c735a5957a7ee 100644 --- a/crates/store/re_types/src/datatypes/tensor_dimension_index_selection.rs +++ b/crates/store/re_types/src/datatypes/tensor_dimension_index_selection.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/tensor_dimension_selection.rs b/crates/store/re_types/src/datatypes/tensor_dimension_selection.rs index 7f7e73bcf8a9f..2e10f82fa4770 100644 --- a/crates/store/re_types/src/datatypes/tensor_dimension_selection.rs +++ b/crates/store/re_types/src/datatypes/tensor_dimension_selection.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/utf8pair.rs b/crates/store/re_types/src/datatypes/utf8pair.rs index 38d450665af05..67cac56b21319 100644 --- a/crates/store/re_types/src/datatypes/utf8pair.rs +++ b/crates/store/re_types/src/datatypes/utf8pair.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/uuid.rs b/crates/store/re_types/src/datatypes/uuid.rs index 6f9c8d5487419..c1bc747308aa8 100644 --- a/crates/store/re_types/src/datatypes/uuid.rs +++ b/crates/store/re_types/src/datatypes/uuid.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/uvec2d.rs b/crates/store/re_types/src/datatypes/uvec2d.rs index d99841311376d..149a186cea70b 100644 --- a/crates/store/re_types/src/datatypes/uvec2d.rs +++ b/crates/store/re_types/src/datatypes/uvec2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/uvec3d.rs b/crates/store/re_types/src/datatypes/uvec3d.rs index 99a0dcf95dee8..fe1fa247fe46b 100644 --- a/crates/store/re_types/src/datatypes/uvec3d.rs +++ b/crates/store/re_types/src/datatypes/uvec3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/uvec4d.rs b/crates/store/re_types/src/datatypes/uvec4d.rs index 4b76b63b8e210..bd9c7cba52429 100644 --- a/crates/store/re_types/src/datatypes/uvec4d.rs +++ b/crates/store/re_types/src/datatypes/uvec4d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/vec2d.rs b/crates/store/re_types/src/datatypes/vec2d.rs index 02250192f749c..418ee1bfd311d 100644 --- a/crates/store/re_types/src/datatypes/vec2d.rs +++ b/crates/store/re_types/src/datatypes/vec2d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/vec3d.rs b/crates/store/re_types/src/datatypes/vec3d.rs index b36a06e8a0e23..282ee4db0d721 100644 --- a/crates/store/re_types/src/datatypes/vec3d.rs +++ b/crates/store/re_types/src/datatypes/vec3d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/vec4d.rs b/crates/store/re_types/src/datatypes/vec4d.rs index 0c3ddefbd9e6a..3ec184780e34d 100644 --- a/crates/store/re_types/src/datatypes/vec4d.rs +++ b/crates/store/re_types/src/datatypes/vec4d.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/video_timestamp.rs b/crates/store/re_types/src/datatypes/video_timestamp.rs index ed839f0cc9d89..3b61853fd78db 100644 --- a/crates/store/re_types/src/datatypes/video_timestamp.rs +++ b/crates/store/re_types/src/datatypes/video_timestamp.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/datatypes/view_coordinates.rs b/crates/store/re_types/src/datatypes/view_coordinates.rs index b73a1c3a365fe..358a745aa47c4 100644 --- a/crates/store/re_types/src/datatypes/view_coordinates.rs +++ b/crates/store/re_types/src/datatypes/view_coordinates.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/archetypes/affix_fuzzer1.rs b/crates/store/re_types/src/testing/archetypes/affix_fuzzer1.rs index 46dbd2e202c3d..96d54bbdeddaf 100644 --- a/crates/store/re_types/src/testing/archetypes/affix_fuzzer1.rs +++ b/crates/store/re_types/src/testing/archetypes/affix_fuzzer1.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -361,9 +361,9 @@ impl ::re_types_core::Archetype for AffixFuzzer1 { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: AffixFuzzer1Indicator = AffixFuzzer1Indicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + AffixFuzzer1Indicator::DEFAULT.serialized().unwrap() } #[inline] @@ -491,7 +491,7 @@ impl ::re_types_core::AsComponents for AffixFuzzer1 { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.fuzz1001.clone(), self.fuzz1002.clone(), self.fuzz1003.clone(), @@ -764,9 +764,12 @@ impl AffixFuzzer1 { .map(|fuzz1022| fuzz1022.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/testing/archetypes/affix_fuzzer2.rs b/crates/store/re_types/src/testing/archetypes/affix_fuzzer2.rs index 9c720318f73a4..58dad117b5b3a 100644 --- a/crates/store/re_types/src/testing/archetypes/affix_fuzzer2.rs +++ b/crates/store/re_types/src/testing/archetypes/affix_fuzzer2.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -322,9 +322,9 @@ impl ::re_types_core::Archetype for AffixFuzzer2 { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: AffixFuzzer2Indicator = AffixFuzzer2Indicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + AffixFuzzer2Indicator::DEFAULT.serialized().unwrap() } #[inline] @@ -440,7 +440,7 @@ impl ::re_types_core::AsComponents for AffixFuzzer2 { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.fuzz1101.clone(), self.fuzz1102.clone(), self.fuzz1103.clone(), @@ -683,9 +683,12 @@ impl AffixFuzzer2 { .map(|fuzz1122| fuzz1122.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/testing/archetypes/affix_fuzzer3.rs b/crates/store/re_types/src/testing/archetypes/affix_fuzzer3.rs index b88ddf968d829..f7215fa86e4f6 100644 --- a/crates/store/re_types/src/testing/archetypes/affix_fuzzer3.rs +++ b/crates/store/re_types/src/testing/archetypes/affix_fuzzer3.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -309,9 +309,9 @@ impl ::re_types_core::Archetype for AffixFuzzer3 { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: AffixFuzzer3Indicator = AffixFuzzer3Indicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + AffixFuzzer3Indicator::DEFAULT.serialized().unwrap() } #[inline] @@ -423,7 +423,7 @@ impl ::re_types_core::AsComponents for AffixFuzzer3 { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.fuzz2001.clone(), self.fuzz2002.clone(), self.fuzz2003.clone(), @@ -637,9 +637,12 @@ impl AffixFuzzer3 { .map(|fuzz2018| fuzz2018.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/testing/archetypes/affix_fuzzer4.rs b/crates/store/re_types/src/testing/archetypes/affix_fuzzer4.rs index e96bb023859c4..3c0353e69f1ba 100644 --- a/crates/store/re_types/src/testing/archetypes/affix_fuzzer4.rs +++ b/crates/store/re_types/src/testing/archetypes/affix_fuzzer4.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; @@ -309,9 +309,9 @@ impl ::re_types_core::Archetype for AffixFuzzer4 { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: AffixFuzzer4Indicator = AffixFuzzer4Indicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + AffixFuzzer4Indicator::DEFAULT.serialized().unwrap() } #[inline] @@ -423,7 +423,7 @@ impl ::re_types_core::AsComponents for AffixFuzzer4 { fn as_serialized_batches(&self) -> Vec { use ::re_types_core::Archetype as _; [ - Self::indicator().serialized(), + Some(Self::indicator()), self.fuzz2101.clone(), self.fuzz2102.clone(), self.fuzz2103.clone(), @@ -637,9 +637,12 @@ impl AffixFuzzer4 { .map(|fuzz2118| fuzz2118.partitioned(_lengths.clone())) .transpose()?, ]; - let indicator_column = - ::re_types_core::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer1.rs b/crates/store/re_types/src/testing/components/affix_fuzzer1.rs index c2cff8dec953f..0fdf3ee92c816 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer1.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer1.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer10.rs b/crates/store/re_types/src/testing/components/affix_fuzzer10.rs index bbca1295e226c..19f4c12f88f6f 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer10.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer10.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer11.rs b/crates/store/re_types/src/testing/components/affix_fuzzer11.rs index 8bd9d33d7946e..b6196f4580691 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer11.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer11.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer12.rs b/crates/store/re_types/src/testing/components/affix_fuzzer12.rs index b4676ed1aaf70..5421c033edd0e 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer12.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer12.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer13.rs b/crates/store/re_types/src/testing/components/affix_fuzzer13.rs index 8937fe3bb2841..508d5865f280c 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer13.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer13.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer14.rs b/crates/store/re_types/src/testing/components/affix_fuzzer14.rs index 5067593e81ee2..679124c3c3060 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer14.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer14.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer15.rs b/crates/store/re_types/src/testing/components/affix_fuzzer15.rs index cb2ad5bc19805..545848f4319f9 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer15.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer15.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer16.rs b/crates/store/re_types/src/testing/components/affix_fuzzer16.rs index f2658bc06cb47..2efe6982908da 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer16.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer16.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer17.rs b/crates/store/re_types/src/testing/components/affix_fuzzer17.rs index f3182b2fd257f..f663ba66b485f 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer17.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer17.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer18.rs b/crates/store/re_types/src/testing/components/affix_fuzzer18.rs index fed1da38c806a..7a073bccd5802 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer18.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer18.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer19.rs b/crates/store/re_types/src/testing/components/affix_fuzzer19.rs index 8b6032bd257ad..26b5190d4fb15 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer19.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer19.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer2.rs b/crates/store/re_types/src/testing/components/affix_fuzzer2.rs index a932b92f47a74..11b0cb3a41203 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer2.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer2.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer20.rs b/crates/store/re_types/src/testing/components/affix_fuzzer20.rs index 1b5eb4731e3fd..6c509915dddf2 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer20.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer20.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer21.rs b/crates/store/re_types/src/testing/components/affix_fuzzer21.rs index bca72320c768f..6ecc1c951504c 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer21.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer21.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer22.rs b/crates/store/re_types/src/testing/components/affix_fuzzer22.rs index 5ae4cbe887a3a..68d2912b22d70 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer22.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer22.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer23.rs b/crates/store/re_types/src/testing/components/affix_fuzzer23.rs index b4e46c296a928..f5e03cfa62a35 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer23.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer23.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer3.rs b/crates/store/re_types/src/testing/components/affix_fuzzer3.rs index 8617e5e18c610..04645a330a011 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer3.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer3.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer4.rs b/crates/store/re_types/src/testing/components/affix_fuzzer4.rs index fafb630b60bfb..109cafc606a28 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer4.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer4.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer5.rs b/crates/store/re_types/src/testing/components/affix_fuzzer5.rs index 4ad2ad0802962..55177c85b5033 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer5.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer5.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer6.rs b/crates/store/re_types/src/testing/components/affix_fuzzer6.rs index 0b177e1e5e9c8..9fa0eb1e21cfc 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer6.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer6.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer7.rs b/crates/store/re_types/src/testing/components/affix_fuzzer7.rs index 3a0d8bf404845..c15837ec055f8 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer7.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer7.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer8.rs b/crates/store/re_types/src/testing/components/affix_fuzzer8.rs index c775293cebc3a..534627cfe1d73 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer8.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer8.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/components/affix_fuzzer9.rs b/crates/store/re_types/src/testing/components/affix_fuzzer9.rs index 68c5ec93327a7..c71c8162729af 100644 --- a/crates/store/re_types/src/testing/components/affix_fuzzer9.rs +++ b/crates/store/re_types/src/testing/components/affix_fuzzer9.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer1.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer1.rs index 13e6f4f041aeb..4bdf5c5c00797 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer1.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer1.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer2.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer2.rs index a916b646eb3a5..d7ee8d0f5ef17 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer2.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer2.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer20.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer20.rs index dd0c35d1ab749..fa25bafa49291 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer20.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer20.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer21.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer21.rs index e9279ccb0602f..3ed6f14a24c97 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer21.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer21.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer22.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer22.rs index 1100cc809f1e0..3fe00a352b573 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer22.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer22.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer3.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer3.rs index 547567ed035d0..f22d70d24d3ab 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer3.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer3.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer4.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer4.rs index e3126bb948c80..7d16baef3bea9 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer4.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer4.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/affix_fuzzer5.rs b/crates/store/re_types/src/testing/datatypes/affix_fuzzer5.rs index 385d878dd62f9..c4b4144d732a4 100644 --- a/crates/store/re_types/src/testing/datatypes/affix_fuzzer5.rs +++ b/crates/store/re_types/src/testing/datatypes/affix_fuzzer5.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/enum_test.rs b/crates/store/re_types/src/testing/datatypes/enum_test.rs index 3cf1f93cadeb6..d21c21f3330be 100644 --- a/crates/store/re_types/src/testing/datatypes/enum_test.rs +++ b/crates/store/re_types/src/testing/datatypes/enum_test.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/flattened_scalar.rs b/crates/store/re_types/src/testing/datatypes/flattened_scalar.rs index 7d39fe768ae80..670bb26d6c279 100644 --- a/crates/store/re_types/src/testing/datatypes/flattened_scalar.rs +++ b/crates/store/re_types/src/testing/datatypes/flattened_scalar.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/multi_enum.rs b/crates/store/re_types/src/testing/datatypes/multi_enum.rs index bd19de09d3d9c..2404164b0ddc2 100644 --- a/crates/store/re_types/src/testing/datatypes/multi_enum.rs +++ b/crates/store/re_types/src/testing/datatypes/multi_enum.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/primitive_component.rs b/crates/store/re_types/src/testing/datatypes/primitive_component.rs index 3d7f926878e93..fa87d0cba711e 100644 --- a/crates/store/re_types/src/testing/datatypes/primitive_component.rs +++ b/crates/store/re_types/src/testing/datatypes/primitive_component.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/string_component.rs b/crates/store/re_types/src/testing/datatypes/string_component.rs index 33519adf86437..b014743b7190b 100644 --- a/crates/store/re_types/src/testing/datatypes/string_component.rs +++ b/crates/store/re_types/src/testing/datatypes/string_component.rs @@ -14,7 +14,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types/src/testing/datatypes/valued_enum.rs b/crates/store/re_types/src/testing/datatypes/valued_enum.rs index 6191394e2fcef..197b53d43983d 100644 --- a/crates/store/re_types/src/testing/datatypes/valued_enum.rs +++ b/crates/store/re_types/src/testing/datatypes/valued_enum.rs @@ -15,7 +15,7 @@ use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use ::re_types_core::{ComponentBatch, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/archetype.rs b/crates/store/re_types_core/src/archetype.rs index 03a354998f1fe..836c53f3d6b4e 100644 --- a/crates/store/re_types_core/src/archetype.rs +++ b/crates/store/re_types_core/src/archetype.rs @@ -1,8 +1,8 @@ use std::{borrow::Cow, sync::Arc}; use crate::{ - ComponentBatch, ComponentBatchCowWithDescriptor, ComponentDescriptor, ComponentName, - DeserializationResult, SerializationResult, _Backtrace, + ComponentBatch, ComponentDescriptor, ComponentName, DeserializationResult, SerializationResult, + SerializedComponentBatch, _Backtrace, }; #[allow(unused_imports)] // used in docstrings @@ -51,12 +51,7 @@ pub trait Archetype { /// /// This allows for associating arbitrary indicator components with arbitrary data. /// Check out the `manual_indicator` API example to see what's possible. - #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - ComponentBatchCowWithDescriptor::new( - Box::<::Indicator>::default() as Box - ) - } + fn indicator() -> SerializedComponentBatch; /// Returns all component descriptors that _must_ be provided by the user when constructing this archetype. fn required_components() -> std::borrow::Cow<'static, [ComponentDescriptor]>; @@ -64,7 +59,7 @@ pub trait Archetype { /// Returns all component descriptors that _should_ be provided by the user when constructing this archetype. #[inline] fn recommended_components() -> std::borrow::Cow<'static, [ComponentDescriptor]> { - std::borrow::Cow::Owned(vec![Self::indicator().descriptor().into_owned()]) + std::borrow::Cow::Owned(vec![Self::indicator().descriptor.clone()]) } /// Returns all component descriptors that _may_ be provided by the user when constructing this archetype. @@ -286,18 +281,6 @@ impl crate::ComponentBatch for GenericIndicatorComponentArray { #[derive(Debug, Clone, Copy)] pub struct NamedIndicatorComponent(pub ComponentName); -impl NamedIndicatorComponent { - #[inline] - pub fn as_batch(&self) -> ComponentBatchCowWithDescriptor<'_> { - ComponentBatchCowWithDescriptor::new(self as &dyn crate::ComponentBatch) - } - - #[inline] - pub fn to_batch(self) -> ComponentBatchCowWithDescriptor<'static> { - ComponentBatchCowWithDescriptor::new(Box::new(self) as Box) - } -} - impl crate::LoggableBatch for NamedIndicatorComponent { #[inline] fn to_arrow(&self) -> SerializationResult { diff --git a/crates/store/re_types_core/src/archetypes/clear.rs b/crates/store/re_types_core/src/archetypes/clear.rs index bc92a191a83ba..4b884ef043560 100644 --- a/crates/store/re_types_core/src/archetypes/clear.rs +++ b/crates/store/re_types_core/src/archetypes/clear.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; @@ -139,9 +139,9 @@ impl crate::Archetype for Clear { } #[inline] - fn indicator() -> ComponentBatchCowWithDescriptor<'static> { - static INDICATOR: ClearIndicator = ClearIndicator::DEFAULT; - ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn crate::ComponentBatch) + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ClearIndicator::DEFAULT.serialized().unwrap() } #[inline] @@ -184,7 +184,7 @@ impl crate::AsComponents for Clear { #[inline] fn as_serialized_batches(&self) -> Vec { use crate::Archetype as _; - [Self::indicator().serialized(), self.is_recursive.clone()] + [Some(Self::indicator()), self.is_recursive.clone()] .into_iter() .flatten() .collect() @@ -242,8 +242,12 @@ impl Clear { .is_recursive .map(|is_recursive| is_recursive.partitioned(_lengths.clone())) .transpose()?]; - let indicator_column = crate::indicator_column::(_lengths.into_iter().count())?; - Ok(columns.into_iter().chain([indicator_column]).flatten()) + Ok(columns + .into_iter() + .flatten() + .chain([crate::indicator_column::( + _lengths.into_iter().count(), + )?])) } /// Helper to partition the component data into unit-length sub-batches. diff --git a/crates/store/re_types_core/src/as_components.rs b/crates/store/re_types_core/src/as_components.rs index 6045561f0508b..2afb204600247 100644 --- a/crates/store/re_types_core/src/as_components.rs +++ b/crates/store/re_types_core/src/as_components.rs @@ -1,6 +1,4 @@ -use crate::{ - ComponentBatch, ComponentBatchCowWithDescriptor, SerializationResult, SerializedComponentBatch, -}; +use crate::{SerializationResult, SerializedComponentBatch}; /// Describes the interface for interpreting an object as a bundle of [`Component`]s. /// @@ -10,8 +8,8 @@ use crate::{ /// it is possible to manually extend existing bundles, or even implement fully custom ones. /// /// All [`AsComponents`] methods are optional to implement, with the exception of -/// [`AsComponents::as_component_batches`], which describes how the bundle can be interpreted -/// as a set of [`ComponentBatch`]es: arrays of components that are ready to be serialized. +/// [`AsComponents::as_serialized_batches`], which describes how the bundle can be interpreted +/// as a set of [`SerializedComponentBatch`]es: serialized component data. /// /// Have a look at our [Custom Data Loader] example to learn more about handwritten bundles. /// @@ -19,32 +17,6 @@ use crate::{ /// [Custom Data Loader]: https://github.com/rerun-io/rerun/blob/latest/examples/rust/custom_data_loader /// [`Component`]: [crate::Component] pub trait AsComponents { - /// Deprecated. Do not use. See [`AsComponents::as_serialized_batches`] instead. - /// - /// Exposes the object's contents as a set of [`ComponentBatch`]s. - /// - /// This is the main mechanism for easily extending builtin archetypes or even writing - /// fully custom ones. - /// Have a look at our [Custom Data Loader] example to learn more about extending archetypes. - /// - /// Implementers of [`AsComponents`] get one last chance to override the tags in the - /// [`ComponentDescriptor`], see [`ComponentBatchCowWithDescriptor::descriptor_override`]. - /// - /// [Custom Data Loader]: https://github.com/rerun-io/rerun/tree/latest/examples/rust/custom_data_loader - /// [`ComponentDescriptor`]: [crate::ComponentDescriptor] - // - // NOTE: Don't bother returning a CoW here: we need to dynamically discard optional components - // depending on their presence (or lack thereof) at runtime anyway. - #[deprecated(since = "0.22.0", note = "use as_serialized_batches instead")] - #[allow(clippy::unimplemented)] // temporary, this method is about to be replaced - fn as_component_batches(&self) -> Vec> { - // Eagerly serialized archetypes simply cannot implement this. - // - // This method only exist while we are in the process of making all existing archetypes - // eagerly serialized, at which point it'll be removed. - unimplemented!() - } - /// Exposes the object's contents as a set of [`SerializedComponentBatch`]es. /// /// This is the main mechanism for easily extending builtin archetypes or even writing @@ -59,19 +31,13 @@ pub trait AsComponents { // // NOTE: Don't bother returning a CoW here: we need to dynamically discard optional components // depending on their presence (or lack thereof) at runtime anyway. - fn as_serialized_batches(&self) -> Vec { - #[allow(deprecated)] // that's the whole point - self.as_component_batches() - .into_iter() - .filter_map(|batch| batch.serialized()) - .collect() - } + fn as_serialized_batches(&self) -> Vec; // --- /// Serializes all non-null [`Component`]s of this bundle into Arrow arrays. /// - /// The default implementation will simply serialize the result of [`Self::as_component_batches`] + /// The default implementation will simply serialize the result of [`Self::as_serialized_batches`] /// as-is, which is what you want in 99.9% of cases. /// /// [`Component`]: [crate::Component] @@ -91,41 +57,6 @@ fn assert_object_safe() { let _: &dyn AsComponents; } -impl AsComponents for dyn ComponentBatch { - #[inline] - fn as_serialized_batches(&self) -> Vec { - self.serialized().into_iter().collect() - } -} - -impl AsComponents for [&dyn ComponentBatch; N] { - #[inline] - fn as_serialized_batches(&self) -> Vec { - self.iter().filter_map(|batch| batch.serialized()).collect() - } -} - -impl AsComponents for [Box; N] { - #[inline] - fn as_serialized_batches(&self) -> Vec { - self.iter().filter_map(|batch| batch.serialized()).collect() - } -} - -impl AsComponents for Vec<&dyn ComponentBatch> { - #[inline] - fn as_serialized_batches(&self) -> Vec { - self.iter().filter_map(|batch| batch.serialized()).collect() - } -} - -impl AsComponents for Vec> { - #[inline] - fn as_serialized_batches(&self) -> Vec { - self.iter().filter_map(|batch| batch.serialized()).collect() - } -} - impl AsComponents for SerializedComponentBatch { #[inline] fn as_serialized_batches(&self) -> Vec { @@ -193,7 +124,7 @@ impl AsComponents for Vec> { /// ```compile_fail /// let comp = re_types_core::components::ClearIsRecursive::default(); -/// let _ = (&comp as &dyn re_types_core::AsComponents).as_component_batches(); +/// let _ = (&comp as &dyn re_types_core::AsComponents).as_serialized_batches(); /// ``` #[allow(dead_code)] #[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation @@ -201,7 +132,7 @@ fn single_ascomponents() {} /// ```compile_fail /// let comp = re_types_core::components::ClearIsRecursive::default(); -/// let _ = (&[comp] as &dyn re_types_core::AsComponents).as_component_batches(); +/// let _ = (&[comp] as &dyn re_types_core::AsComponents).as_serialized_batches(); /// ``` #[allow(dead_code)] #[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation @@ -212,7 +143,7 @@ fn single_ascomponents_wrapped() { /// ```compile_fail /// let comp = re_types_core::components::ClearIsRecursive::default(); -/// let _ = (&[comp, comp, comp] as &dyn re_types_core::AsComponents).as_component_batches(); +/// let _ = (&[comp, comp, comp] as &dyn re_types_core::AsComponents).as_serialized_batches(); /// ``` #[allow(dead_code)] #[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation @@ -224,7 +155,7 @@ fn single_ascomponents_wrapped_many() { /// ```compile_fail /// let comp = re_types_core::components::ClearIsRecursive::default(); /// let comps = vec![comp, comp, comp]; -/// let _ = (&comps as &dyn re_types_core::AsComponents).as_component_batches(); +/// let _ = (&comps as &dyn re_types_core::AsComponents).as_serialized_batches(); /// ``` #[allow(dead_code)] #[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation @@ -233,7 +164,7 @@ fn many_ascomponents() {} /// ```compile_fail /// let comp = re_types_core::components::ClearIsRecursive::default(); /// let comps = vec![comp, comp, comp]; -/// let _ = (&[comps] as &dyn re_types_core::AsComponents).as_component_batches(); +/// let _ = (&[comps] as &dyn re_types_core::AsComponents).as_serialized_batches(); /// ``` #[allow(dead_code)] #[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation @@ -251,7 +182,7 @@ fn many_componentbatch_wrapped() {} /// ```compile_fail /// let comp = re_types_core::components::ClearIsRecursive::default(); /// let comps = vec![comp, comp, comp]; -/// let _ = (&[comps.clone(), comps.clone(), comps.clone()] as &dyn re_types_core::AsComponents).as_component_batches(); +/// let _ = (&[comps.clone(), comps.clone(), comps.clone()] as &dyn re_types_core::AsComponents).as_serialized_batches(); /// ``` #[allow(dead_code)] #[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation @@ -340,11 +271,7 @@ mod tests { let got = { let red = &red as &dyn crate::ComponentBatch; - (&[red] as &dyn crate::AsComponents) - .as_serialized_batches() - .into_iter() - .map(|batch| batch.array) - .collect_vec() + vec![red.try_serialized().unwrap().array] }; let expected = vec![ Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc, @@ -371,11 +298,7 @@ mod tests { let got = { let red = &red as &dyn crate::ComponentBatch; - (&[red] as &dyn crate::AsComponents) - .as_serialized_batches() - .into_iter() - .map(|batch| batch.array) - .collect_vec() + vec![red.try_serialized().unwrap().array] }; let expected = vec![ Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc, @@ -404,11 +327,14 @@ mod tests { let red = &red as &dyn crate::ComponentBatch; let green = &green as &dyn crate::ComponentBatch; let blue = &blue as &dyn crate::ComponentBatch; - (&[red, green, blue] as &dyn crate::AsComponents) - .as_serialized_batches() - .into_iter() - .map(|batch| batch.array) - .collect_vec() + [ + red.try_serialized().unwrap(), + green.try_serialized().unwrap(), + blue.try_serialized().unwrap(), + ] + .into_iter() + .map(|batch| batch.array) + .collect_vec() }; let expected = vec![ Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc, @@ -452,11 +378,7 @@ mod tests { let got = { let colors = &colors as &dyn crate::ComponentBatch; - (&[colors] as &dyn crate::AsComponents) - .as_serialized_batches() - .into_iter() - .map(|batch| batch.array) - .collect_vec() + vec![colors.try_serialized().unwrap().array] }; let expected = vec![Arc::new(ArrowPrimitiveArray::::from(vec![ red.0, green.0, blue.0, @@ -471,11 +393,11 @@ mod tests { // Nothing out of the ordinary here, a collection of batches is indeed a collection of batches. let got = { let colors = &colors as &dyn crate::ComponentBatch; - (&[colors, colors, colors] as &dyn crate::AsComponents) - .as_serialized_batches() - .into_iter() - .map(|batch| batch.array) - .collect_vec() + vec![ + colors.try_serialized().unwrap().array, + colors.try_serialized().unwrap().array, + colors.try_serialized().unwrap().array, + ] }; let expected = vec![ Arc::new(ArrowPrimitiveArray::::from(vec![ diff --git a/crates/store/re_types_core/src/components/clear_is_recursive.rs b/crates/store/re_types_core/src/components/clear_is_recursive.rs index bea7656bbd70d..7c068d97d070a 100644 --- a/crates/store/re_types_core/src/components/clear_is_recursive.rs +++ b/crates/store/re_types_core/src/components/clear_is_recursive.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/bool.rs b/crates/store/re_types_core/src/datatypes/bool.rs index 5b0449faf392e..1eae199487285 100644 --- a/crates/store/re_types_core/src/datatypes/bool.rs +++ b/crates/store/re_types_core/src/datatypes/bool.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/entity_path.rs b/crates/store/re_types_core/src/datatypes/entity_path.rs index 82500a6eb71f2..81fb6bda0ea3a 100644 --- a/crates/store/re_types_core/src/datatypes/entity_path.rs +++ b/crates/store/re_types_core/src/datatypes/entity_path.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/float32.rs b/crates/store/re_types_core/src/datatypes/float32.rs index a896b9511961c..a02985d0a8e67 100644 --- a/crates/store/re_types_core/src/datatypes/float32.rs +++ b/crates/store/re_types_core/src/datatypes/float32.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/float64.rs b/crates/store/re_types_core/src/datatypes/float64.rs index f37dd44c68c08..473b3ccf0f796 100644 --- a/crates/store/re_types_core/src/datatypes/float64.rs +++ b/crates/store/re_types_core/src/datatypes/float64.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/time_int.rs b/crates/store/re_types_core/src/datatypes/time_int.rs index 0e4140163f6a2..7fe9a8ac868e4 100644 --- a/crates/store/re_types_core/src/datatypes/time_int.rs +++ b/crates/store/re_types_core/src/datatypes/time_int.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/time_range.rs b/crates/store/re_types_core/src/datatypes/time_range.rs index bb531e04c3bb6..fec4ef2552afb 100644 --- a/crates/store/re_types_core/src/datatypes/time_range.rs +++ b/crates/store/re_types_core/src/datatypes/time_range.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/time_range_boundary.rs b/crates/store/re_types_core/src/datatypes/time_range_boundary.rs index 00dbf2167aeba..9c2c8e9bd236e 100644 --- a/crates/store/re_types_core/src/datatypes/time_range_boundary.rs +++ b/crates/store/re_types_core/src/datatypes/time_range_boundary.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/uint16.rs b/crates/store/re_types_core/src/datatypes/uint16.rs index 5f5454b8f3988..e89f030d348e7 100644 --- a/crates/store/re_types_core/src/datatypes/uint16.rs +++ b/crates/store/re_types_core/src/datatypes/uint16.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/uint32.rs b/crates/store/re_types_core/src/datatypes/uint32.rs index 7ea217ece7dc2..525f312721192 100644 --- a/crates/store/re_types_core/src/datatypes/uint32.rs +++ b/crates/store/re_types_core/src/datatypes/uint32.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/uint64.rs b/crates/store/re_types_core/src/datatypes/uint64.rs index 278a18839f90c..ea8b6c64a1344 100644 --- a/crates/store/re_types_core/src/datatypes/uint64.rs +++ b/crates/store/re_types_core/src/datatypes/uint64.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/utf8.rs b/crates/store/re_types_core/src/datatypes/utf8.rs index a55595ac30e06..0f72b89195286 100644 --- a/crates/store/re_types_core/src/datatypes/utf8.rs +++ b/crates/store/re_types_core/src/datatypes/utf8.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/datatypes/visible_time_range.rs b/crates/store/re_types_core/src/datatypes/visible_time_range.rs index d666d25e3a63e..029661a6cf3b2 100644 --- a/crates/store/re_types_core/src/datatypes/visible_time_range.rs +++ b/crates/store/re_types_core/src/datatypes/visible_time_range.rs @@ -14,7 +14,7 @@ use crate::try_serialize_field; use crate::SerializationResult; -use crate::{ComponentBatch, ComponentBatchCowWithDescriptor, SerializedComponentBatch}; +use crate::{ComponentBatch, SerializedComponentBatch}; use crate::{ComponentDescriptor, ComponentName}; use crate::{DeserializationError, DeserializationResult}; diff --git a/crates/store/re_types_core/src/lib.rs b/crates/store/re_types_core/src/lib.rs index 4a4354bc42aea..92dec6e9b6862 100644 --- a/crates/store/re_types_core/src/lib.rs +++ b/crates/store/re_types_core/src/lib.rs @@ -48,8 +48,7 @@ pub use self::{ UnorderedComponentNameSet, }, loggable_batch::{ - ComponentBatch, ComponentBatchCow, ComponentBatchCowWithDescriptor, LoggableBatch, - SerializedComponentBatch, SerializedComponentColumn, + ComponentBatch, LoggableBatch, SerializedComponentBatch, SerializedComponentColumn, }, result::{ DeserializationError, DeserializationResult, ResultExt, SerializationError, @@ -192,27 +191,21 @@ pub fn try_serialize_field( #[doc(hidden)] // public so we can access it from re_types too pub fn indicator_column( num_rows: usize, -) -> SerializationResult> { - let indicator: Option = A::indicator().serialized().map(Into::into); - - indicator - .map(|column| { - let SerializedComponentColumn { - list_array, - descriptor, - } = column; - - let (field, _offsets, values, _nulls) = list_array.into_parts(); - - let offsets = arrow::buffer::OffsetBuffer::new_zeroed(num_rows); - let nulls = None; - - arrow::array::ListArray::try_new(field, offsets, values, nulls) - .map(|list_array| SerializedComponentColumn { - list_array, - descriptor, - }) - .map_err(Into::into) +) -> SerializationResult { + let SerializedComponentColumn { + list_array, + descriptor, + } = A::indicator().into(); + + let (field, _offsets, values, _nulls) = list_array.into_parts(); + + let offsets = arrow::buffer::OffsetBuffer::new_zeroed(num_rows); + let nulls = None; + + arrow::array::ListArray::try_new(field, offsets, values, nulls) + .map(|list_array| SerializedComponentColumn { + list_array, + descriptor, }) - .transpose() + .map_err(Into::into) } diff --git a/crates/store/re_types_core/src/loggable_batch.rs b/crates/store/re_types_core/src/loggable_batch.rs index f483c97f0dd6e..9b2b586f7b5ed 100644 --- a/crates/store/re_types_core/src/loggable_batch.rs +++ b/crates/store/re_types_core/src/loggable_batch.rs @@ -52,21 +52,6 @@ pub trait ComponentBatch: LoggableBatch { /// Every component batch is uniquely identified by its [`ComponentDescriptor`]. fn descriptor(&self) -> Cow<'_, ComponentDescriptor>; - // Wraps the current [`ComponentBatch`] with the given descriptor. - // - // TODO(cmc): This should probably go away, but we'll see about that once I start tackling - // partial updates themselves. - fn with_descriptor( - &self, - descriptor: ComponentDescriptor, - ) -> ComponentBatchCowWithDescriptor<'_> - where - Self: Sized, - { - ComponentBatchCowWithDescriptor::new(ComponentBatchCow::Ref(self as &dyn ComponentBatch)) - .with_descriptor_override(descriptor) - } - /// Serializes the contents of this [`ComponentBatch`]. /// /// Once serialized, the data is ready to be logged into Rerun via the [`AsComponents`] trait. @@ -350,119 +335,6 @@ impl From<&SerializedComponentBatch> for arrow::datatypes::Field { } } -// --- - -// TODO(cmc): All these crazy types are about to disappear. ComponentBatch should only live at the -// edge, and therefore not require all these crazy kinds of derivatives (require eager serialization). - -/// Some [`ComponentBatch`], optionally with an overridden [`ComponentDescriptor`]. -/// -/// Used by implementers of [`crate::AsComponents`] to both efficiently expose their component data -/// and assign the right tags given the surrounding context. -pub struct ComponentBatchCowWithDescriptor<'a> { - /// The component data. - pub batch: ComponentBatchCow<'a>, - - /// If set, will override the [`ComponentBatch`]'s [`ComponentDescriptor`]. - pub descriptor_override: Option, -} - -impl<'a> From> for ComponentBatchCowWithDescriptor<'a> { - #[inline] - fn from(batch: ComponentBatchCow<'a>) -> Self { - Self::new(batch) - } -} - -impl<'a> ComponentBatchCowWithDescriptor<'a> { - #[inline] - pub fn new(batch: impl Into>) -> Self { - Self { - batch: batch.into(), - descriptor_override: None, - } - } - - #[inline] - pub fn with_descriptor_override(self, descriptor: ComponentDescriptor) -> Self { - Self { - descriptor_override: Some(descriptor), - ..self - } - } -} - -impl LoggableBatch for ComponentBatchCowWithDescriptor<'_> { - #[inline] - fn to_arrow(&self) -> SerializationResult { - self.batch.to_arrow() - } -} - -impl ComponentBatch for ComponentBatchCowWithDescriptor<'_> { - #[inline] - fn descriptor(&self) -> Cow<'_, ComponentDescriptor> { - self.descriptor_override - .as_ref() - .map(Into::into) - .unwrap_or_else(|| self.batch.descriptor()) - } - - #[inline] - fn name(&self) -> ComponentName { - self.batch.name() - } -} - -/// Holds either an owned [`ComponentBatch`] that lives on heap, or a reference to one. -/// -/// This doesn't use [`std::borrow::Cow`] on purpose: `Cow` requires `Clone`, which would break -/// object-safety, which would prevent us from erasing [`ComponentBatch`]s in the first place. -pub enum ComponentBatchCow<'a> { - Owned(Box), - Ref(&'a dyn ComponentBatch), -} - -impl<'a> From<&'a dyn ComponentBatch> for ComponentBatchCow<'a> { - #[inline] - fn from(comp_batch: &'a dyn ComponentBatch) -> Self { - Self::Ref(comp_batch) - } -} - -impl From> for ComponentBatchCow<'_> { - #[inline] - fn from(comp_batch: Box) -> Self { - Self::Owned(comp_batch) - } -} - -impl<'a> std::ops::Deref for ComponentBatchCow<'a> { - type Target = dyn ComponentBatch + 'a; - - #[inline] - fn deref(&self) -> &(dyn ComponentBatch + 'a) { - match self { - ComponentBatchCow::Owned(this) => &**this, - ComponentBatchCow::Ref(this) => *this, - } - } -} - -impl LoggableBatch for ComponentBatchCow<'_> { - #[inline] - fn to_arrow(&self) -> SerializationResult { - (**self).to_arrow() - } -} - -impl ComponentBatch for ComponentBatchCow<'_> { - #[inline] - fn descriptor(&self) -> Cow<'_, ComponentDescriptor> { - (**self).descriptor() - } -} - // --- Unary --- impl LoggableBatch for L { diff --git a/crates/top/re_sdk/src/lib.rs b/crates/top/re_sdk/src/lib.rs index f353c8dc7201f..0a2d442ac1858 100644 --- a/crates/top/re_sdk/src/lib.rs +++ b/crates/top/re_sdk/src/lib.rs @@ -94,11 +94,10 @@ pub mod time { pub use time::{Time, TimePoint, Timeline}; pub use re_types_core::{ - Archetype, ArchetypeName, AsComponents, Component, ComponentBatch, ComponentBatchCow, - ComponentBatchCowWithDescriptor, ComponentDescriptor, ComponentName, DatatypeName, - DeserializationError, DeserializationResult, GenericIndicatorComponent, Loggable, - LoggableBatch, NamedIndicatorComponent, SerializationError, SerializationResult, - SerializedComponentBatch, SerializedComponentColumn, + Archetype, ArchetypeName, AsComponents, Component, ComponentBatch, ComponentDescriptor, + ComponentName, DatatypeName, DeserializationError, DeserializationResult, + GenericIndicatorComponent, Loggable, LoggableBatch, NamedIndicatorComponent, + SerializationError, SerializationResult, SerializedComponentBatch, SerializedComponentColumn, }; pub use re_byte_size::SizeBytes; diff --git a/crates/top/re_sdk/src/recording_stream.rs b/crates/top/re_sdk/src/recording_stream.rs index 1b63d51d6e82d..8348ab5e2eccb 100644 --- a/crates/top/re_sdk/src/recording_stream.rs +++ b/crates/top/re_sdk/src/recording_stream.rs @@ -1086,79 +1086,6 @@ impl RecordingStream { ) } - /// Logs a set of [`re_types_core::ComponentBatch`]es into Rerun. - /// - /// If `static_` is set to `true`, all timestamp data associated with this message will be - /// dropped right before sending it to Rerun. - /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows - /// any temporal data of the same type. - /// - /// Otherwise, the data will be timestamped automatically based on the [`RecordingStream`]'s - /// internal clock. - /// See `RecordingStream::set_time_*` family of methods for more information. - /// - /// The number of instances will be determined by the longest batch in the bundle. - /// - /// The entity path can either be a string - /// (with special characters escaped, split on unescaped slashes) - /// or an [`EntityPath`] constructed with [`crate::entity_path`]. - /// See for more on entity paths. - /// - /// Internally, the stream will automatically micro-batch multiple log calls to optimize - /// transport. - /// See [SDK Micro Batching] for more information. - /// - /// [SDK Micro Batching]: https://www.rerun.io/docs/reference/sdk/micro-batching - #[deprecated(since = "0.22.0", note = "use log_serialized_batches instead")] - pub fn log_component_batches<'a>( - &self, - ent_path: impl Into, - static_: bool, - comp_batches: impl IntoIterator, - ) -> RecordingStreamResult<()> { - let row_id = RowId::new(); // Create row-id as early as possible. It has a timestamp and is used to estimate e2e latency. - self.log_component_batches_impl(row_id, ent_path, static_, comp_batches) - } - - fn log_component_batches_impl<'a>( - &self, - row_id: RowId, - entity_path: impl Into, - static_: bool, - comp_batches: impl IntoIterator, - ) -> RecordingStreamResult<()> { - if !self.is_enabled() { - return Ok(()); // silently drop the message - } - - let entity_path = entity_path.into(); - - let comp_batches: Result, _> = comp_batches - .into_iter() - .map(|comp_batch| { - comp_batch - .to_arrow() - .map(|array| (comp_batch.descriptor().into_owned(), array)) - }) - .collect(); - let components: IntMap<_, _> = comp_batches?.into_iter().collect(); - - // NOTE: The timepoint is irrelevant, the `RecordingStream` will overwrite it using its - // internal clock. - let timepoint = TimePoint::default(); - - if !components.is_empty() { - let row = PendingRow { - row_id, - timepoint, - components, - }; - self.record_row(entity_path, row, !static_); - } - - Ok(()) - } - /// Logs a set of [`SerializedComponentBatch`]es into Rerun. /// /// If `static_` is set to `true`, all timestamp data associated with this message will be @@ -2658,7 +2585,8 @@ mod tests { .unwrap(); // This call used to *not* compile due to a lack of `?Sized` bounds. - rec.log("labels", &labels as &dyn crate::ComponentBatch) + use re_types_core::ComponentBatch as _; + rec.log("labels", &labels.try_serialized().unwrap()) .unwrap(); } } diff --git a/crates/viewer/re_data_ui/src/instance_path.rs b/crates/viewer/re_data_ui/src/instance_path.rs index dd3f07dae4948..c7e5092329c0a 100644 --- a/crates/viewer/re_data_ui/src/instance_path.rs +++ b/crates/viewer/re_data_ui/src/instance_path.rs @@ -8,7 +8,7 @@ use re_types::{ archetypes, components, datatypes::{ChannelDatatype, ColorModel}, image::ImageKind, - Archetype, Component, ComponentName, + Component, ComponentName, }; use re_ui::UiExt as _; use re_viewer_context::{ @@ -301,13 +301,13 @@ fn preview_if_image_ui( .ok()?; // TODO(#8129): it's ugly but indicators are going away next anyway. - let kind = if component_map.contains_key(&re_types_core::ComponentBatch::name( - &archetypes::DepthImage::indicator(), - )) { + let kind = if component_map + .contains_key(&archetypes::DepthImage::descriptor_indicator().component_name) + { ImageKind::Depth - } else if component_map.contains_key(&re_types_core::ComponentBatch::name( - &archetypes::SegmentationImage::indicator(), - )) { + } else if component_map + .contains_key(&archetypes::SegmentationImage::descriptor_indicator().component_name) + { ImageKind::Segmentation } else { ImageKind::Color diff --git a/crates/viewer/re_view_spatial/src/view_2d.rs b/crates/viewer/re_view_spatial/src/view_2d.rs index 1949cfa043cb5..3a33f48b884fb 100644 --- a/crates/viewer/re_view_spatial/src/view_2d.rs +++ b/crates/viewer/re_view_spatial/src/view_2d.rs @@ -7,7 +7,7 @@ use re_types::View; use re_types::{ archetypes::{DepthImage, Image}, blueprint::archetypes::{Background, NearClipPlane, VisualBounds2D}, - Archetype, ComponentName, ViewClassIdentifier, + ComponentName, ViewClassIdentifier, }; use re_ui::UiExt as _; use re_view::view_property_ui; @@ -367,13 +367,12 @@ fn recommended_views_with_image_splits( &mut found_image_dimensions, ); - use re_types::ComponentBatch as _; let image_count = count_non_nested_images_with_component( image_dimensions, entities, ctx.recording(), subtree, - &Image::indicator().name(), + &Image::descriptor_indicator().component_name, ); let depth_count = count_non_nested_images_with_component( @@ -381,7 +380,7 @@ fn recommended_views_with_image_splits( entities, ctx.recording(), subtree, - &DepthImage::indicator().name(), + &DepthImage::descriptor_indicator().component_name, ); let video_count = count_non_nested_images_with_component( @@ -389,7 +388,7 @@ fn recommended_views_with_image_splits( entities, ctx.recording(), subtree, - &re_types::archetypes::AssetVideo::indicator().name(), + &re_types::archetypes::AssetVideo::descriptor_indicator().component_name, ); let all_have_same_size = found_image_dimensions.len() <= 1; diff --git a/crates/viewer/re_view_time_series/src/line_visualizer_system.rs b/crates/viewer/re_view_time_series/src/line_visualizer_system.rs index d8b88011e8ef4..baf5fb8d79b02 100644 --- a/crates/viewer/re_view_time_series/src/line_visualizer_system.rs +++ b/crates/viewer/re_view_time_series/src/line_visualizer_system.rs @@ -44,8 +44,8 @@ impl VisualizerSystem for SeriesLineSystem { .map(|descr| descr.component_name), ); - use re_types::ComponentBatch as _; - query_info.indicators = std::iter::once(SeriesLine::indicator().name()).collect(); + query_info.indicators = + std::iter::once(SeriesLine::descriptor_indicator().component_name).collect(); query_info } diff --git a/crates/viewer/re_view_time_series/src/point_visualizer_system.rs b/crates/viewer/re_view_time_series/src/point_visualizer_system.rs index 94810b6e1b8ac..08ad127eb5e7e 100644 --- a/crates/viewer/re_view_time_series/src/point_visualizer_system.rs +++ b/crates/viewer/re_view_time_series/src/point_visualizer_system.rs @@ -44,8 +44,8 @@ impl VisualizerSystem for SeriesPointSystem { .map(|descr| descr.component_name), ); - use re_types::ComponentBatch as _; - query_info.indicators = std::iter::once(SeriesPoint::indicator().name()).collect(); + query_info.indicators = + std::iter::once(SeriesPoint::descriptor_indicator().component_name).collect(); query_info } diff --git a/crates/viewer/re_viewer_context/src/view/visualizer_system.rs b/crates/viewer/re_viewer_context/src/view/visualizer_system.rs index 64e933e87964a..7307798f0419f 100644 --- a/crates/viewer/re_viewer_context/src/view/visualizer_system.rs +++ b/crates/viewer/re_viewer_context/src/view/visualizer_system.rs @@ -54,15 +54,14 @@ pub struct VisualizerQueryInfo { } impl VisualizerQueryInfo { - pub fn from_archetype() -> Self { - use re_types_core::ComponentBatch as _; + pub fn from_archetype() -> Self { Self { - indicators: std::iter::once(T::indicator().name()).collect(), - required: T::required_components() + indicators: std::iter::once(A::indicator().descriptor.component_name).collect(), + required: A::required_components() .iter() .map(|descr| descr.component_name) .collect(), - queried: T::all_components() + queried: A::all_components() .iter() .map(|descr| descr.component_name) .collect(), diff --git a/docs/snippets/all/archetypes/mesh3d_partial_updates.rs b/docs/snippets/all/archetypes/mesh3d_partial_updates.rs index f3d2533b886a6..b7d9eb14a7bee 100644 --- a/docs/snippets/all/archetypes/mesh3d_partial_updates.rs +++ b/docs/snippets/all/archetypes/mesh3d_partial_updates.rs @@ -21,12 +21,15 @@ fn main() -> Result<(), Box> { rec.set_time_sequence("frame", i); let factor = (i as f32 * 0.04).sin().abs(); - let vertex_positions: [rerun::Position3D; 3] = [ - (glam::Vec3::from(vertex_positions[0]) * factor).into(), - (glam::Vec3::from(vertex_positions[1]) * factor).into(), - (glam::Vec3::from(vertex_positions[2]) * factor).into(), + let vertex_positions = [ + (glam::Vec3::from(vertex_positions[0]) * factor), + (glam::Vec3::from(vertex_positions[1]) * factor), + (glam::Vec3::from(vertex_positions[2]) * factor), ]; - rec.log("triangle", &vertex_positions as &dyn rerun::ComponentBatch)?; + rec.log( + "triangle", + &rerun::Mesh3D::update_fields().with_vertex_positions(vertex_positions), + )?; } Ok(()) diff --git a/docs/snippets/all/concepts/different_data_per_timeline.rs b/docs/snippets/all/concepts/different_data_per_timeline.rs index 0f13e9e4441be..2c1a2f42342fb 100644 --- a/docs/snippets/all/concepts/different_data_per_timeline.rs +++ b/docs/snippets/all/concepts/different_data_per_timeline.rs @@ -13,7 +13,7 @@ fn main() -> Result<(), Box> { rec.set_time_seconds("red timeline", 1.0); rec.log( "points", - &[&rerun::components::Color::from_u32(0xFF0000FF) as &dyn rerun::ComponentBatch], + &rerun::Points2D::update_fields().with_colors([0xFF0000FF]), )?; // And a blue color on the other. @@ -21,7 +21,7 @@ fn main() -> Result<(), Box> { rec.set_time_sequence("blue timeline", 1); rec.log( "points", - &[&rerun::components::Color::from_u32(0x0000FFFF) as &dyn rerun::ComponentBatch], + &rerun::Points2D::update_fields().with_colors([0x0000FFFF]), )?; // TODO(#5521): log VisualBounds2D diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.rs b/docs/snippets/all/descriptors/descr_custom_archetype.rs index 83cab7434ce6b..6bde8415329c0 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.rs +++ b/docs/snippets/all/descriptors/descr_custom_archetype.rs @@ -26,16 +26,16 @@ impl CustomPoints3D { } impl rerun::AsComponents for CustomPoints3D { - fn as_component_batches(&self) -> Vec> { + fn as_serialized_batches(&self) -> Vec { [ - Some(Self::indicator().to_batch()), - Some( - self.positions - .with_descriptor(Self::overridden_position_descriptor()), - ), + Self::indicator().serialized(), + self.positions.serialized().map(|positions| { + positions.with_descriptor_override(Self::overridden_position_descriptor()) + }), self.colors .as_ref() - .map(|colors| colors.with_descriptor(Self::overridden_color_descriptor())), + .and_then(|colors| colors.serialized()) + .map(|colors| colors.with_descriptor_override(Self::overridden_color_descriptor())), ] .into_iter() .flatten() diff --git a/examples/rust/custom_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_view/src/color_coordinates_visualizer_system.rs index 4f9f20bfe9558..d65fa2c481f7d 100644 --- a/examples/rust/custom_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_view/src/color_coordinates_visualizer_system.rs @@ -25,6 +25,12 @@ struct ColorArchetype; impl re_types::Archetype for ColorArchetype { type Indicator = re_types::GenericIndicatorComponent; + fn indicator() -> re_types::SerializedComponentBatch { + use re_types::ComponentBatch as _; + #[allow(clippy::unwrap_used)] + Self::Indicator::default().serialized().unwrap() + } + fn name() -> re_types::ArchetypeName { "InstanceColor".into() } From d0c41069459dfc01150aa730e573d6dd51e8c6c3 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 28 Jan 2025 08:20:04 -0500 Subject: [PATCH 21/43] Start including grpc feature in release (#8825) ### What Start including the `grpc` feature in release so we don't need adhoc builds/wheels for testing features. --- crates/top/rerun-cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/top/rerun-cli/Cargo.toml b/crates/top/rerun-cli/Cargo.toml index 18e3f17789496..9f435772cac63 100644 --- a/crates/top/rerun-cli/Cargo.toml +++ b/crates/top/rerun-cli/Cargo.toml @@ -58,7 +58,7 @@ default = ["native_viewer", "web_viewer", "map_view"] ## The features we enable when we build the pre-built binaries during our releases. ## This may enable features that require extra build tools that not everyone has. -release = ["default", "nasm"] +release = ["default", "grpc", "nasm"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. From 8e1e5d962fc4a6e13d6d260d11d4c2106e188b29 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:20:14 +0100 Subject: [PATCH 22/43] The empty/full entity icon now reflects presence of component on the current timeline (#8839) ### What According to the code, the entity icon was supposed to reflect the existence of data _on the current timeline_. However, due to a bug in `all_components_on_timline`, it reflected the existence of data _on any timeline_. This PR fixes the aforementioned bug. As a result, the icon now _actually_ represents the state on current timeline. Some snapshot tests had to be fixed to pass. **Reminder**: As soon as a static component is logged to an entity, it is deemed to have data on _all_ past, present, and future timelines. As a result, it always has the "full" icon. --------- Co-authored-by: jprochazk --- crates/store/re_chunk_store/src/query.rs | 50 ++++++++++------ crates/store/re_chunk_store/tests/reads.rs | 58 +++++++++++++++++++ .../tests/blueprint_tree_tests.rs | 8 ++- .../tests/view_structure_test.rs | 5 +- .../re_viewer_context/src/test_context.rs | 9 ++- 5 files changed, 109 insertions(+), 21 deletions(-) diff --git a/crates/store/re_chunk_store/src/query.rs b/crates/store/re_chunk_store/src/query.rs index 8a1b344cf9139..f6bc4cc2a13e0 100644 --- a/crates/store/re_chunk_store/src/query.rs +++ b/crates/store/re_chunk_store/src/query.rs @@ -117,25 +117,32 @@ impl ChunkStore { .static_chunk_ids_per_entity .get(entity_path) .map(|static_chunks_per_component| { - static_chunks_per_component.keys().copied().collect() - }); + static_chunks_per_component + .keys() + .copied() + .collect::() + }) + .filter(|names| !names.is_empty()); let temporal_components: Option = self .temporal_chunk_ids_per_entity_per_component .get(entity_path) .map(|temporal_chunk_ids_per_timeline| { temporal_chunk_ids_per_timeline - .iter() - .filter(|(cur_timeline, _)| *cur_timeline == timeline) - .flat_map(|(_, temporal_chunk_ids_per_component)| { - temporal_chunk_ids_per_component.keys().copied() + .get(timeline) + .map(|temporal_chunk_ids_per_component| { + temporal_chunk_ids_per_component + .keys() + .copied() + .collect::() }) - .collect() - }); + .unwrap_or_default() + }) + .filter(|names| !names.is_empty()); match (static_components, temporal_components) { (None, None) => None, - (None, comps @ Some(_)) | (comps @ Some(_), None) => comps, + (None, Some(comps)) | (Some(comps), None) => Some(comps), (Some(static_comps), Some(temporal_comps)) => { Some(static_comps.into_iter().chain(temporal_comps).collect()) } @@ -159,25 +166,32 @@ impl ChunkStore { .static_chunk_ids_per_entity .get(entity_path) .map(|static_chunks_per_component| { - static_chunks_per_component.keys().copied().collect() - }); + static_chunks_per_component + .keys() + .copied() + .collect::() + }) + .filter(|names| !names.is_empty()); let temporal_components: Option = self .temporal_chunk_ids_per_entity_per_component .get(entity_path) .map(|temporal_chunk_ids_per_timeline| { temporal_chunk_ids_per_timeline - .iter() - .filter(|(cur_timeline, _)| *cur_timeline == timeline) - .flat_map(|(_, temporal_chunk_ids_per_component)| { - temporal_chunk_ids_per_component.keys().copied() + .get(timeline) + .map(|temporal_chunk_ids_per_component| { + temporal_chunk_ids_per_component + .keys() + .copied() + .collect::() }) - .collect() - }); + .unwrap_or_default() + }) + .filter(|names| !names.is_empty()); match (static_components, temporal_components) { (None, None) => None, - (None, comps @ Some(_)) | (comps @ Some(_), None) => comps, + (None, Some(comps)) | (Some(comps), None) => Some(comps), (Some(static_comps), Some(temporal_comps)) => { Some(static_comps.into_iter().chain(temporal_comps).collect()) } diff --git a/crates/store/re_chunk_store/tests/reads.rs b/crates/store/re_chunk_store/tests/reads.rs index 1ebc112c6ecdc..7e5760ee9fc62 100644 --- a/crates/store/re_chunk_store/tests/reads.rs +++ b/crates/store/re_chunk_store/tests/reads.rs @@ -125,6 +125,64 @@ fn all_components() -> anyhow::Result<()> { Ok(()) } +#[test] +fn test_all_components_on_timeline() -> anyhow::Result<()> { + re_log::setup_logging(); + + let entity_path1 = EntityPath::from("both/timeline"); + let entity_path2 = EntityPath::from("only/timeline1"); + + let timeline1 = Timeline::new("timeline1", TimeType::Sequence); + let timeline2 = Timeline::new("timeline2", TimeType::Sequence); + + let time = TimeInt::new_temporal(1); + + let mut store = ChunkStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + ChunkStoreConfig::COMPACTION_DISABLED, + ); + + let chunk = Chunk::builder(entity_path1.clone()) + .with_component_batch( + RowId::new(), + [(timeline1, time), (timeline2, time)], + &build_some_large_structs(2), + ) + .build()?; + store.insert_chunk(&Arc::new(chunk))?; + + let chunk = Chunk::builder(entity_path2.clone()) + .with_component_batches( + RowId::new(), + [(timeline1, time)], + [&build_some_large_structs(2) as _], + ) + .build()?; + store.insert_chunk(&Arc::new(chunk))?; + + // entity1 is on both timelines + assert!(!store + .all_components_on_timeline(&timeline1, &entity_path1) + .unwrap() + .is_empty()); + assert!(!store + .all_components_on_timeline(&timeline2, &entity_path1) + .unwrap() + .is_empty()); + + // entity2 is only on timeline1 + assert!(!store + .all_components_on_timeline(&timeline1, &entity_path2) + .unwrap() + .is_empty()); + + assert!(store + .all_components_on_timeline(&timeline2, &entity_path2) + .is_none()); + + Ok(()) +} + // --- #[test] diff --git a/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs b/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs index a07681b53fd9c..481df5767bcf1 100644 --- a/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs +++ b/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs @@ -5,7 +5,7 @@ use egui::Vec2; use re_blueprint_tree::BlueprintTree; use re_chunk_store::external::re_chunk::ChunkBuilder; use re_chunk_store::RowId; -use re_log_types::build_frame_nr; +use re_log_types::{build_frame_nr, Timeline}; use re_types::archetypes::Points3D; use re_viewer_context::{ test_context::TestContext, CollapseScope, RecommendedView, ViewClass, ViewId, @@ -72,6 +72,9 @@ fn collapse_expand_all_blueprint_panel_should_match_snapshot() { let mut blueprint_tree = BlueprintTree::default(); + // set the current timeline to the timeline where data was logged to + test_context.set_active_timeline(Timeline::new_sequence("frame_nr")); + let mut harness = test_context .setup_kittest_for_rendering() .with_size(Vec2::new(400.0, 800.0)) @@ -191,6 +194,9 @@ fn run_blueprint_panel_and_save_snapshot( mut blueprint_tree: BlueprintTree, snapshot_name: &str, ) { + // set the current timeline to the timeline where data was logged to + test_context.set_active_timeline(Timeline::new_sequence("frame_nr")); + let mut harness = test_context .setup_kittest_for_rendering() .with_size(Vec2::new(400.0, 800.0)) diff --git a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs index 8c318f4fb374e..3645d7fcb4adb 100644 --- a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +++ b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs @@ -11,7 +11,7 @@ use re_blueprint_tree::data::BlueprintTreeData; use re_blueprint_tree::BlueprintTree; use re_chunk_store::external::re_chunk::ChunkBuilder; use re_chunk_store::RowId; -use re_log_types::{build_frame_nr, EntityPath}; +use re_log_types::{build_frame_nr, EntityPath, Timeline}; use re_types::archetypes::Points3D; use re_ui::filter_widget::FilterState; use re_viewer_context::test_context::TestContext; @@ -171,6 +171,9 @@ fn run_test_case(test_case: &TestCase, filter_query: Option<&str>) -> Result<(), blueprint_tree.activate_filter(filter_query); } + // set the current timeline to the timeline where data was logged to + test_context.set_active_timeline(Timeline::new_sequence("frame_nr")); + let mut harness = test_context .setup_kittest_for_rendering() .with_size(Vec2::new(400.0, 800.0)) diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index d00d5ef41efff..d59bd21eaa769 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -8,7 +8,7 @@ use parking_lot::Mutex; use re_chunk::{Chunk, ChunkBuilder}; use re_chunk_store::LatestAtQuery; use re_entity_db::EntityDb; -use re_log_types::{EntityPath, StoreId, StoreKind}; +use re_log_types::{EntityPath, StoreId, StoreKind, Timeline}; use re_types_core::reflection::Reflection; use crate::{ @@ -201,6 +201,13 @@ impl TestContext { *self.recording_config.time_ctrl.read().timeline() } + pub fn set_active_timeline(&self, timeline: Timeline) { + self.recording_config + .time_ctrl + .write() + .set_timeline(timeline); + } + pub fn edit_selection(&mut self, edit_fn: impl FnOnce(&mut ApplicationSelectionState)) { edit_fn(&mut self.selection_state); From 24a233fabb61fd4fbcccba600483a7cb1a5cb558 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 28 Jan 2025 14:22:29 +0100 Subject: [PATCH 23/43] Explain and test the hashing behavior relied upon in the micro-batcher (#8831) Title. * Supersedes #https://github.com/rerun-io/rerun/pull/8788 --- crates/store/re_chunk/src/batcher.rs | 180 +++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 8 deletions(-) diff --git a/crates/store/re_chunk/src/batcher.rs b/crates/store/re_chunk/src/batcher.rs index 662ccdbecb6a3..ba99ed0e4b315 100644 --- a/crates/store/re_chunk/src/batcher.rs +++ b/crates/store/re_chunk/src/batcher.rs @@ -797,6 +797,8 @@ impl PendingRow { { re_tracing::profile_scope!("compute timeline sets"); + // The hash is deterministic because the traversal of a `TimePoint` is itself + // deterministic: `TimePoint` is backed by a `BTreeMap`. for row in rows { let mut hasher = ahash::AHasher::default(); row.timepoint @@ -819,6 +821,18 @@ impl PendingRow { { re_tracing::profile_scope!("compute datatype sets"); + // The hash is dependent on the order in which the `PendingRow` was created (i.e. + // the order in which its components were inserted). + // + // This is because the components are stored in a `IntMap`, which doesn't do any + // hashing. For that reason, the traversal order of a `IntMap` in deterministic: + // it's always the same for `IntMap` that share the same keys, as long as these + // keys were inserted in the same order. + // See `intmap_order_is_deterministic` in the tests below. + // + // In practice, the `PendingRow`s in a given program are always built in the same + // order for the duration of that program, which is why this works. + // See `simple_but_hashes_wont_match` in the tests below. for row in rows { let mut hasher = ahash::AHasher::default(); row.components @@ -1007,7 +1021,7 @@ impl PendingTimeColumn { mod tests { use crossbeam::channel::TryRecvError; - use re_log_types::example_components::{MyPoint, MyPoint64}; + use re_log_types::example_components::{MyColor, MyIndex, MyLabel, MyPoint, MyPoint64}; use re_types_core::{Component as _, Loggable as _}; use super::*; @@ -1027,9 +1041,29 @@ mod tests { let points2 = MyPoint::to_arrow([MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)])?; let points3 = MyPoint::to_arrow([MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)])?; - let components1 = [(MyPoint::descriptor(), points1.clone())]; - let components2 = [(MyPoint::descriptor(), points2.clone())]; - let components3 = [(MyPoint::descriptor(), points3.clone())]; + let labels1 = MyLabel::to_arrow([MyLabel("a".into()), MyLabel("b".into())])?; + let labels2 = MyLabel::to_arrow([MyLabel("c".into()), MyLabel("d".into())])?; + let labels3 = MyLabel::to_arrow([MyLabel("e".into()), MyLabel("d".into())])?; + + let indices1 = MyIndex::to_arrow([MyIndex(0), MyIndex(1)])?; + let indices2 = MyIndex::to_arrow([MyIndex(2), MyIndex(3)])?; + let indices3 = MyIndex::to_arrow([MyIndex(4), MyIndex(5)])?; + + let components1 = [ + (MyPoint::descriptor(), points1.clone()), + (MyLabel::descriptor(), labels1.clone()), + (MyIndex::descriptor(), indices1.clone()), + ]; + let components2 = [ + (MyPoint::descriptor(), points2.clone()), + (MyLabel::descriptor(), labels2.clone()), + (MyIndex::descriptor(), indices2.clone()), + ]; + let components3 = [ + (MyPoint::descriptor(), points3.clone()), + (MyLabel::descriptor(), labels3.clone()), + (MyIndex::descriptor(), indices3.clone()), + ]; let row1 = PendingRow::new(timepoint1.clone(), components1.into_iter().collect()); let row2 = PendingRow::new(timepoint2.clone(), components2.into_iter().collect()); @@ -1069,11 +1103,29 @@ mod tests { timeline1, TimeColumn::new(Some(true), timeline1, vec![42, 43, 44].into()), )]; - let expected_components = [( - MyPoint::descriptor(), - arrow_util::arrays_to_list_array_opt(&[&*points1, &*points2, &*points3].map(Some)) + let expected_components = [ + ( + MyPoint::descriptor(), + arrow_util::arrays_to_list_array_opt( + &[&*points1, &*points2, &*points3].map(Some), + ) .unwrap(), - )]; + ), // + ( + MyLabel::descriptor(), + arrow_util::arrays_to_list_array_opt( + &[&*labels1, &*labels2, &*labels3].map(Some), + ) + .unwrap(), + ), // + ( + MyIndex::descriptor(), + arrow_util::arrays_to_list_array_opt( + &[&*indices1, &*indices2, &*indices3].map(Some), + ) + .unwrap(), + ), // + ]; let expected_chunk = Chunk::from_native_row_ids( chunks[0].id, entity_path1.clone(), @@ -1091,6 +1143,118 @@ mod tests { Ok(()) } + #[test] + #[allow(clippy::len_zero)] + fn simple_but_hashes_might_not_match() -> anyhow::Result<()> { + let batcher = ChunkBatcher::new(ChunkBatcherConfig::NEVER)?; + + let timeline1 = Timeline::new_temporal("log_time"); + + let timepoint1 = TimePoint::default().with(timeline1, 42); + let timepoint2 = TimePoint::default().with(timeline1, 43); + let timepoint3 = TimePoint::default().with(timeline1, 44); + + let points1 = MyPoint::to_arrow([MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)])?; + let points2 = MyPoint::to_arrow([MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)])?; + let points3 = MyPoint::to_arrow([MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)])?; + + let labels1 = MyLabel::to_arrow([MyLabel("a".into()), MyLabel("b".into())])?; + let labels2 = MyLabel::to_arrow([MyLabel("c".into()), MyLabel("d".into())])?; + let labels3 = MyLabel::to_arrow([MyLabel("e".into()), MyLabel("d".into())])?; + + let indices1 = MyIndex::to_arrow([MyIndex(0), MyIndex(1)])?; + let indices2 = MyIndex::to_arrow([MyIndex(2), MyIndex(3)])?; + let indices3 = MyIndex::to_arrow([MyIndex(4), MyIndex(5)])?; + + let components1 = [ + (MyIndex::descriptor(), indices1.clone()), + (MyPoint::descriptor(), points1.clone()), + (MyLabel::descriptor(), labels1.clone()), + ]; + let components2 = [ + (MyPoint::descriptor(), points2.clone()), + (MyLabel::descriptor(), labels2.clone()), + (MyIndex::descriptor(), indices2.clone()), + ]; + let components3 = [ + (MyLabel::descriptor(), labels3.clone()), + (MyIndex::descriptor(), indices3.clone()), + (MyPoint::descriptor(), points3.clone()), + ]; + + let row1 = PendingRow::new(timepoint1.clone(), components1.into_iter().collect()); + let row2 = PendingRow::new(timepoint2.clone(), components2.into_iter().collect()); + let row3 = PendingRow::new(timepoint3.clone(), components3.into_iter().collect()); + + let entity_path1: EntityPath = "a/b/c".into(); + batcher.push_row(entity_path1.clone(), row1.clone()); + batcher.push_row(entity_path1.clone(), row2.clone()); + batcher.push_row(entity_path1.clone(), row3.clone()); + + let chunks_rx = batcher.chunks(); + drop(batcher); // flush and close + + let mut chunks = Vec::new(); + loop { + let chunk = match chunks_rx.try_recv() { + Ok(chunk) => chunk, + Err(TryRecvError::Empty) => panic!("expected chunk, got none"), + Err(TryRecvError::Disconnected) => break, + }; + chunks.push(chunk); + } + + chunks.sort_by_key(|chunk| chunk.row_id_range().unwrap().0); + + // Make the programmer's life easier if this test fails. + eprintln!("Chunks:"); + for chunk in &chunks { + eprintln!("{chunk}"); + } + + // The rows's components were inserted in different orders, and therefore the resulting + // `IntMap`s *may* have different traversal orders, which ultimately means that the datatype + // hashes *may* end up being different: i.e., possibly no batching. + // + // In practice, it's still possible to get lucky and end up with two maps that just happen + // to share the same iteration order regardless, which is why this assertion is overly broad. + // Try running this test with `--show-output`. + assert!(chunks.len() >= 1); + + Ok(()) + } + + #[test] + #[allow(clippy::zero_sized_map_values)] + fn intmap_order_is_deterministic() { + let descriptors = [ + MyPoint::descriptor(), + MyColor::descriptor(), + MyLabel::descriptor(), + MyPoint64::descriptor(), + MyIndex::descriptor(), + ]; + + let expected: IntMap = + descriptors.iter().cloned().map(|d| (d, ())).collect(); + let expected: Vec<_> = expected.into_keys().collect(); + + for _ in 0..1_000 { + let got_collect: IntMap = + descriptors.clone().into_iter().map(|d| (d, ())).collect(); + let got_collect: Vec<_> = got_collect.into_keys().collect(); + + let mut got_insert: IntMap = Default::default(); + for d in descriptors.clone() { + got_insert.insert(d, ()); + } + let got_insert: Vec<_> = got_insert.into_keys().collect(); + + assert_eq!(expected, got_collect); + assert_eq!(expected, got_insert); + } + } + /// A bunch of rows that don't fit any of the split conditions should end up together. #[test] fn simple_static() -> anyhow::Result<()> { From 42e47cd53c16989755c7cc1b272b83d73ab5776d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ktu=C4=9F=20Karaka=C5=9Fl=C4=B1?= <20567087+goktug97@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:24:38 +0100 Subject: [PATCH 24/43] Fix formatting in Python SDK LineStrip2D/3D (#8845) Error message in Python SDK LineStrip2D/3D is missing f-string --- rerun_py/rerun_sdk/rerun/components/geo_line_string_ext.py | 2 +- rerun_py/rerun_sdk/rerun/components/line_strip2d_ext.py | 2 +- rerun_py/rerun_sdk/rerun/components/line_strip3d_ext.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rerun_py/rerun_sdk/rerun/components/geo_line_string_ext.py b/rerun_py/rerun_sdk/rerun/components/geo_line_string_ext.py index dba3cb0507bfa..3bacb98e467fb 100644 --- a/rerun_py/rerun_sdk/rerun/components/geo_line_string_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/geo_line_string_ext.py @@ -74,7 +74,7 @@ def to_dvec2D_batch(strip: Any) -> DVec2DBatch: else: if isinstance(strip, np.ndarray) and (strip.ndim != 2 or strip.shape[1] != 2): raise ValueError( - "Expected a sequence of 2D vectors, instead got array with shape {strip.shape}." + f"Expected a sequence of 2D vectors, instead got array with shape {strip.shape}." ) return DVec2DBatch(strip) diff --git a/rerun_py/rerun_sdk/rerun/components/line_strip2d_ext.py b/rerun_py/rerun_sdk/rerun/components/line_strip2d_ext.py index a56812676cd5a..e0791fa8c0bf3 100644 --- a/rerun_py/rerun_sdk/rerun/components/line_strip2d_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/line_strip2d_ext.py @@ -67,7 +67,7 @@ def to_vec2d_batch(strip: Any) -> Vec2DBatch: else: if isinstance(strip, np.ndarray) and (strip.ndim != 2 or strip.shape[1] != 2): raise ValueError( - "Expected a sequence of 2D vectors, instead got array with shape {strip.shape}." + f"Expected a sequence of 2D vectors, instead got array with shape {strip.shape}." ) return Vec2DBatch(strip) diff --git a/rerun_py/rerun_sdk/rerun/components/line_strip3d_ext.py b/rerun_py/rerun_sdk/rerun/components/line_strip3d_ext.py index e8a9101a86f48..dd38cc3d5e9b7 100644 --- a/rerun_py/rerun_sdk/rerun/components/line_strip3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/line_strip3d_ext.py @@ -67,7 +67,7 @@ def to_vec3d_batch(strip: Any) -> Vec3DBatch: else: if isinstance(strip, np.ndarray) and (strip.ndim != 2 or strip.shape[1] != 3): raise ValueError( - "Expected a sequence of 3D vectors, instead got array with shape {strip.shape}." + f"Expected a sequence of 3D vectors, instead got array with shape {strip.shape}." ) return Vec3DBatch(strip) From 0e133408ac2808a956a635eaf0d43db441f3a7d6 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 29 Jan 2025 12:12:48 +0100 Subject: [PATCH 25/43] Zero-length indicators on all codepaths in C++ (#8842) Co-authored-by: Andreas Reich --- .../re_types_builder/src/codegen/cpp/mod.rs | 3 +- .../descriptors/descr_custom_archetype.cpp | 3 +- docs/snippets/all/tutorials/custom_data.cpp | 3 +- .../rerun/archetypes/annotation_context.cpp | 3 +- rerun_cpp/src/rerun/archetypes/arrows2d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/arrows3d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/asset3d.cpp | 3 +- .../src/rerun/archetypes/asset_video.cpp | 3 +- .../src/rerun/archetypes/asset_video_ext.cpp | 3 ++ rerun_cpp/src/rerun/archetypes/bar_chart.cpp | 3 +- rerun_cpp/src/rerun/archetypes/boxes2d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/boxes3d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/capsules3d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/clear.cpp | 3 +- .../src/rerun/archetypes/depth_image.cpp | 3 +- .../src/rerun/archetypes/ellipsoids3d.cpp | 3 +- .../src/rerun/archetypes/encoded_image.cpp | 3 +- .../src/rerun/archetypes/geo_line_strings.cpp | 3 +- rerun_cpp/src/rerun/archetypes/geo_points.cpp | 3 +- .../src/rerun/archetypes/graph_edges.cpp | 3 +- .../src/rerun/archetypes/graph_nodes.cpp | 3 +- rerun_cpp/src/rerun/archetypes/image.cpp | 3 +- .../src/rerun/archetypes/instance_poses3d.cpp | 3 +- .../src/rerun/archetypes/line_strips2d.cpp | 3 +- .../src/rerun/archetypes/line_strips3d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/mesh3d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/pinhole.cpp | 3 +- rerun_cpp/src/rerun/archetypes/points2d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/points3d.cpp | 3 +- rerun_cpp/src/rerun/archetypes/scalar.cpp | 3 +- .../rerun/archetypes/segmentation_image.cpp | 3 +- .../src/rerun/archetypes/series_line.cpp | 3 +- .../src/rerun/archetypes/series_point.cpp | 3 +- rerun_cpp/src/rerun/archetypes/tensor.cpp | 3 +- .../src/rerun/archetypes/text_document.cpp | 3 +- rerun_cpp/src/rerun/archetypes/text_log.cpp | 3 +- .../src/rerun/archetypes/transform3d.cpp | 3 +- .../archetypes/video_frame_reference.cpp | 3 +- .../src/rerun/archetypes/view_coordinates.cpp | 3 +- .../rerun/blueprint/archetypes/background.cpp | 3 +- .../archetypes/container_blueprint.cpp | 3 +- .../blueprint/archetypes/dataframe_query.cpp | 3 +- .../blueprint/archetypes/force_center.cpp | 3 +- .../archetypes/force_collision_radius.cpp | 3 +- .../rerun/blueprint/archetypes/force_link.cpp | 3 +- .../blueprint/archetypes/force_many_body.cpp | 3 +- .../blueprint/archetypes/force_position.cpp | 3 +- .../blueprint/archetypes/line_grid3d.cpp | 3 +- .../blueprint/archetypes/map_background.cpp | 3 +- .../rerun/blueprint/archetypes/map_zoom.cpp | 3 +- .../blueprint/archetypes/near_clip_plane.cpp | 3 +- .../blueprint/archetypes/panel_blueprint.cpp | 3 +- .../blueprint/archetypes/plot_legend.cpp | 3 +- .../blueprint/archetypes/scalar_axis.cpp | 3 +- .../archetypes/tensor_scalar_mapping.cpp | 3 +- .../archetypes/tensor_slice_selection.cpp | 3 +- .../blueprint/archetypes/tensor_view_fit.cpp | 3 +- .../blueprint/archetypes/view_blueprint.cpp | 3 +- .../blueprint/archetypes/view_contents.cpp | 3 +- .../archetypes/viewport_blueprint.cpp | 3 +- .../archetypes/visible_time_ranges.cpp | 3 +- .../blueprint/archetypes/visual_bounds2d.cpp | 3 +- rerun_cpp/src/rerun/component_batch.hpp | 15 ++++---- rerun_cpp/src/rerun/component_column.hpp | 36 +++++++++++++++++-- .../generated/archetypes/affix_fuzzer1.cpp | 3 +- .../generated/archetypes/affix_fuzzer2.cpp | 3 +- .../generated/archetypes/affix_fuzzer3.cpp | 3 +- .../generated/archetypes/affix_fuzzer4.cpp | 3 +- 68 files changed, 111 insertions(+), 138 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/cpp/mod.rs b/crates/build/re_types_builder/src/codegen/cpp/mod.rs index bcbac763b69bb..2538ee6eb5bdf 100644 --- a/crates/build/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/build/re_types_builder/src/codegen/cpp/mod.rs @@ -1831,8 +1831,7 @@ fn archetype_serialize(type_ident: &Ident, obj: &Object, hpp_includes: &mut Incl #NEWLINE_TOKEN #(#push_batches)* { - auto indicator = #type_ident::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator<#type_ident>(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.cpp b/docs/snippets/all/descriptors/descr_custom_archetype.cpp index 80a4955feaf49..60bd6ad10f8a2 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.cpp +++ b/docs/snippets/all/descriptors/descr_custom_archetype.cpp @@ -38,8 +38,7 @@ struct rerun::AsComponents { static Result> serialize(const CustomPoints3D& archetype) { std::vector batches; - CustomPoints3D::IndicatorComponent indicator; - batches.push_back(ComponentBatch::from_loggable(indicator).value_or_throw()); + batches.push_back(ComponentBatch::from_indicator().value_or_throw()); auto positions_descr = rerun::Loggable::Descriptor .or_with_archetype_name("user.CustomPoints3D") diff --git a/docs/snippets/all/tutorials/custom_data.cpp b/docs/snippets/all/tutorials/custom_data.cpp index 14c1698801c26..f984496cc4238 100644 --- a/docs/snippets/all/tutorials/custom_data.cpp +++ b/docs/snippets/all/tutorials/custom_data.cpp @@ -44,8 +44,7 @@ struct rerun::AsComponents { auto batches = AsComponents::serialize(archetype.points).value_or_throw(); // Add a custom indicator component. - CustomPoints3D::IndicatorComponent indicator; - batches.push_back(ComponentBatch::from_loggable(indicator).value_or_throw()); + batches.push_back(ComponentBatch::from_indicator().value_or_throw()); // Add custom confidence components if present. if (archetype.confidences) { diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.cpp b/rerun_cpp/src/rerun/archetypes/annotation_context.cpp index 1d6ac80242874..872a2bd719555 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.cpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.cpp @@ -50,8 +50,7 @@ namespace rerun { cells.push_back(archetype.context.value()); } { - auto indicator = AnnotationContext::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.cpp b/rerun_cpp/src/rerun/archetypes/arrows2d.cpp index c38ea2e8f1eca..783efe80f6628 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.cpp @@ -142,8 +142,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Arrows2D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.cpp b/rerun_cpp/src/rerun/archetypes/arrows3d.cpp index 600136ee75dbe..87cc3df3f319d 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.cpp @@ -129,8 +129,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Arrows3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.cpp b/rerun_cpp/src/rerun/archetypes/asset3d.cpp index 490da9ffb365d..bf61fe7b9c961 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.cpp @@ -77,8 +77,7 @@ namespace rerun { cells.push_back(archetype.albedo_factor.value()); } { - auto indicator = Asset3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.cpp b/rerun_cpp/src/rerun/archetypes/asset_video.cpp index 8f1f635099e5a..e200acfe922db 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.cpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.cpp @@ -62,8 +62,7 @@ namespace rerun { cells.push_back(archetype.media_type.value()); } { - auto indicator = AssetVideo::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/asset_video_ext.cpp b/rerun_cpp/src/rerun/archetypes/asset_video_ext.cpp index 1bb8c643fde31..7a3a406345788 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video_ext.cpp @@ -87,6 +87,9 @@ namespace rerun::archetypes { return std::vector(); } auto blob_list_array = std::dynamic_pointer_cast(blob.value().array); + if (!blob_list_array) { + return Error(ErrorCode::InvalidArchetypeField, "Blob array is not a primitive array"); + } auto blob_array = std::dynamic_pointer_cast(blob_list_array->values()); if (!blob_array) { diff --git a/rerun_cpp/src/rerun/archetypes/bar_chart.cpp b/rerun_cpp/src/rerun/archetypes/bar_chart.cpp index d3a4df04c78e8..4ae0082d7ea29 100644 --- a/rerun_cpp/src/rerun/archetypes/bar_chart.cpp +++ b/rerun_cpp/src/rerun/archetypes/bar_chart.cpp @@ -62,8 +62,7 @@ namespace rerun { cells.push_back(archetype.color.value()); } { - auto indicator = BarChart::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.cpp b/rerun_cpp/src/rerun/archetypes/boxes2d.cpp index 5e1c9789d0753..c3d8b72fe4191 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.cpp @@ -142,8 +142,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Boxes2D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.cpp b/rerun_cpp/src/rerun/archetypes/boxes3d.cpp index 77d527268152f..ab94890b3acfe 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.cpp @@ -175,8 +175,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Boxes3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/capsules3d.cpp b/rerun_cpp/src/rerun/archetypes/capsules3d.cpp index dfd56f22f0406..96275ec3b7acf 100644 --- a/rerun_cpp/src/rerun/archetypes/capsules3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/capsules3d.cpp @@ -163,8 +163,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Capsules3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/clear.cpp b/rerun_cpp/src/rerun/archetypes/clear.cpp index 76748ed833ecb..cd4a884eeae1a 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.cpp +++ b/rerun_cpp/src/rerun/archetypes/clear.cpp @@ -51,8 +51,7 @@ namespace rerun { cells.push_back(archetype.is_recursive.value()); } { - auto indicator = Clear::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/depth_image.cpp b/rerun_cpp/src/rerun/archetypes/depth_image.cpp index 1819b3941737c..35d0b48b9bf05 100644 --- a/rerun_cpp/src/rerun/archetypes/depth_image.cpp +++ b/rerun_cpp/src/rerun/archetypes/depth_image.cpp @@ -130,8 +130,7 @@ namespace rerun { cells.push_back(archetype.draw_order.value()); } { - auto indicator = DepthImage::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp index 995881f410976..ddf9ea5df1b27 100644 --- a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.cpp @@ -175,8 +175,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Ellipsoids3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/encoded_image.cpp b/rerun_cpp/src/rerun/archetypes/encoded_image.cpp index ee294035a5c71..e772f25b5d8bd 100644 --- a/rerun_cpp/src/rerun/archetypes/encoded_image.cpp +++ b/rerun_cpp/src/rerun/archetypes/encoded_image.cpp @@ -88,8 +88,7 @@ namespace rerun { cells.push_back(archetype.draw_order.value()); } { - auto indicator = EncodedImage::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp b/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp index dcb2cfc34a610..5d981d0c09e41 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp +++ b/rerun_cpp/src/rerun/archetypes/geo_line_strings.cpp @@ -77,8 +77,7 @@ namespace rerun { cells.push_back(archetype.colors.value()); } { - auto indicator = GeoLineStrings::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/geo_points.cpp b/rerun_cpp/src/rerun/archetypes/geo_points.cpp index e12e2a6bef587..7eaf1d7825202 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_points.cpp +++ b/rerun_cpp/src/rerun/archetypes/geo_points.cpp @@ -87,8 +87,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = GeoPoints::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/graph_edges.cpp b/rerun_cpp/src/rerun/archetypes/graph_edges.cpp index 81085ab365ebf..74d5a4b94c9d8 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_edges.cpp +++ b/rerun_cpp/src/rerun/archetypes/graph_edges.cpp @@ -62,8 +62,7 @@ namespace rerun { cells.push_back(archetype.graph_type.value()); } { - auto indicator = GraphEdges::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp b/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp index b8da1b853aae4..40d1e3fd96828 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp +++ b/rerun_cpp/src/rerun/archetypes/graph_nodes.cpp @@ -116,8 +116,7 @@ namespace rerun { cells.push_back(archetype.radii.value()); } { - auto indicator = GraphNodes::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/image.cpp b/rerun_cpp/src/rerun/archetypes/image.cpp index b4a959e592cd4..91c2d55746d77 100644 --- a/rerun_cpp/src/rerun/archetypes/image.cpp +++ b/rerun_cpp/src/rerun/archetypes/image.cpp @@ -88,8 +88,7 @@ namespace rerun { cells.push_back(archetype.draw_order.value()); } { - auto indicator = Image::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp b/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp index 49342877e5c5d..74181deab9718 100644 --- a/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/instance_poses3d.cpp @@ -110,8 +110,7 @@ namespace rerun { cells.push_back(archetype.mat3x3.value()); } { - auto indicator = InstancePoses3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp index 28683ce8edbd2..ec12c5c102ec7 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.cpp @@ -129,8 +129,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = LineStrips2D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp b/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp index c029f7b8d83c2..74872d884756b 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips3d.cpp @@ -116,8 +116,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = LineStrips3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/mesh3d.cpp b/rerun_cpp/src/rerun/archetypes/mesh3d.cpp index ef535ed5e41fe..5f55970b29fd8 100644 --- a/rerun_cpp/src/rerun/archetypes/mesh3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/mesh3d.cpp @@ -169,8 +169,7 @@ namespace rerun { cells.push_back(archetype.class_ids.value()); } { - auto indicator = Mesh3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.cpp b/rerun_cpp/src/rerun/archetypes/pinhole.cpp index 926abbeb79926..f7ff4cd739e14 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.cpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.cpp @@ -95,8 +95,7 @@ namespace rerun { cells.push_back(archetype.image_plane_distance.value()); } { - auto indicator = Pinhole::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/points2d.cpp b/rerun_cpp/src/rerun/archetypes/points2d.cpp index ba33eb2f6bd98..a81fcb66c8458 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.cpp @@ -144,8 +144,7 @@ namespace rerun { cells.push_back(archetype.keypoint_ids.value()); } { - auto indicator = Points2D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/points3d.cpp b/rerun_cpp/src/rerun/archetypes/points3d.cpp index ee364cc892b05..f43338fdf0263 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.cpp @@ -131,8 +131,7 @@ namespace rerun { cells.push_back(archetype.keypoint_ids.value()); } { - auto indicator = Points3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/scalar.cpp b/rerun_cpp/src/rerun/archetypes/scalar.cpp index 773a19075edce..fc88862fde07b 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.cpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.cpp @@ -49,8 +49,7 @@ namespace rerun { cells.push_back(archetype.scalar.value()); } { - auto indicator = Scalar::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp index 43d2c9fdf7290..5650a2e4ef098 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.cpp @@ -88,8 +88,7 @@ namespace rerun { cells.push_back(archetype.draw_order.value()); } { - auto indicator = SegmentationImage::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/series_line.cpp b/rerun_cpp/src/rerun/archetypes/series_line.cpp index c654d2df42a3b..75f5b9e23172e 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.cpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.cpp @@ -91,8 +91,7 @@ namespace rerun { cells.push_back(archetype.aggregation_policy.value()); } { - auto indicator = SeriesLine::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/series_point.cpp b/rerun_cpp/src/rerun/archetypes/series_point.cpp index b9f9283863b83..cf097faf120c1 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.cpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.cpp @@ -90,8 +90,7 @@ namespace rerun { cells.push_back(archetype.marker_size.value()); } { - auto indicator = SeriesPoint::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/tensor.cpp b/rerun_cpp/src/rerun/archetypes/tensor.cpp index 205f9a3b5c950..aa37878df5b4b 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.cpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.cpp @@ -64,8 +64,7 @@ namespace rerun { cells.push_back(archetype.value_range.value()); } { - auto indicator = Tensor::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/text_document.cpp b/rerun_cpp/src/rerun/archetypes/text_document.cpp index 325eb45a592ab..d58d720b30a59 100644 --- a/rerun_cpp/src/rerun/archetypes/text_document.cpp +++ b/rerun_cpp/src/rerun/archetypes/text_document.cpp @@ -62,8 +62,7 @@ namespace rerun { cells.push_back(archetype.media_type.value()); } { - auto indicator = TextDocument::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/text_log.cpp b/rerun_cpp/src/rerun/archetypes/text_log.cpp index 13e857555c556..e9f0693961fde 100644 --- a/rerun_cpp/src/rerun/archetypes/text_log.cpp +++ b/rerun_cpp/src/rerun/archetypes/text_log.cpp @@ -75,8 +75,7 @@ namespace rerun { cells.push_back(archetype.color.value()); } { - auto indicator = TextLog::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.cpp b/rerun_cpp/src/rerun/archetypes/transform3d.cpp index 67341326e4428..f6a89867d3b54 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.cpp @@ -135,8 +135,7 @@ namespace rerun { cells.push_back(archetype.axis_length.value()); } { - auto indicator = Transform3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp index 23d0b90b174a2..ab2c713246a99 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.cpp @@ -64,8 +64,7 @@ namespace rerun { cells.push_back(archetype.video_reference.value()); } { - auto indicator = VideoFrameReference::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp index 2e50be5812a22..09ca6e9c817a6 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.cpp @@ -49,8 +49,7 @@ namespace rerun { cells.push_back(archetype.xyz.value()); } { - auto indicator = ViewCoordinates::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp index 36f96072f8de4..3b49dab965daa 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp @@ -63,8 +63,7 @@ namespace rerun { cells.push_back(archetype.color.value()); } { - auto indicator = Background::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp index 9a6e01623e949..f520d341354fd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp @@ -152,8 +152,7 @@ namespace rerun { cells.push_back(archetype.grid_columns.value()); } { - auto indicator = ContainerBlueprint::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp index 56239fc2fb1a0..2c201fcd6e6b5 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp @@ -115,8 +115,7 @@ namespace rerun { cells.push_back(archetype.select.value()); } { - auto indicator = DataframeQuery::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp index efaa25a2fe777..4aba6daa24475 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp @@ -63,8 +63,7 @@ namespace rerun { cells.push_back(archetype.strength.value()); } { - auto indicator = ForceCenter::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp index 2c6b8cb5fabd0..5de4e3f29e77a 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp @@ -79,8 +79,7 @@ namespace rerun { cells.push_back(archetype.iterations.value()); } { - auto indicator = ForceCollisionRadius::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp index 5c8d9d753da1f..c28dcc726c1b8 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp @@ -77,8 +77,7 @@ namespace rerun { cells.push_back(archetype.iterations.value()); } { - auto indicator = ForceLink::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp index 40cdbf629973d..9c6f4bfa30ef3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp @@ -64,8 +64,7 @@ namespace rerun { cells.push_back(archetype.strength.value()); } { - auto indicator = ForceManyBody::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp index 61d23a2af26c6..d050fca0fd792 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp @@ -77,8 +77,7 @@ namespace rerun { cells.push_back(archetype.position.value()); } { - auto indicator = ForcePosition::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp index d63c0ee6f8f8e..3af6350b8c6bb 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp @@ -105,8 +105,7 @@ namespace rerun { cells.push_back(archetype.color.value()); } { - auto indicator = LineGrid3D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp index 395631961c44e..c35c98281f10b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp @@ -50,8 +50,7 @@ namespace rerun { cells.push_back(archetype.provider.value()); } { - auto indicator = MapBackground::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp index 22c6e86f12890..7df3ee712df5b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp @@ -50,8 +50,7 @@ namespace rerun { cells.push_back(archetype.zoom.value()); } { - auto indicator = MapZoom::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp index 9655cf7e8fa64..d97805a446ca3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp @@ -54,8 +54,7 @@ namespace rerun { cells.push_back(archetype.near_clip_plane.value()); } { - auto indicator = NearClipPlane::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp index 9119e5485a2df..1b530d2620fd1 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp @@ -51,8 +51,7 @@ namespace rerun { cells.push_back(archetype.state.value()); } { - auto indicator = PanelBlueprint::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp index e86c994d4a775..5d530d2aecdec 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp @@ -64,8 +64,7 @@ namespace rerun { cells.push_back(archetype.visible.value()); } { - auto indicator = PlotLegend::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp index fc089a96d4ff8..5443a994ce6e8 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp @@ -64,8 +64,7 @@ namespace rerun { cells.push_back(archetype.zoom_lock.value()); } { - auto indicator = ScalarAxis::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp index 24d8c553a8658..947f952459b54 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp @@ -76,8 +76,7 @@ namespace rerun { cells.push_back(archetype.gamma.value()); } { - auto indicator = TensorScalarMapping::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp index b89e169e738fd..1f14ea599bd6e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp @@ -97,8 +97,7 @@ namespace rerun { cells.push_back(archetype.slider.value()); } { - auto indicator = TensorSliceSelection::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp index 6669ddd484c67..bf45a7d3058a8 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp @@ -51,8 +51,7 @@ namespace rerun { cells.push_back(archetype.scaling.value()); } { - auto indicator = TensorViewFit::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp index 2ece106212f1d..bf2e963c737a5 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp @@ -97,8 +97,7 @@ namespace rerun { cells.push_back(archetype.visible.value()); } { - auto indicator = ViewBlueprint::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp index 2140e17f60c15..d8bcb69fea685 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp @@ -51,8 +51,7 @@ namespace rerun { cells.push_back(archetype.query.value()); } { - auto indicator = ViewContents::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp index adf36c90d1cd2..430a3b13a3fa3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp @@ -113,8 +113,7 @@ namespace rerun { cells.push_back(archetype.past_viewer_recommendations.value()); } { - auto indicator = ViewportBlueprint::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp index 3e04ff3f10e94..e94d4f2dd74dd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp @@ -51,8 +51,7 @@ namespace rerun { cells.push_back(archetype.ranges.value()); } { - auto indicator = VisibleTimeRanges::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp index cb45b44159293..f5f8dcd9a05a7 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp @@ -51,8 +51,7 @@ namespace rerun { cells.push_back(archetype.range.value()); } { - auto indicator = VisualBounds2D::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/component_batch.hpp b/rerun_cpp/src/rerun/component_batch.hpp index 9047a405a18d9..6d95a5f159718 100644 --- a/rerun_cpp/src/rerun/component_batch.hpp +++ b/rerun_cpp/src/rerun/component_batch.hpp @@ -29,12 +29,6 @@ namespace rerun { ComponentTypeHandle component_type; public: - ComponentBatch() = default; - ComponentBatch(ComponentBatch&& other) = default; - ComponentBatch(const ComponentBatch& other) = default; - ComponentBatch& operator=(ComponentBatch&& other) = default; - ComponentBatch& operator=(const ComponentBatch& other) = default; - /// Creates a new empty component batch with a given descriptor. template static Result empty(const ComponentDescriptor& descriptor) { @@ -180,6 +174,15 @@ namespace rerun { } } + /// Creates a new component batch for an archetype indicator. + template + static Result from_indicator() { + return ComponentBatch::from_loggable( + typename Archetype::IndicatorComponent(), + Loggable::Descriptor + ); + } + /// Size in the number of elements the underlying arrow array contains. size_t length() const; diff --git a/rerun_cpp/src/rerun/component_column.hpp b/rerun_cpp/src/rerun/component_column.hpp index 1eea20dbfb708..20852f1910f0c 100644 --- a/rerun_cpp/src/rerun/component_column.hpp +++ b/rerun_cpp/src/rerun/component_column.hpp @@ -25,6 +25,24 @@ namespace rerun { ComponentTypeHandle component_type; public: + /// Creates a new component column from a collection of component instances. + /// + /// Automatically registers the component type the first time this type is encountered. + /// + /// \param components Continuous collection of components which is about to be partitioned. + /// \param lengths The number of components in each run. for `rerun::RecordingStream::send_columns`, + /// this specifies the number of components at each time point. + /// The sum of the lengths must be equal to the number of components in the batch. + template + [[deprecated( + "Use from_loggable_with_lengths(components, lengths, descriptor) (with explicit descriptor) instead" + )]] static Result + from_loggable_with_lengths( + const Collection& components, const Collection& lengths + ) { + return from_loggable_with_lengths(components, lengths, Loggable::Descriptor); + } + /// Creates a new component column from a collection of component instances. /// /// Automatically registers the component type the first time this type is encountered. @@ -46,6 +64,21 @@ namespace rerun { return from_batch_with_lengths(component_batch_result.value, lengths); } + /// Creates a new component column from a collection of component instances where each run has a length of one. + /// + /// When used with `rerun::RecordingStream::send_columns`, this is equivalent to `from_loggable(components, std::vector{1, 1, ...})`. + /// I.e. there's a single component for each time point. + /// + /// Automatically registers the component type the first time this type is encountered. + /// + /// \param components Continuous collection of components which is about to be partitioned into runs of length one. + template + [[deprecated("Use from_loggable(components, descriptor) (with explicit descriptor) instead" + )]] static Result + from_loggable(const Collection& components) { + return from_loggable(components, Loggable::Descriptor); + } + /// Creates a new component column from a collection of component instances where each run has a length of one. /// /// When used with `rerun::RecordingStream::send_columns`, this is equivalent to `from_loggable(components, std::vector{1, 1, ...})`. @@ -70,8 +103,7 @@ namespace rerun { /// Creates a new component column with a given number of archetype indicators for a given archetype type. template static Result from_indicators(uint32_t num_indicators) { - auto component_batch_result = - ComponentBatch::from_loggable(typename Archetype::IndicatorComponent()); + auto component_batch_result = ComponentBatch::from_indicator(); if (component_batch_result.is_err()) { return component_batch_result.error; } diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp index e25054b48b634..1a022ae12209b 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.cpp @@ -322,8 +322,7 @@ namespace rerun { cells.push_back(archetype.fuzz1022.value()); } { - auto indicator = AffixFuzzer1::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp index 5fd61a0841f06..831b332f8c5c9 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.cpp @@ -283,8 +283,7 @@ namespace rerun { cells.push_back(archetype.fuzz1122.value()); } { - auto indicator = AffixFuzzer2::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp index cf1efc4462659..5c10aeb6d9ba5 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.cpp @@ -270,8 +270,7 @@ namespace rerun { cells.push_back(archetype.fuzz2018.value()); } { - auto indicator = AffixFuzzer3::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp index 16093b3189cb5..b6df49bb87fca 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.cpp @@ -270,8 +270,7 @@ namespace rerun { cells.push_back(archetype.fuzz2118.value()); } { - auto indicator = AffixFuzzer4::IndicatorComponent(); - auto result = ComponentBatch::from_loggable(indicator); + auto result = ComponentBatch::from_indicator(); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); } From 9ff9e7f10fcc446d99763cd1be1c3e039ff00439 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 29 Jan 2025 12:17:44 +0100 Subject: [PATCH 26/43] Order-agnostic `rrd compare` command + snippet clean up (#8843) See: ```rust /// If specified, the comparison will focus purely on semantics, ignoring order. /// /// The Rerun data model is itself unordered, and because many of the internal pipelines are /// asynchronous by nature, it is very easy to end up with semantically identical, but /// differently ordered data. /// In most cases, the distinction is irrelevant, and you'd rather the comparison succeeds. #[clap(long, default_value_t = false)] unordered: bool, ``` --- crates/top/rerun/src/commands/rrd/compare.rs | 53 +++++++++++++++---- .../all/archetypes/image_send_columns.cpp | 2 +- .../all/archetypes/image_send_columns.py | 4 +- .../all/archetypes/image_send_columns.rs | 10 +--- .../all/archetypes/mesh3d_partial_updates.cpp | 5 +- docs/snippets/snippets.toml | 40 ++------------ scripts/roundtrip_utils.py | 2 +- 7 files changed, 57 insertions(+), 59 deletions(-) diff --git a/crates/top/rerun/src/commands/rrd/compare.rs b/crates/top/rerun/src/commands/rrd/compare.rs index 3faa45e09b2fa..df5cf55f479fa 100644 --- a/crates/top/rerun/src/commands/rrd/compare.rs +++ b/crates/top/rerun/src/commands/rrd/compare.rs @@ -6,6 +6,8 @@ use std::{ use anyhow::Context as _; use itertools::{izip, Itertools}; +use re_chunk::Chunk; + // --- #[derive(Debug, Clone, clap::Parser)] @@ -13,6 +15,15 @@ pub struct CompareCommand { path_to_rrd1: String, path_to_rrd2: String, + /// If specified, the comparison will focus purely on semantics, ignoring order. + /// + /// The Rerun data model is itself unordered, and because many of the internal pipelines are + /// asynchronous by nature, it is very easy to end up with semantically identical, but + /// differently ordered data. + /// In most cases, the distinction is irrelevant, and you'd rather the comparison succeeds. + #[clap(long, default_value_t = false)] + unordered: bool, + /// If specified, dumps both .rrd files as tables. #[clap(long, default_value_t = false)] full_dump: bool, @@ -27,6 +38,7 @@ impl CompareCommand { let Self { path_to_rrd1, path_to_rrd2, + unordered, full_dump, } = self; @@ -64,17 +76,36 @@ impl CompareCommand { re_format::format_uint(chunks2.len()), ); - for (chunk1, chunk2) in izip!(chunks1, chunks2) { - anyhow::ensure!( - re_chunk::Chunk::are_similar(&chunk1, &chunk2), - "Chunks do not match:\n{}", - similar_asserts::SimpleDiff::from_str( - &format!("{chunk1}"), - &format!("{chunk2}"), - "got", - "expected", - ), - ); + let mut unordered_failed = false; + if *unordered { + let mut chunks2_opt: Vec>> = + chunks2.clone().into_iter().map(Some).collect_vec(); + 'outer: for chunk1 in &chunks1 { + for chunk2 in chunks2_opt.iter_mut().filter(|c| c.is_some()) { + #[allow(clippy::unwrap_used)] + if re_chunk::Chunk::are_similar(chunk1, chunk2.as_ref().unwrap()) { + *chunk2 = None; + continue 'outer; + } + } + unordered_failed = true; + break; + } + } + + if !*unordered || unordered_failed { + for (chunk1, chunk2) in izip!(chunks1, chunks2) { + anyhow::ensure!( + re_chunk::Chunk::are_similar(&chunk1, &chunk2), + "Chunks do not match:\n{}", + similar_asserts::SimpleDiff::from_str( + &format!("{chunk1}"), + &format!("{chunk2}"), + "got", + "expected", + ), + ); + } } re_log::debug!("{path_to_rrd1:?} and {path_to_rrd2:?} are similar enough."); diff --git a/docs/snippets/all/archetypes/image_send_columns.cpp b/docs/snippets/all/archetypes/image_send_columns.cpp index f179bdfefc9b5..d7c6d40fde1b1 100644 --- a/docs/snippets/all/archetypes/image_send_columns.cpp +++ b/docs/snippets/all/archetypes/image_send_columns.cpp @@ -32,7 +32,7 @@ int main() { rerun::ColorModel::RGB, rerun::ChannelDatatype::U8 ); - rec.log_static("images", rerun::borrow(&format), rerun::Image::IndicatorComponent()); + rec.log_static("images", rerun::Image::update_fields().with_format(format)); // Split up the image data into several components referencing the underlying data. const size_t image_size_in_bytes = width * height * 3; diff --git a/docs/snippets/all/archetypes/image_send_columns.py b/docs/snippets/all/archetypes/image_send_columns.py index 3359fe5d7d726..c735eafb780c1 100644 --- a/docs/snippets/all/archetypes/image_send_columns.py +++ b/docs/snippets/all/archetypes/image_send_columns.py @@ -16,8 +16,8 @@ images[t, 50:150, (t * 10) : (t * 10 + 100), 1] = 255 # Log the ImageFormat and indicator once, as static. -format_static = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8") -rr.send_columns("images", indexes=[], columns=rr.Image.columns(format=format_static)) +format = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8") +rr.log("images", rr.Image.from_fields(format=format), static=True) # Send all images at once. rr.send_columns( diff --git a/docs/snippets/all/archetypes/image_send_columns.rs b/docs/snippets/all/archetypes/image_send_columns.rs index a157ced265629..cb4983e272b17 100644 --- a/docs/snippets/all/archetypes/image_send_columns.rs +++ b/docs/snippets/all/archetypes/image_send_columns.rs @@ -20,15 +20,9 @@ fn main() -> Result<(), Box> { .fill(255); } - // Send the ImageFormat and indicator once, as static. + // Log the ImageFormat and indicator once, as static. let format = rerun::components::ImageFormat::rgb8([width as _, height as _]); - rec.send_columns( - "images", - [], - rerun::Image::update_fields() - .with_format(format) - .columns_of_unit_batches()?, - )?; + rec.log_static("images", &rerun::Image::update_fields().with_format(format))?; // Split up the image data into several components referencing the underlying data. let image_size_in_bytes = width * height * 3; diff --git a/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp b/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp index c23404909fbc8..9ca7143fc2c58 100644 --- a/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp +++ b/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp @@ -43,6 +43,9 @@ int main() { mul_pos(factor, vertex_positions[1]), mul_pos(factor, vertex_positions[2]), }; - rec.log("triangle", modified_vertex_positions); + rec.log( + "triangle", + rerun::Mesh3D::update_fields().with_vertex_positions(modified_vertex_positions) + ); } } diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 83fa22a045d4a..28fff444a310c 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -198,15 +198,8 @@ quick_start = [ # These examples don't have exactly the same implementation. "py", "rust", ] -"archetypes/arrows3d_simple" = [ # TODO(#3206): examples use different RNGs - "cpp", +"archetypes/arrows3d_simple" = [ # Python uses doubles "py", - "rust", -] -"archetypes/asset3d_out_of_tree" = [ # float issues since calculation is done slightly differently (also, Python uses doubles) - "cpp", - "py", - "rust", ] "archetypes/bar_chart" = [ # On Windows this logs f64 instead of u64 unless a numpy array with explicit type is used. "py", @@ -221,11 +214,9 @@ quick_start = [ # These examples don't have exactly the same implementation. "py", "rust", ] -"archetypes/mesh3d_partial_updates" = [ # TODO(andreas): use new partial update api - "cpp", +"archetypes/mesh3d_partial_updates" = [ # Python uses doubles "py", - "rust", -] # float precision issues +] "archetypes/pinhole_simple" = [ # TODO(#3206): examples use different RNGs "cpp", "py", @@ -249,17 +240,7 @@ quick_start = [ # These examples don't have exactly the same implementation. "py", "rust", ] -"archetypes/series_point_style" = [ # TODO(#5116): trigonometric functions have slightly different outcomes - "cpp", - "py", - "rust", -] -"archetypes/series_line_style" = [ # TODO(#5116):trigonometric functions have slightly different outcomes - "cpp", - "py", - "rust", -] -"archetypes/text_log_integration" = [ # The entity path will differ because the Rust code is part of a library +"archetypes/text_log_integration" = [ # The entity path will differ because the integrations work differently "cpp", "py", "rust", @@ -277,19 +258,8 @@ quick_start = [ # These examples don't have exactly the same implementation. "py", "rust", ] -"archetypes/image_send_columns" = [ # This mixes `log` and `send_columns`. Since `log` is suspect to delays by the batcher, this test gets flaky. - "cpp", - "rust", -] -"archetypes/mesh3d_instancing" = [ # TODO(#3235): Slight floating point differences in deg to rad conversion. - "cpp", - "py", - "rust", -] -"archetypes/video_auto_frames" = [ # This mixes `log` and `send_columns`. Since `log` is suspect to delays by the batcher, this test gets flaky. - "cpp", +"archetypes/mesh3d_instancing" = [ # Python uses doubles "py", - "rust", ] # `$config_dir` will be replaced with the absolute path of `docs/snippets`. diff --git a/scripts/roundtrip_utils.py b/scripts/roundtrip_utils.py index 85775b5a238f2..5dbbd47211d02 100644 --- a/scripts/roundtrip_utils.py +++ b/scripts/roundtrip_utils.py @@ -58,7 +58,7 @@ def roundtrip_env(*, save_path: str | None = None) -> dict[str, str]: def run_comparison(rrd0_path: str, rrd1_path: str, full_dump: bool) -> None: - cmd = ["rerun", "rrd", "compare"] + cmd = ["rerun", "rrd", "compare", "--unordered"] if full_dump: cmd += ["--full-dump"] cmd += [rrd0_path, rrd1_path] From a0aae042922b31adb75bc4583a20f56696717cd7 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 29 Jan 2025 12:22:27 +0100 Subject: [PATCH 27/43] Remove indicators from custom data examples (#8846) This is just confusing users for no value: A) they're deprecated and B) only the builtin indicators have any effect on the viewer anyhow. --- .../all/descriptors/descr_custom_archetype.cpp | 5 ----- .../all/descriptors/descr_custom_archetype.py | 2 +- .../all/descriptors/descr_custom_archetype.rs | 10 ---------- docs/snippets/all/tutorials/custom_data.cpp | 6 ------ docs/snippets/all/tutorials/custom_data.py | 1 - docs/snippets/all/tutorials/custom_data.rs | 15 ++++++--------- 6 files changed, 7 insertions(+), 32 deletions(-) diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.cpp b/docs/snippets/all/descriptors/descr_custom_archetype.cpp index 60bd6ad10f8a2..a9043b1da4eca 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.cpp +++ b/docs/snippets/all/descriptors/descr_custom_archetype.cpp @@ -26,9 +26,6 @@ struct rerun::Loggable { /// A custom archetype that extends Rerun's builtin `rerun::Points3D` archetype with a custom component. struct CustomPoints3D { - static constexpr const char IndicatorComponentName[] = "user.CustomPoints3DIndicator"; - using IndicatorComponent = rerun::components::IndicatorComponent; - rerun::Collection positions; std::optional> colors; }; @@ -38,8 +35,6 @@ struct rerun::AsComponents { static Result> serialize(const CustomPoints3D& archetype) { std::vector batches; - batches.push_back(ComponentBatch::from_indicator().value_or_throw()); - auto positions_descr = rerun::Loggable::Descriptor .or_with_archetype_name("user.CustomPoints3D") .or_with_archetype_field_name("custom_positions"); diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.py b/docs/snippets/all/descriptors/descr_custom_archetype.py index 324b48c58a0fe..45b9ff50f615a 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.py +++ b/docs/snippets/all/descriptors/descr_custom_archetype.py @@ -23,7 +23,7 @@ def __init__(self: Any, positions: npt.ArrayLike, colors: npt.ArrayLike) -> None ) def as_component_batches(self) -> Iterable[rr.ComponentBatchLike]: - return [rr.IndicatorComponentBatch("user.CustomPoints3D"), self.positions, self.colors] + return [self.positions, self.colors] rr.init("rerun_example_descriptors_custom_archetype") diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.rs b/docs/snippets/all/descriptors/descr_custom_archetype.rs index 6bde8415329c0..a4ecd1790b707 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.rs +++ b/docs/snippets/all/descriptors/descr_custom_archetype.rs @@ -6,10 +6,6 @@ struct CustomPoints3D { } impl CustomPoints3D { - fn indicator() -> rerun::NamedIndicatorComponent { - rerun::NamedIndicatorComponent("user.CustomPoints3DIndicator".into()) - } - fn overridden_position_descriptor() -> ComponentDescriptor { ComponentDescriptor { archetype_name: Some("user.CustomPoints3D".into()), @@ -28,7 +24,6 @@ impl CustomPoints3D { impl rerun::AsComponents for CustomPoints3D { fn as_serialized_batches(&self) -> Vec { [ - Self::indicator().serialized(), self.positions.serialized().map(|positions| { positions.with_descriptor_override(Self::overridden_position_descriptor()) }), @@ -105,11 +100,6 @@ fn check_tags(rec: &rerun::RecordingStream) { descriptors.sort(); let expected = vec![ - ComponentDescriptor { - archetype_name: None, - archetype_field_name: None, - component_name: "user.CustomPoints3DIndicator".into(), - }, ComponentDescriptor { archetype_name: Some("user.CustomPoints3D".into()), archetype_field_name: Some("colors".into()), diff --git a/docs/snippets/all/tutorials/custom_data.cpp b/docs/snippets/all/tutorials/custom_data.cpp index f984496cc4238..4f379244ac181 100644 --- a/docs/snippets/all/tutorials/custom_data.cpp +++ b/docs/snippets/all/tutorials/custom_data.cpp @@ -29,9 +29,6 @@ struct rerun::Loggable { /// A custom archetype that extends Rerun's builtin `rerun::Points3D` archetype with a custom component. struct CustomPoints3D { - static constexpr const char IndicatorComponentName[] = "user.CustomPoints3DIndicator"; - using IndicatorComponent = rerun::components::IndicatorComponent; - rerun::Points3D points; // Using a rerun::Collection is not strictly necessary, you could also use an std::vector for example, // but useful for avoiding allocations since `rerun::Collection` can borrow data from other containers. @@ -43,9 +40,6 @@ struct rerun::AsComponents { static Result> serialize(const CustomPoints3D& archetype) { auto batches = AsComponents::serialize(archetype.points).value_or_throw(); - // Add a custom indicator component. - batches.push_back(ComponentBatch::from_indicator().value_or_throw()); - // Add custom confidence components if present. if (archetype.confidences) { auto descriptor = rerun::Loggable::Descriptor diff --git a/docs/snippets/all/tutorials/custom_data.py b/docs/snippets/all/tutorials/custom_data.py index 422197690dd9b..661db34a83ba3 100755 --- a/docs/snippets/all/tutorials/custom_data.py +++ b/docs/snippets/all/tutorials/custom_data.py @@ -38,7 +38,6 @@ def __init__(self: Any, positions: npt.ArrayLike, confidences: npt.ArrayLike) -> def as_component_batches(self) -> Iterable[rr.ComponentBatchLike]: return ( list(self.points3d.as_component_batches()) # The components from Points3D - + [rr.IndicatorComponentBatch("user.CustomPoints3D")] # Our custom indicator + [self.confidences] # Custom confidence data ) diff --git a/docs/snippets/all/tutorials/custom_data.rs b/docs/snippets/all/tutorials/custom_data.rs index 2857159a2729f..9105b951e607b 100644 --- a/docs/snippets/all/tutorials/custom_data.rs +++ b/docs/snippets/all/tutorials/custom_data.rs @@ -19,22 +19,19 @@ struct CustomPoints3D { impl rerun::AsComponents for CustomPoints3D { fn as_serialized_batches(&self) -> Vec { - let indicator = rerun::NamedIndicatorComponent("user.CustomPoints3DIndicator".into()); self.points3d .as_serialized_batches() .into_iter() .chain( - [ - indicator.serialized(), - self.confidences - .as_ref() - .and_then(|batch| batch.serialized()) - .map(|batch| + [self + .confidences + .as_ref() + .and_then(|batch| batch.serialized()) + .map(|batch| // Optionally override the descriptor with extra information. batch .or_with_archetype_name(|| "user.CustomPoints3D".into()) - .or_with_archetype_field_name(|| "confidences".into())), - ] + .or_with_archetype_field_name(|| "confidences".into()))] .into_iter() .flatten(), ) From e0c706b01a52fa463f60b4175c4f3b730dbaa002 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 29 Jan 2025 12:59:32 +0100 Subject: [PATCH 28/43] Python: untagged-resistant APIs (#8849) It's pretty much just a matter of explicitly asking for `DescribedComponentBatch`es instead of `ComponentBatchLike`s in a couple of places. The end result is that legacy code still works, but yields type errors. * Fixes https://github.com/rerun-io/rerun/issues/8756 --- .../src/codegen/python/mod.rs | 5 ++--- crates/store/re_types_core/src/archetype.rs | 1 - docs/content/howto/logging/custom-data.md | 2 +- .../all/descriptors/descr_custom_archetype.py | 4 ++-- docs/snippets/all/tutorials/custom_data.py | 4 ++-- docs/snippets/snippets.toml | 1 - .../openstreetmap_data/openstreetmap_data.py | 2 +- examples/python/plots/plots.py | 5 +---- rerun_py/rerun_sdk/rerun/__init__.py | 2 +- rerun_py/rerun_sdk/rerun/_baseclasses.py | 21 ++++++++++++------- rerun_py/rerun_sdk/rerun/_log.py | 8 +++---- rerun_py/rerun_sdk/rerun/any_value.py | 12 +++++------ .../rerun/archetypes/annotation_context.py | 6 ++---- .../rerun_sdk/rerun/archetypes/arrows2d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/arrows3d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/asset3d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/asset_video.py | 6 ++---- .../rerun_sdk/rerun/archetypes/bar_chart.py | 6 ++---- .../rerun_sdk/rerun/archetypes/boxes2d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/boxes3d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/capsules3d.py | 6 ++---- rerun_py/rerun_sdk/rerun/archetypes/clear.py | 6 ++---- .../rerun_sdk/rerun/archetypes/depth_image.py | 6 ++---- .../rerun/archetypes/ellipsoids3d.py | 6 ++---- .../rerun/archetypes/encoded_image.py | 6 ++---- .../rerun/archetypes/geo_line_strings.py | 6 ++---- .../rerun_sdk/rerun/archetypes/geo_points.py | 6 ++---- .../rerun_sdk/rerun/archetypes/graph_edges.py | 6 ++---- .../rerun_sdk/rerun/archetypes/graph_nodes.py | 6 ++---- rerun_py/rerun_sdk/rerun/archetypes/image.py | 6 ++---- .../rerun/archetypes/instance_poses3d.py | 6 ++---- .../rerun/archetypes/line_strips2d.py | 6 ++---- .../rerun/archetypes/line_strips3d.py | 6 ++---- rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/pinhole.py | 6 ++---- .../rerun_sdk/rerun/archetypes/points2d.py | 6 ++---- .../rerun_sdk/rerun/archetypes/points3d.py | 6 ++---- rerun_py/rerun_sdk/rerun/archetypes/scalar.py | 6 ++---- .../rerun/archetypes/segmentation_image.py | 6 ++---- .../rerun_sdk/rerun/archetypes/series_line.py | 6 ++---- .../rerun/archetypes/series_point.py | 6 ++---- rerun_py/rerun_sdk/rerun/archetypes/tensor.py | 6 ++---- .../rerun/archetypes/text_document.py | 6 ++---- .../rerun_sdk/rerun/archetypes/text_log.py | 6 ++---- .../rerun_sdk/rerun/archetypes/transform3d.py | 6 ++---- .../rerun/archetypes/video_frame_reference.py | 6 ++---- .../rerun/archetypes/view_coordinates.py | 6 ++---- .../rerun/components/view_coordinates_ext.py | 6 +++--- .../rerun/datatypes/class_description_ext.py | 6 +++--- .../test_types/archetypes/affix_fuzzer1.py | 6 ++---- .../test_types/archetypes/affix_fuzzer2.py | 6 ++---- .../test_types/archetypes/affix_fuzzer3.py | 6 ++---- .../test_types/archetypes/affix_fuzzer4.py | 6 ++---- 53 files changed, 117 insertions(+), 196 deletions(-) diff --git a/crates/build/re_types_builder/src/codegen/python/mod.rs b/crates/build/re_types_builder/src/codegen/python/mod.rs index 0c87fe0ffe30d..63ad76d0d0916 100644 --- a/crates/build/re_types_builder/src/codegen/python/mod.rs +++ b/crates/build/re_types_builder/src/codegen/python/mod.rs @@ -2645,15 +2645,14 @@ fn quote_columnar_methods(reporter: &Reporter, obj: &Object, objects: &Objects) {init_args}, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) "# diff --git a/crates/store/re_types_core/src/archetype.rs b/crates/store/re_types_core/src/archetype.rs index 836c53f3d6b4e..ea83590ae8d0c 100644 --- a/crates/store/re_types_core/src/archetype.rs +++ b/crates/store/re_types_core/src/archetype.rs @@ -50,7 +50,6 @@ pub trait Archetype { /// Creates a [`ComponentBatch`] out of the associated [`Self::Indicator`] component. /// /// This allows for associating arbitrary indicator components with arbitrary data. - /// Check out the `manual_indicator` API example to see what's possible. fn indicator() -> SerializedComponentBatch; /// Returns all component descriptors that _must_ be provided by the user when constructing this archetype. diff --git a/docs/content/howto/logging/custom-data.md b/docs/content/howto/logging/custom-data.md index 8200fc88f7017..93636ebad1028 100644 --- a/docs/content/howto/logging/custom-data.md +++ b/docs/content/howto/logging/custom-data.md @@ -37,7 +37,7 @@ class LabeledPoints: points: np.ndarray labels: List[str] - def as_component_batches(self) -> Iterable[rr.ComponentBatch]: + def as_component_batches(self) -> list[rr.ComponentBatch]: return rr.Points3D(positions=self.points, labels=self.labels).as_component_batches() … diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.py b/docs/snippets/all/descriptors/descr_custom_archetype.py index 45b9ff50f615a..ddcb1431d6885 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.py +++ b/docs/snippets/all/descriptors/descr_custom_archetype.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Any, Iterable +from typing import Any import numpy.typing as npt import rerun as rr # pip install rerun-sdk @@ -22,7 +22,7 @@ def __init__(self: Any, positions: npt.ArrayLike, colors: npt.ArrayLike) -> None archetype_field_name="colors", ) - def as_component_batches(self) -> Iterable[rr.ComponentBatchLike]: + def as_component_batches(self) -> list[rr.DescribedComponentBatch]: return [self.positions, self.colors] diff --git a/docs/snippets/all/tutorials/custom_data.py b/docs/snippets/all/tutorials/custom_data.py index 661db34a83ba3..10e6e5e995a2a 100755 --- a/docs/snippets/all/tutorials/custom_data.py +++ b/docs/snippets/all/tutorials/custom_data.py @@ -3,7 +3,7 @@ from __future__ import annotations import argparse -from typing import Any, Iterable +from typing import Any import numpy as np import numpy.typing as npt @@ -35,7 +35,7 @@ def __init__(self: Any, positions: npt.ArrayLike, confidences: npt.ArrayLike) -> archetype_name="user.CustomPoints3D", archetype_field_name="confidences" ) - def as_component_batches(self) -> Iterable[rr.ComponentBatchLike]: + def as_component_batches(self) -> list[rr.DescribedComponentBatch]: return ( list(self.points3d.as_component_batches()) # The components from Points3D + [self.confidences] # Custom confidence data diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 28fff444a310c..a0d167a20b62c 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -2,7 +2,6 @@ # These snippets will be excluded from the snippet index, unconditionally. [snippets_ref.snippets.opt_out] -"archetypes/manual_indicator" = [] # These archetypes will ignore the associated snippets in the snippet index. [snippets_ref.archetypes.opt_out] diff --git a/examples/python/openstreetmap_data/openstreetmap_data.py b/examples/python/openstreetmap_data/openstreetmap_data.py index a93b22d85e7f1..9d7379cf99d5b 100644 --- a/examples/python/openstreetmap_data/openstreetmap_data.py +++ b/examples/python/openstreetmap_data/openstreetmap_data.py @@ -81,7 +81,7 @@ def log_way(way: dict[str, Any]) -> None: def log_data(data: dict[str, Any]) -> None: try: copyright_text = data["osm3s"]["copyright"] - rr.log("copyright", [rr.components.Text(copyright_text)], static=True) + rr.log("copyright", rr.TextDocument(copyright_text), static=True) except KeyError: pass diff --git a/examples/python/plots/plots.py b/examples/python/plots/plots.py index 8ef9008138d28..681849a4b63c6 100755 --- a/examples/python/plots/plots.py +++ b/examples/python/plots/plots.py @@ -101,10 +101,7 @@ def log_classification() -> None: rr.log( "classification/samples", rr.Scalar(g_of_t), - [ - rr.components.Color(color), - rr.components.MarkerSize(marker_size), - ], + rr.SeriesPoint(color=color, marker_size=marker_size), ) diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index c9bb5414cb4c3..d970a74ad7493 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -33,6 +33,7 @@ remote as remote, ) from ._baseclasses import ( + ComponentBatchLike as ComponentBatchLike, ComponentBatchMixin as ComponentBatchMixin, ComponentColumn as ComponentColumn, ComponentColumnList as ComponentColumnList, @@ -45,7 +46,6 @@ ) from ._log import ( AsComponents as AsComponents, - ComponentBatchLike as ComponentBatchLike, IndicatorComponentBatch as IndicatorComponentBatch, escape_entity_path_part as escape_entity_path_part, log as log, diff --git a/rerun_py/rerun_sdk/rerun/_baseclasses.py b/rerun_py/rerun_sdk/rerun/_baseclasses.py index 10b57f3668a33..de07020e73958 100644 --- a/rerun_py/rerun_sdk/rerun/_baseclasses.py +++ b/rerun_py/rerun_sdk/rerun/_baseclasses.py @@ -172,7 +172,7 @@ def as_arrow_array(self) -> pa.Array: class AsComponents(Protocol): """Describes interface for interpreting an object as a bundle of Components.""" - def as_component_batches(self) -> Iterable[ComponentBatchLike]: + def as_component_batches(self) -> list[DescribedComponentBatch]: """ Returns an iterable of `ComponentBatchLike` objects. @@ -204,24 +204,27 @@ def archetype_name(cls) -> str: return ".".join(cls.__module__.rsplit(".", 1)[:-1] + [cls.__name__]) @classmethod - def indicator(cls) -> ComponentBatchLike: + def indicator(cls) -> DescribedComponentBatch: """ - Creates a `ComponentBatchLike` out of the associated indicator component. + Creates a `DescribedComponentBatch` out of the associated indicator component. This allows for associating arbitrary indicator components with arbitrary data. - Check out the `manual_indicator` API example to see what's possible. """ from ._log import IndicatorComponentBatch - return IndicatorComponentBatch(cls.archetype_name()) + indicator = IndicatorComponentBatch(cls.archetype_name()) + return DescribedComponentBatch(indicator, indicator.component_descriptor()) - def as_component_batches(self) -> Iterable[ComponentBatchLike]: + def as_component_batches(self, *, include_indicators: bool = True) -> list[DescribedComponentBatch]: """ Return all the component batches that make up the archetype. Part of the `AsComponents` logging interface. """ - yield self.indicator() + if include_indicators: + batches = [self.indicator()] + else: + batches = [] for fld in fields(type(self)): if "component" in fld.metadata: @@ -232,7 +235,9 @@ def as_component_batches(self) -> Iterable[ComponentBatchLike]: archetype_name=self.archetype_name(), archetype_field_name=fld.name, ) - yield DescribedComponentBatch(comp, descr) + batches.append(DescribedComponentBatch(comp, descr)) + + return batches __repr__ = __str__ diff --git a/rerun_py/rerun_sdk/rerun/_log.py b/rerun_py/rerun_sdk/rerun/_log.py index 1cc96a0e6304a..c6814bf6229ef 100644 --- a/rerun_py/rerun_sdk/rerun/_log.py +++ b/rerun_py/rerun_sdk/rerun/_log.py @@ -6,7 +6,7 @@ import pyarrow as pa import rerun_bindings as bindings -from ._baseclasses import AsComponents, ComponentBatchLike, ComponentDescriptor +from ._baseclasses import AsComponents, ComponentDescriptor, DescribedComponentBatch from .error_utils import _send_warning_or_raise, catch_and_log_exceptions from .recording_stream import RecordingStream @@ -50,8 +50,8 @@ def component_descriptor(self) -> ComponentDescriptor: @catch_and_log_exceptions() def log( entity_path: str | list[str], - entity: AsComponents | Iterable[ComponentBatchLike], - *extra: AsComponents | Iterable[ComponentBatchLike], + entity: AsComponents | Iterable[DescribedComponentBatch], + *extra: AsComponents | Iterable[DescribedComponentBatch], static: bool = False, recording: RecordingStream | None = None, strict: bool | None = None, @@ -170,7 +170,7 @@ def log( @catch_and_log_exceptions() def log_components( entity_path: str | list[str], - components: Iterable[ComponentBatchLike], + components: Iterable[DescribedComponentBatch], *, static: bool = False, recording: RecordingStream | None = None, diff --git a/rerun_py/rerun_sdk/rerun/any_value.py b/rerun_py/rerun_sdk/rerun/any_value.py index 699e1f4cbb643..9178738d99ec3 100644 --- a/rerun_py/rerun_sdk/rerun/any_value.py +++ b/rerun_py/rerun_sdk/rerun/any_value.py @@ -1,14 +1,14 @@ from __future__ import annotations -from typing import Any, Iterable +from typing import Any import numpy as np import pyarrow as pa from rerun._baseclasses import ComponentDescriptor -from ._baseclasses import ComponentColumn, ComponentColumnList -from ._log import AsComponents, ComponentBatchLike +from ._baseclasses import ComponentBatchLike, ComponentColumn, ComponentColumnList, DescribedComponentBatch +from ._log import AsComponents from .error_utils import catch_and_log_exceptions ANY_VALUE_TYPE_REGISTRY: dict[ComponentDescriptor, Any] = {} @@ -213,15 +213,15 @@ def __init__(self, drop_untyped_nones: bool = True, **kwargs: Any) -> None: """ global ANY_VALUE_TYPE_REGISTRY - self.component_batches = [] + self.component_batches = list() with catch_and_log_exceptions(self.__class__.__name__): for name, value in kwargs.items(): batch = AnyBatchValue(name, value, drop_untyped_nones=drop_untyped_nones) if batch.is_valid(): - self.component_batches.append(batch) + self.component_batches.append(DescribedComponentBatch(batch, batch.descriptor)) - def as_component_batches(self) -> Iterable[ComponentBatchLike]: + def as_component_batches(self) -> list[DescribedComponentBatch]: return self.component_batches @classmethod diff --git a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py index 0dbc49759503f..3a6e3a429e282 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -161,15 +160,14 @@ def columns( context=context, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py index 67c699e5d1a66..a9d24dbfd7f7e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .arrows2d_ext import Arrows2DExt @@ -224,15 +223,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py index 46fbb6b3908d2..1d79f54be2972 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .arrows3d_ext import Arrows3DExt @@ -211,15 +210,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py index a79de5417499f..8d7e0ebf9a156 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .asset3d_ext import Asset3DExt @@ -182,15 +181,14 @@ def columns( albedo_factor=albedo_factor, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index cc562db11e5ea..39c32dad89357 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .asset_video_ext import AssetVideoExt @@ -216,15 +215,14 @@ def columns( media_type=media_type, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py index c2fd31202688f..3815c5a440916 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .bar_chart_ext import BarChartExt @@ -157,15 +156,14 @@ def columns( color=color, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index 1a9d3544b18a6..191f0d9b6bbcc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .boxes2d_ext import Boxes2DExt @@ -209,15 +208,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py index a52824abe62f5..0253571684037 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .boxes3d_ext import Boxes3DExt @@ -255,15 +254,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py index 451187d2c8050..b95ef33848c27 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .capsules3d_ext import Capsules3DExt @@ -254,15 +253,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/clear.py b/rerun_py/rerun_sdk/rerun/archetypes/clear.py index aa3df34320738..d5e534dcd996d 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/clear.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/clear.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .clear_ext import ClearExt @@ -132,15 +131,14 @@ def columns( is_recursive=is_recursive, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py index edc3caa9a0ab0..1b338da1eca73 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .depth_image_ext import DepthImageExt @@ -252,15 +251,14 @@ def columns( draw_order=draw_order, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py index 9c1cc1c9fadce..3ffb63eafa177 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .ellipsoids3d_ext import Ellipsoids3DExt @@ -256,15 +255,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py index fc5a335e6977c..0499c68726723 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .encoded_image_ext import EncodedImageExt @@ -177,15 +176,14 @@ def columns( draw_order=draw_order, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py index 5dcec3aca6194..b215ec5f185f3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .geo_line_strings_ext import GeoLineStringsExt @@ -173,15 +172,14 @@ def columns( colors=colors, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py index 12448bdae4334..6e8af386c3531 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .geo_points_ext import GeoPointsExt @@ -176,15 +175,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py index 971521785ce39..df899cdc2a217 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -169,15 +168,14 @@ def columns( graph_type=graph_type, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py index 6fb1b80fafb60..bd10b1f256451 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -221,15 +220,14 @@ def columns( radii=radii, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py index 676732732eec3..e30ea37620192 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .image_ext import ImageExt @@ -207,15 +206,14 @@ def columns( draw_order=draw_order, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py index d1eabfed421cc..6666628e182ec 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -229,15 +228,14 @@ def columns( mat3x3=mat3x3, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index 1a227a10f75f3..034dd9d7c0067 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -301,15 +300,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py index 6d6c7eb87349e..4fe82549563cc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -292,15 +291,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py index 9642cc8945ccb..db0716a5982d5 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .mesh3d_ext import Mesh3DExt @@ -272,15 +271,14 @@ def columns( class_ids=class_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py index 8dfb85e263489..4809091292b9d 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .pinhole_ext import PinholeExt @@ -252,15 +251,14 @@ def columns( image_plane_distance=image_plane_distance, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index 597b2f1f456a3..9907eeaa834dd 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .points2d_ext import Points2DExt @@ -279,15 +278,14 @@ def columns( keypoint_ids=keypoint_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index 93877ff3f4acc..03a1f4e09316a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .points3d_ext import Points3DExt @@ -302,15 +301,14 @@ def columns( keypoint_ids=keypoint_ids, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index 0935a5449b8a3..186290834ca0c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -185,15 +184,14 @@ def columns( scalar=scalar, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py index 59069ba65891b..a1211ed171168 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .segmentation_image_ext import SegmentationImageExt @@ -179,15 +178,14 @@ def columns( draw_order=draw_order, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 176c0d0c8d882..35976c95e4084 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -219,15 +218,14 @@ def columns( aggregation_policy=aggregation_policy, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index 3cade8565bcb5..4e66927515bd1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -225,15 +224,14 @@ def columns( marker_size=marker_size, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py index 7920f6d050237..066854ef64a36 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .tensor_ext import TensorExt @@ -165,15 +164,14 @@ def columns( value_range=value_range, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py index b223747a0fe9b..ac5214af50e8f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -217,15 +216,14 @@ def columns( media_type=media_type, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py index 076e4f286e622..987e261f90099 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions @@ -186,15 +185,14 @@ def columns( color=color, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index cc9ce26b45cb6..d8382baf71b70 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .transform3d_ext import Transform3DExt @@ -280,15 +279,14 @@ def columns( axis_length=axis_length, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index 1151f796679de..ee94f43bebc03 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -12,7 +12,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .video_frame_reference_ext import VideoFrameReferenceExt @@ -232,15 +231,14 @@ def columns( video_reference=video_reference, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 754e6cd15b887..708f57571dab7 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -14,7 +14,6 @@ from .._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from ..error_utils import catch_and_log_exceptions from .view_coordinates_ext import ViewCoordinatesExt @@ -163,15 +162,14 @@ def columns( xyz=xyz, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py b/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py index c98b7d1ad6fee..10bc10471f69a 100644 --- a/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py @@ -1,13 +1,13 @@ from __future__ import annotations from enum import IntEnum -from typing import TYPE_CHECKING, Any, Iterable, cast +from typing import TYPE_CHECKING, Any, cast import numpy as np import numpy.typing as npt if TYPE_CHECKING: - from .._log import ComponentBatchLike + from .._baseclasses import DescribedComponentBatch from . import ViewCoordinates @@ -30,7 +30,7 @@ def coordinates__field_converter_override(data: npt.ArrayLike) -> npt.NDArray[np return coordinates # Implement the AsComponents protocol - def as_component_batches(self) -> Iterable[ComponentBatchLike]: + def as_component_batches(self) -> list[DescribedComponentBatch]: from ..archetypes import ViewCoordinates from ..components import ViewCoordinates as ViewCoordinatesComponent diff --git a/rerun_py/rerun_sdk/rerun/datatypes/class_description_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/class_description_ext.py index c754b876ae211..0a0bbdcf759a1 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/class_description_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/class_description_ext.py @@ -1,14 +1,14 @@ from __future__ import annotations import itertools -from typing import TYPE_CHECKING, Any, Iterable, Sequence, cast +from typing import TYPE_CHECKING, Any, Sequence, cast import pyarrow as pa from .keypoint_pair_ext import _keypoint_pair_converter if TYPE_CHECKING: - from .. import ComponentBatchLike + from .. import DescribedComponentBatch from . import ( AnnotationInfo, AnnotationInfoLike, @@ -65,7 +65,7 @@ def __init__( ) # Implement the AsComponents protocol - def as_component_batches(self) -> Iterable[ComponentBatchLike]: + def as_component_batches(self) -> list[DescribedComponentBatch]: from ..archetypes import AnnotationContext from . import ClassDescription diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py index 79ceb0c878b35..63caa98f29c55 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py @@ -12,7 +12,6 @@ from rerun._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -247,15 +246,14 @@ def columns( fuzz1022=fuzz1022, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py index 8c0a406757f05..b2515c0df034c 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py @@ -12,7 +12,6 @@ from rerun._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -226,15 +225,14 @@ def columns( fuzz1122=fuzz1122, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py index a80bcc258c747..e91fc070719c5 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py @@ -12,7 +12,6 @@ from rerun._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -220,15 +219,14 @@ def columns( fuzz2018=fuzz2018, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py index c82c67cff9762..966b0f21cc40d 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py @@ -12,7 +12,6 @@ from rerun._baseclasses import ( Archetype, ComponentColumnList, - DescribedComponentBatch, ) from rerun.error_utils import catch_and_log_exceptions @@ -220,15 +219,14 @@ def columns( fuzz2118=fuzz2118, ) - batches = [batch for batch in inst.as_component_batches() if isinstance(batch, DescribedComponentBatch)] + batches = inst.as_component_batches(include_indicators=False) if len(batches) == 0: return ComponentColumnList([]) lengths = np.ones(len(batches[0]._batch.as_arrow_array())) columns = [batch.partition(lengths) for batch in batches] - indicator_batch = DescribedComponentBatch(cls.indicator(), cls.indicator().component_descriptor()) - indicator_column = indicator_batch.partition(np.zeros(len(lengths))) + indicator_column = cls.indicator().partition(np.zeros(len(lengths))) return ComponentColumnList([indicator_column] + columns) From 46bca8859d77647b94a262ca5b33e6f34e9af89f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 29 Jan 2025 16:00:14 +0100 Subject: [PATCH 29/43] Opt out of {platform/compiler}-dependent C++ snippets (#8851) --- docs/snippets/all/archetypes/series_line_style.cpp | 2 +- docs/snippets/all/archetypes/series_point_style.cpp | 2 +- docs/snippets/snippets.toml | 6 ++++++ rerun_cpp/src/rerun/archetypes/series_line.hpp | 2 +- rerun_cpp/src/rerun/archetypes/series_point.hpp | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/snippets/all/archetypes/series_line_style.cpp b/docs/snippets/all/archetypes/series_line_style.cpp index 00a0d4a31923d..f0a66197b8e52 100644 --- a/docs/snippets/all/archetypes/series_line_style.cpp +++ b/docs/snippets/all/archetypes/series_line_style.cpp @@ -27,6 +27,6 @@ int main() { rec.set_time_sequence("step", t); rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 100.0))); - rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0f))); + rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0))); } } diff --git a/docs/snippets/all/archetypes/series_point_style.cpp b/docs/snippets/all/archetypes/series_point_style.cpp index 21914afbfd25e..6630943fa000e 100644 --- a/docs/snippets/all/archetypes/series_point_style.cpp +++ b/docs/snippets/all/archetypes/series_point_style.cpp @@ -35,6 +35,6 @@ int main() { rec.set_time_sequence("step", t); rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 10.0))); - rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 10.0f))); + rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 10.0))); } } diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index a0d167a20b62c..8e6c67c813a9f 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -260,6 +260,12 @@ quick_start = [ # These examples don't have exactly the same implementation. "archetypes/mesh3d_instancing" = [ # Python uses doubles "py", ] +"archetypes/series_line_style" = [ + "cpp", # somehow, C++ yields a different result, see +] +"archetypes/series_point_style" = [ + "cpp", # somehow, C++ yields a different result, see +] # `$config_dir` will be replaced with the absolute path of `docs/snippets`. # Note that the snippet comparison tool will automatically run `/tests/assets/download_test_assets.py` before running the snippets. diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index 4722904b7ba57..a5df98544785b 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -58,7 +58,7 @@ namespace rerun::archetypes { /// rec.set_time_sequence("step", t); /// /// rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 100.0))); - /// rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0f))); + /// rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0))); /// } /// } /// ``` diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index 47b59063e40b2..2e2f7b8365bdd 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -66,7 +66,7 @@ namespace rerun::archetypes { /// rec.set_time_sequence("step", t); /// /// rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 10.0))); - /// rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 10.0f))); + /// rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 10.0))); /// } /// } /// ``` From e3990f8069c8b3d666b2d0171d5fcbb0f6ccbb78 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:54:05 +0100 Subject: [PATCH 30/43] Fix failing nightly (#8862) --- crates/viewer/re_blueprint_tree/Cargo.toml | 1 + docs/snippets/all/tutorials/custom_data.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/viewer/re_blueprint_tree/Cargo.toml b/crates/viewer/re_blueprint_tree/Cargo.toml index daba6ada7340b..0bc11d345ea39 100644 --- a/crates/viewer/re_blueprint_tree/Cargo.toml +++ b/crates/viewer/re_blueprint_tree/Cargo.toml @@ -50,3 +50,4 @@ re_viewport_blueprint = { workspace = true, features = ["testing"] } egui_kittest.workspace = true insta = { workspace = true, features = ["redactions", "yaml"] } +smallvec = { workspace = true, features = ["serde"] } diff --git a/docs/snippets/all/tutorials/custom_data.rs b/docs/snippets/all/tutorials/custom_data.rs index 9105b951e607b..d07710c9ee780 100644 --- a/docs/snippets/all/tutorials/custom_data.rs +++ b/docs/snippets/all/tutorials/custom_data.rs @@ -23,16 +23,16 @@ impl rerun::AsComponents for CustomPoints3D { .as_serialized_batches() .into_iter() .chain( - [self - .confidences - .as_ref() - .and_then(|batch| batch.serialized()) - .map(|batch| + std::iter::once( + self.confidences + .as_ref() + .and_then(|batch| batch.serialized()) + .map(|batch| // Optionally override the descriptor with extra information. batch .or_with_archetype_name(|| "user.CustomPoints3D".into()) - .or_with_archetype_field_name(|| "confidences".into()))] - .into_iter() + .or_with_archetype_field_name(|| "confidences".into())), + ) .flatten(), ) .collect() From 2dd6e80fceae4eb0e48ad851b7a822ec4ecb1b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20G=C3=B6rtler?= Date: Thu, 30 Jan 2025 10:12:09 +0100 Subject: [PATCH 31/43] Convert graph view to `egui::Scene` (#8847) ### Related * Closes #8478 ### What Title. --- Cargo.lock | 28 ++--- crates/viewer/re_ui/src/lib.rs | 1 - crates/viewer/re_ui/src/zoom_pan_area.rs | 114 ------------------ crates/viewer/re_view_graph/src/properties.rs | 10 +- crates/viewer/re_view_graph/src/ui/draw.rs | 4 +- crates/viewer/re_view_graph/src/ui/state.rs | 1 - crates/viewer/re_view_graph/src/view.rs | 71 +++++------ .../tests/snapshots/coincident_nodes.png | 4 +- .../tests/snapshots/self_and_multi_edges.png | 4 +- 9 files changed, 53 insertions(+), 184 deletions(-) delete mode 100644 crates/viewer/re_ui/src/zoom_pan_area.rs diff --git a/Cargo.lock b/Cargo.lock index 1c4309d97405a..68944fa4819db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1957,7 +1957,7 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ecolor" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "bytemuck", "color-hex", @@ -1974,7 +1974,7 @@ checksum = "18aade80d5e09429040243ce1143ddc08a92d7a22820ac512610410a4dd5214f" [[package]] name = "eframe" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "ahash", "bytemuck", @@ -2013,7 +2013,7 @@ dependencies = [ [[package]] name = "egui" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "accesskit", "ahash", @@ -2031,7 +2031,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "ahash", "bytemuck", @@ -2050,7 +2050,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "accesskit_winit", "ahash", @@ -2091,7 +2091,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "ahash", "egui", @@ -2108,7 +2108,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "ahash", "bytemuck", @@ -2125,7 +2125,7 @@ dependencies = [ [[package]] name = "egui_kittest" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "dify", "eframe", @@ -2196,7 +2196,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "emath" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "bytemuck", "serde", @@ -2312,7 +2312,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" dependencies = [ "ab_glyph", "ahash", @@ -2331,7 +2331,7 @@ dependencies = [ [[package]] name = "epaint_default_fonts" version = "0.30.0" -source = "git+https://github.com/emilk/egui.git?branch=master#bc5f908b80cbcb20a728b36d20df860d90a29263" +source = "git+https://github.com/emilk/egui.git?branch=master#83649f2e295a4c27ea08023b6e7f591d3e60ea7f" [[package]] name = "equivalent" @@ -3902,7 +3902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5493,7 +5493,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -10032,7 +10032,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/crates/viewer/re_ui/src/lib.rs b/crates/viewer/re_ui/src/lib.rs index d41c88322d06b..96cb28147f4f5 100644 --- a/crates/viewer/re_ui/src/lib.rs +++ b/crates/viewer/re_ui/src/lib.rs @@ -16,7 +16,6 @@ mod section_collapsing_header; pub mod syntax_highlighting; mod ui_ext; mod ui_layout; -pub mod zoom_pan_area; use egui::Color32; use egui::NumExt as _; diff --git a/crates/viewer/re_ui/src/zoom_pan_area.rs b/crates/viewer/re_ui/src/zoom_pan_area.rs deleted file mode 100644 index f3f2530ba571c..0000000000000 --- a/crates/viewer/re_ui/src/zoom_pan_area.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! A small, self-container pan-and-zoom area for [`egui`]. -//! -//! Throughout this module, we use the following conventions or naming the different spaces: -//! * `ui`-space: The _global_ `egui` space. -//! * `view`-space: The space where the pan-and-zoom area is drawn. -//! * `scene`-space: The space where the actual content is drawn. - -use egui::{emath::TSTransform, Rect, Response, Ui, UiBuilder, Vec2}; - -/// Helper function to handle pan and zoom interactions on a response. -fn register_pan_and_zoom(ui: &Ui, resp: &Response, ui_from_scene: &mut TSTransform) { - if resp.dragged() { - ui_from_scene.translation += ui_from_scene.scaling * resp.drag_delta(); - } - - if let Some(mouse_pos) = ui.input(|i| i.pointer.latest_pos()) { - if resp.contains_pointer() { - let pointer_in_scene = ui_from_scene.inverse() * mouse_pos; - let zoom_delta = ui.ctx().input(|i| i.zoom_delta()); - let pan_delta = ui.ctx().input(|i| i.smooth_scroll_delta); - - // Most of the time we can return early. This is also important to - // avoid `ui_from_scene` to change slightly due to floating point errors. - if zoom_delta == 1.0 && pan_delta == Vec2::ZERO { - return; - } - - // Zoom in on pointer, but only if we are not zoomed out too far. - if zoom_delta < 1.0 || ui_from_scene.scaling < 1.0 { - *ui_from_scene = *ui_from_scene - * TSTransform::from_translation(pointer_in_scene.to_vec2()) - * TSTransform::from_scaling(zoom_delta) - * TSTransform::from_translation(-pointer_in_scene.to_vec2()); - - // We clamp the resulting scaling to avoid zooming out too far. - ui_from_scene.scaling = ui_from_scene.scaling.min(1.0); - } - - // Pan: - *ui_from_scene = TSTransform::from_translation(pan_delta) * *ui_from_scene; - } - } -} - -/// Creates a transformation that fits a given scene rectangle into the available screen size. -pub fn fit_to_rect_in_scene(rect_in_ui: Rect, rect_in_scene: Rect) -> TSTransform { - let available_size_in_ui = rect_in_ui.size(); - - // Compute the scale factor to fit the bounding rectangle into the available screen size. - let scale_x = available_size_in_ui.x / rect_in_scene.width(); - let scale_y = available_size_in_ui.y / rect_in_scene.height(); - - // Use the smaller of the two scales to ensure the whole rectangle fits on the screen. - let scale = scale_x.min(scale_y).min(1.0); - - // Compute the translation to center the bounding rect in the screen. - let center_screen = rect_in_ui.center(); - let center_scene = rect_in_scene.center().to_vec2(); - - // Set the transformation to scale and then translate to center. - TSTransform::from_translation(center_screen.to_vec2() - center_scene * scale) - * TSTransform::from_scaling(scale) -} - -/// Provides a zoom-pan area for a given view. -/// -/// Will fill the entire `max_rect` of the `parent_ui`. -pub fn zoom_pan_area( - parent_ui: &mut Ui, - to_global: &mut TSTransform, - draw_contents: impl FnOnce(&mut Ui), -) -> Response { - // Create a new egui paint layer, where we can draw our contents: - let zoom_pan_layer_id = egui::LayerId::new( - parent_ui.layer_id().order, - parent_ui.id().with("zoom_pan_area"), - ); - - // Put the layer directly on-top of the main layer of the ui: - parent_ui - .ctx() - .set_sublayer(parent_ui.layer_id(), zoom_pan_layer_id); - - let global_view_bounds = parent_ui.max_rect(); - - let mut local_ui = parent_ui.new_child( - UiBuilder::new() - .layer_id(zoom_pan_layer_id) - .max_rect(to_global.inverse() * global_view_bounds) - .sense(egui::Sense::click_and_drag()), - ); - local_ui.set_min_size(local_ui.max_rect().size()); // Allocate all available space - - // Set proper clip-rect so we can interact with the background: - local_ui.set_clip_rect(local_ui.max_rect()); - - let pan_response = local_ui.response(); - - // Update the `to_global` transform based on use interaction: - register_pan_and_zoom(&local_ui, &pan_response, to_global); - - // Update the clip-rect with the new transform, to avoid frame-delays - local_ui.set_clip_rect(to_global.inverse() * global_view_bounds); - - // Add the actual contents to the area: - draw_contents(&mut local_ui); - - // Tell egui to apply the transform on the layer: - local_ui - .ctx() - .set_transform_layer(zoom_pan_layer_id, *to_global); - - pan_response -} diff --git a/crates/viewer/re_view_graph/src/properties.rs b/crates/viewer/re_view_graph/src/properties.rs index 35ad81696095a..068a667addc22 100644 --- a/crates/viewer/re_view_graph/src/properties.rs +++ b/crates/viewer/re_view_graph/src/properties.rs @@ -6,7 +6,6 @@ use re_types::{ components::Position2D, Archetype as _, }; -use re_ui::zoom_pan_area::fit_to_rect_in_scene; use re_viewer_context::{TypedComponentFallbackProvider, ViewStateExt as _}; use crate::{ui::GraphViewState, GraphView}; @@ -22,14 +21,7 @@ impl TypedComponentFallbackProvider for GraphView { }; match state.layout_state.bounding_rect() { - Some(rect) if valid_bound(&rect) => { - if let Some(rect_in_ui) = state.rect_in_ui { - let ui_from_world = fit_to_rect_in_scene(rect_in_ui, rect); - (ui_from_world.inverse() * rect_in_ui).into() - } else { - rect.into() - } - } + Some(rect) if valid_bound(&rect) => rect.into(), _ => VisualBounds2D::default(), } } diff --git a/crates/viewer/re_view_graph/src/ui/draw.rs b/crates/viewer/re_view_graph/src/ui/draw.rs index 237a1837091d9..c6f2940a363dd 100644 --- a/crates/viewer/re_view_graph/src/ui/draw.rs +++ b/crates/viewer/re_view_graph/src/ui/draw.rs @@ -52,8 +52,8 @@ pub enum LevelOfDetail { } impl LevelOfDetail { - pub fn from_scaling(zoom: f32) -> Self { - if zoom < 0.20 { + pub fn from_scaling(scale: f32) -> Self { + if scale < 0.20 { Self::Low } else { Self::Full diff --git a/crates/viewer/re_view_graph/src/ui/state.rs b/crates/viewer/re_view_graph/src/ui/state.rs index 79c0221174e08..7564324f527a9 100644 --- a/crates/viewer/re_view_graph/src/ui/state.rs +++ b/crates/viewer/re_view_graph/src/ui/state.rs @@ -13,7 +13,6 @@ use crate::layout::{ForceLayoutParams, ForceLayoutProvider, Layout, LayoutReques pub struct GraphViewState { pub layout_state: LayoutState, pub visual_bounds: Option, - pub rect_in_ui: Option, } impl GraphViewState { diff --git a/crates/viewer/re_view_graph/src/view.rs b/crates/viewer/re_view_graph/src/view.rs index f0842ffdd8ff8..5d6a85aa2ece8 100644 --- a/crates/viewer/re_view_graph/src/view.rs +++ b/crates/viewer/re_view_graph/src/view.rs @@ -1,4 +1,3 @@ -use egui::Response; use re_log_types::EntityPath; use re_types::{ blueprint::{ @@ -10,11 +9,7 @@ use re_types::{ }, ViewClassIdentifier, }; -use re_ui::{ - self, - zoom_pan_area::{fit_to_rect_in_scene, zoom_pan_area}, - ModifiersMarkdown, MouseButtonMarkdown, UiExt as _, -}; +use re_ui::{self, ModifiersMarkdown, MouseButtonMarkdown, UiExt as _}; use re_view::{ controls::{DRAG_PAN2D_BUTTON, ZOOM_SCROLL_MODIFIER}, view_property_ui, @@ -182,34 +177,33 @@ Display a graph of nodes and edges. let request = LayoutRequest::from_graphs(graphs.iter()); let layout = state.layout_state.get(request, params); - // Prepare the view and the transformations. - let rect_in_ui = *state.rect_in_ui.insert(ui.max_rect()); - - let mut ui_from_world = fit_to_rect_in_scene(rect_in_ui, rect_in_scene.into()); - - // We store a copy of the transformation to see if it has changed. - let ui_from_world_ref = ui_from_world; - - let level_of_detail = LevelOfDetail::from_scaling(ui_from_world.scaling); - - let mut hover_click_item: Option<(Item, Response)> = None; - - let resp = zoom_pan_area(ui, &mut ui_from_world, |ui| { - let mut world_bounding_rect = egui::Rect::NOTHING; - - for graph in &graphs { - let graph_rect = draw_graph( - ui, - ctx, - graph, - layout, - query, - level_of_detail, - &mut hover_click_item, - ); - world_bounding_rect = world_bounding_rect.union(graph_rect); - } - }); + let mut scene_rect = egui::Rect::from(rect_in_scene); + let scene_rect_ref = scene_rect; + + // To determine the overall scale factor needed for the level-of-details + // computation, we need to look at the two dimensions separately due to letter-boxing. + let rect_in_ui = ui.max_rect(); + let scale = rect_in_ui.size() / scene_rect.size(); + + let level_of_detail = LevelOfDetail::from_scaling(scale.min_elem()); + + let mut hover_click_item: Option<(Item, egui::Response)> = None; + + let resp = egui::Scene::new() + .show(ui, &mut scene_rect, |ui| { + for graph in &graphs { + draw_graph( + ui, + ctx, + graph, + layout, + query, + level_of_detail, + &mut hover_click_item, + ); + } + }) + .response; if let Some((item, response)) = hover_click_item { ctx.handle_select_hover_drag_interactions(&response, item, false); @@ -224,15 +218,14 @@ Display a graph of nodes and edges. } // Update blueprint if changed - let updated_rect_in_scene = - blueprint::components::VisualBounds2D::from(ui_from_world.inverse() * rect_in_ui); + let updated_bounds = blueprint::components::VisualBounds2D::from(scene_rect); if resp.double_clicked() { bounds_property.reset_blueprint_component::(ctx); - } else if ui_from_world != ui_from_world_ref { - bounds_property.save_blueprint_component(ctx, &updated_rect_in_scene); + } else if scene_rect != scene_rect_ref { + bounds_property.save_blueprint_component(ctx, &updated_bounds); } // Update stored bounds on the state, so visualizers see an up-to-date value. - state.visual_bounds = Some(updated_rect_in_scene); + state.visual_bounds = Some(updated_bounds); if state.layout_state.is_in_progress() { ui.ctx().request_repaint(); diff --git a/crates/viewer/re_view_graph/tests/snapshots/coincident_nodes.png b/crates/viewer/re_view_graph/tests/snapshots/coincident_nodes.png index 822c52010a9f3..f62dabd54955b 100644 --- a/crates/viewer/re_view_graph/tests/snapshots/coincident_nodes.png +++ b/crates/viewer/re_view_graph/tests/snapshots/coincident_nodes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92c1300cfe79b2369f2e6446119159dde90835c8e01caabdc587567249ae6ccf -size 848 +oid sha256:177dfc40ce059ed36109d783e0a5862378042d0f365147107940014d3b14b4d3 +size 870 diff --git a/crates/viewer/re_view_graph/tests/snapshots/self_and_multi_edges.png b/crates/viewer/re_view_graph/tests/snapshots/self_and_multi_edges.png index 19135e6297249..35efb3fc0ff60 100644 --- a/crates/viewer/re_view_graph/tests/snapshots/self_and_multi_edges.png +++ b/crates/viewer/re_view_graph/tests/snapshots/self_and_multi_edges.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c9674e1320b5f097078357c41fd56d16007ad30d12a9296ee8c77c35f52b0d2 -size 22355 +oid sha256:b02fc0df02c613dfb41a8ec712d7ab1648c1ce0fe324f1d992e2a24e4fdb553f +size 20082 From 1352fa35d5e779e5886da593711c216c76a81b42 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 30 Jan 2025 10:39:05 +0100 Subject: [PATCH 32/43] Fix rounding issue in snippet comparision (#8867) --- docs/snippets/all/archetypes/arrows3d_simple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/snippets/all/archetypes/arrows3d_simple.cpp b/docs/snippets/all/archetypes/arrows3d_simple.cpp index 1d668ef386d74..5c9877d884cd5 100644 --- a/docs/snippets/all/archetypes/arrows3d_simple.cpp +++ b/docs/snippets/all/archetypes/arrows3d_simple.cpp @@ -19,7 +19,7 @@ int main() { origins.push_back({0, 0, 0}); float angle = TAU * static_cast(i) * 0.01f; - float length = log2f(static_cast(i + 1)); + float length = static_cast(log2(i + 1)); vectors.push_back({length * sinf(angle), 0.0, length * cosf(angle)}); uint8_t c = static_cast(round(angle / TAU * 255.0f)); From 306f7df30bf70bd6d0225b7c2323c462d812f89f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 30 Jan 2025 10:58:49 +0100 Subject: [PATCH 33/43] Require descriptors to be provided on all log calls in C++ (either explicitely or implicitely via archetype) (#8853) Co-authored-by: Clement Rey --- .../reference/migration/migration-0-22.md | 24 +- .../concepts/different_data_per_timeline.cpp | 4 +- .../descriptors/descr_builtin_component.cpp | 9 +- .../descriptors/descr_custom_component.cpp | 9 +- examples/cpp/incremental_logging/main.cpp | 10 +- rerun_cpp/src/rerun/as_components.hpp | 86 ++--- rerun_cpp/src/rerun/component_batch.hpp | 48 --- rerun_cpp/src/rerun/component_column.hpp | 38 +-- rerun_cpp/src/rerun/recording_stream.hpp | 75 +++-- rerun_cpp/tests/log_empty.cpp | 11 +- rerun_cpp/tests/recording_stream.cpp | 315 ++++-------------- 11 files changed, 195 insertions(+), 434 deletions(-) diff --git a/docs/content/reference/migration/migration-0-22.md b/docs/content/reference/migration/migration-0-22.md index 093f5d730c8bb..2658d923d6bd7 100644 --- a/docs/content/reference/migration/migration-0-22.md +++ b/docs/content/reference/migration/migration-0-22.md @@ -39,11 +39,29 @@ As part of the switch to "eager archetype serialization" (serialization of arche However, it is still possible to do so with the `TensorData` component. -### C++ `RecordingStream::send_column` no longer takes raw component collections +### C++ `RecordingStream::log`/`send_column` no longer takes raw component collections -Previously, `RecordingStream::send_column` accepted raw component collections. +Previously, both `RecordingStream::log` and `RecordingStream::send_column` were able to +handle raw component collections which then would be serialized to arrow on the fly. -This is no longer the case and only `rerun::ComponentColumn` and anything else from which +#### `log` + +Under the hood we allow any type that implements the `AsComponents` trait. +However, `AsComponents` is no longer implemented for collections of components / implementors of `Loggable`. + +Instead, you're encouraged to use archetypes for cases where you'd previously use loose collections of components. +This is made easier by the fact that archetypes can now be created without specifying required components. +For example, colors of a point cloud can be logged without position data: + +```cpp +rec.log("points", rerun::Points3D().with_colors(colors)); +``` + +Custom implementations of `AsComponents` still work as before. + +#### `send_column` + +Only `rerun::ComponentColumn` and anything else from which a `Collection` can be constructed is accepted. The preferred way to create `rerun::ComponentColumn`s is to use the new `columns` method on archetypes. diff --git a/docs/snippets/all/concepts/different_data_per_timeline.cpp b/docs/snippets/all/concepts/different_data_per_timeline.cpp index 962075fe8af20..97df2084bd1bf 100644 --- a/docs/snippets/all/concepts/different_data_per_timeline.cpp +++ b/docs/snippets/all/concepts/different_data_per_timeline.cpp @@ -13,12 +13,12 @@ int main() { // Log a red color on one timeline. rec.reset_time(); // Clears all set timeline info. rec.set_time_seconds("red timeline", 1.0); - rec.log("points", std::array{rerun::components::Color(0xFF0000FF)}); + rec.log("points", rerun::Points2D::update_fields().with_colors(rerun::Color(0xFF0000FF))); // And a blue color on the other. rec.reset_time(); // Clears all set timeline info. rec.set_time_sequence("blue timeline", 1); - rec.log("points", std::array{rerun::components::Color(0x0000FFFF)}); + rec.log("points", rerun::Points2D::update_fields().with_colors(rerun::Color(0x0000FFFF))); // TODO(#5521): log VisualBounds2D } diff --git a/docs/snippets/all/descriptors/descr_builtin_component.cpp b/docs/snippets/all/descriptors/descr_builtin_component.cpp index bfdeb8ef1c34d..425f7883bc31d 100644 --- a/docs/snippets/all/descriptors/descr_builtin_component.cpp +++ b/docs/snippets/all/descriptors/descr_builtin_component.cpp @@ -4,8 +4,13 @@ int main() { const auto rec = rerun::RecordingStream("rerun_example_descriptors_builtin_component"); rec.spawn().exit_on_failure(); - rerun::Position3D positions[1] = {{1.0f, 2.0f, 3.0f}}; - rec.log_static("data", positions); + rec.log_static( + "data", + rerun::ComponentBatch::from_loggable( + {1.0f, 2.0f, 3.0f}, + rerun::Loggable::Descriptor + ) + ); // The tags are indirectly checked by the Rust version (have a look over there for more info). } diff --git a/docs/snippets/all/descriptors/descr_custom_component.cpp b/docs/snippets/all/descriptors/descr_custom_component.cpp index 00f11492758be..a76b6921fc7c6 100644 --- a/docs/snippets/all/descriptors/descr_custom_component.cpp +++ b/docs/snippets/all/descriptors/descr_custom_component.cpp @@ -28,8 +28,13 @@ int main() { const auto rec = rerun::RecordingStream("rerun_example_descriptors_custom_component"); rec.spawn().exit_on_failure(); - CustomPosition3D positions[1] = {{rerun::components::Position3D{1.0f, 2.0f, 3.0f}}}; - rec.log_static("data", positions); + rec.log_static( + "data", + rerun::ComponentBatch::from_loggable( + {1.0f, 2.0f, 3.0f}, + rerun::Loggable::Descriptor + ) + ); // The tags are indirectly checked by the Rust version (have a look over there for more info). } diff --git a/examples/cpp/incremental_logging/main.cpp b/examples/cpp/incremental_logging/main.cpp index 11b9c60bc1e90..8859ab36e84d5 100644 --- a/examples/cpp/incremental_logging/main.cpp +++ b/examples/cpp/incremental_logging/main.cpp @@ -49,14 +49,10 @@ int main() { rerun::TextDocument(README).with_media_type(rerun::components::MediaType::markdown()) ); - rerun::Collection colors = rerun::Color(255, 0, 0); - rerun::Collection radii = rerun::Radius(0.1f); - // Only log colors and radii once. - rec.set_time_sequence("frame_nr", 0); - rec.log("points", colors, radii); // Logging statically with `RecordingStream::log_static` would also work. - // rec.log_static("points", colors, radii); + rec.set_time_sequence("frame_nr", 0); + rec.log("points", rerun::Points3D().with_colors(rerun::Color(255, 0, 0)).with_radii(0.1f)); std::default_random_engine gen; std::uniform_real_distribution dist_pos(-5.0f, 5.0f); @@ -71,6 +67,6 @@ int main() { std::generate(points.begin(), points.end(), [&] { return rerun::Position3D(dist_pos(gen), dist_pos(gen), dist_pos(gen)); }); - rec.log("points", rerun::Points3D(points)); + rec.log("points", rerun::Points3D::update_fields().with_positions(points)); } } diff --git a/rerun_cpp/src/rerun/as_components.hpp b/rerun_cpp/src/rerun/as_components.hpp index 8caa8d57118d1..d8aaa7a9dd187 100644 --- a/rerun_cpp/src/rerun/as_components.hpp +++ b/rerun_cpp/src/rerun/as_components.hpp @@ -22,81 +22,69 @@ namespace rerun { static_assert( NoAsComponentsFor::value, "AsComponents is not implemented for this type. " - "It is implemented for all built-in archetypes as well as std::vector, std::array, and " - "c-arrays of components. " + "It is implemented for all built-in archetypes as well as invidiual & collections of `rerun::ComponentBatch`." "You can add your own implementation by specializing AsComponents for your type T." ); // TODO(andreas): List methods that the trait should implement. }; + // TODO(andreas): make these return collection? + // TODO(andreas): Now that we no longer rely on `Loggable` trait implementations here, `serialize` is a misnomer. Consider using `operator()` instead. + // Documenting the builtin generic `AsComponents` impls is too much clutter for the doc class overview. /// \cond private - /// `AsComponents` for a Collection of types implementing the `rerun::Loggable` trait. - template - struct AsComponents> { - static_assert( - is_loggable, "The given type does not implement the rerun::Loggable trait." - ); - - static Result> serialize( - const Collection& components + /// `AsComponents` for a `Collection`. + template <> + struct AsComponents> { + static Result> serialize(Collection components ) { - auto batch_result = ComponentBatch::from_loggable(components); - RR_RETURN_NOT_OK(batch_result.error); - - return Result>({std::move(batch_result.value)}); + return Result>(std::move(components).to_vector()); } }; - /// `AsComponents` for a `std::vector` of types implementing the `rerun::Loggable` trait. - template - struct AsComponents> { - static Result> serialize( - const std::vector& components - ) { - return AsComponents>::serialize(components); + /// `AsComponents` for a single `ComponentBatch`. + template <> + struct AsComponents { + static Result> serialize(ComponentBatch components) { + return Result>({std::move(components)}); } }; - /// AsComponents for `std::initializer_list` - template - struct AsComponents> { + /// `AsComponents` for a `Collection` wrapped in a `Result`, forwarding errors for convenience. + template <> + struct AsComponents>> { static Result> serialize( - std::initializer_list components + Result> components ) { - return AsComponents>::serialize(components); + RR_RETURN_NOT_OK(components.error); + return Result>(std::move(components.value).to_vector()); } }; - /// `AsComponents` for an `std::array` of types implementing the `rerun::Loggable` trait. - template - struct AsComponents> { + /// `AsComponents` for a `Collection` individually wrapped in `Result`, forwarding errors for convenience. + template <> + struct AsComponents>> { static Result> serialize( - const std::array& components + Collection> components ) { - return AsComponents>::serialize(components); - } - }; - - /// `AsComponents` for an c-array of types implementing the `rerun::Loggable` trait. - template - struct AsComponents { - static Result> serialize(const TComponent (&components - )[NumInstances]) { - return AsComponents>::serialize(components); + std::vector result; + result.reserve(components.size()); + for (auto& component : components) { + RR_RETURN_NOT_OK(component.error); + result.push_back(std::move(component.value)); + } + return Result>(std::move(result)); } }; - /// `AsComponents` for single indicator components. - template - struct AsComponents> { - static Result> serialize( - const components::IndicatorComponent& indicator - ) { - return AsComponents< - Collection>>::serialize(indicator); + /// `AsComponents` for a single `ComponentBatch` wrapped in a `Result`, forwarding errors for convenience. + template <> + struct AsComponents> { + static Result> serialize(Result components) { + RR_RETURN_NOT_OK(components.error); + return Result>({std::move(components.value)}); } }; diff --git a/rerun_cpp/src/rerun/component_batch.hpp b/rerun_cpp/src/rerun/component_batch.hpp index 6d95a5f159718..3856fe8dc7417 100644 --- a/rerun_cpp/src/rerun/component_batch.hpp +++ b/rerun_cpp/src/rerun/component_batch.hpp @@ -35,14 +35,6 @@ namespace rerun { return from_loggable(Collection(), descriptor); } - /// Creates a new component batch from a collection of component instances. - /// - /// Automatically registers the component type the first time this type is encountered. - template - static Result from_loggable(const rerun::Collection& components) { - return from_loggable(components, Loggable::Descriptor); - } - /// Creates a new component batch from a collection of component instances. /// /// Automatically registers the component type the first time this type is encountered. @@ -89,16 +81,6 @@ namespace rerun { return component_batch; } - /// Creates a new component batch from a single component instance. - /// - /// Automatically registers the component type the first time this type is encountered. - template - static Result from_loggable(const T& component) { - // Collection adapter will automatically borrow for single elements, but let's do this explicitly, avoiding the extra hoop. - const auto collection = Collection::borrow(&component, 1); - return from_loggable(collection); - } - /// Creates a new component batch from a single component instance. /// /// Automatically registers the component type the first time this type is encountered. @@ -111,20 +93,6 @@ namespace rerun { return from_loggable(collection, descriptor); } - /// Creates a new data cell from a single optional component instance. - /// - /// None is represented as a data cell with 0 instances. - /// - /// Automatically registers the component type the first time this type is encountered. - template - static Result from_loggable(const std::optional& component) { - if (component.has_value()) { - return from_loggable(component.value()); - } else { - return from_loggable(Collection()); - } - } - /// Creates a new data cell from a single optional component instance. /// /// None is represented as a data cell with 0 instances. @@ -141,22 +109,6 @@ namespace rerun { } } - /// Creates a new data cell from an optional collection of component instances. - /// - /// None is represented as a data cell with 0 instances. - /// - /// Automatically registers the component type the first time this type is encountered. - template - static Result from_loggable( - const std::optional>& components - ) { - if (components.has_value()) { - return from_loggable(components.value()); - } else { - return from_loggable(Collection()); - } - } - /// Creates a new data cell from an optional collection of component instances. /// /// None is represented as a data cell with 0 instances. diff --git a/rerun_cpp/src/rerun/component_column.hpp b/rerun_cpp/src/rerun/component_column.hpp index 20852f1910f0c..4ddb2a6d70d1d 100644 --- a/rerun_cpp/src/rerun/component_column.hpp +++ b/rerun_cpp/src/rerun/component_column.hpp @@ -25,24 +25,6 @@ namespace rerun { ComponentTypeHandle component_type; public: - /// Creates a new component column from a collection of component instances. - /// - /// Automatically registers the component type the first time this type is encountered. - /// - /// \param components Continuous collection of components which is about to be partitioned. - /// \param lengths The number of components in each run. for `rerun::RecordingStream::send_columns`, - /// this specifies the number of components at each time point. - /// The sum of the lengths must be equal to the number of components in the batch. - template - [[deprecated( - "Use from_loggable_with_lengths(components, lengths, descriptor) (with explicit descriptor) instead" - )]] static Result - from_loggable_with_lengths( - const Collection& components, const Collection& lengths - ) { - return from_loggable_with_lengths(components, lengths, Loggable::Descriptor); - } - /// Creates a new component column from a collection of component instances. /// /// Automatically registers the component type the first time this type is encountered. @@ -55,7 +37,7 @@ namespace rerun { template static Result from_loggable_with_lengths( const Collection& components, const Collection& lengths, - const ComponentDescriptor& descriptor = Loggable::Descriptor + const ComponentDescriptor& descriptor ) { auto component_batch_result = ComponentBatch::from_loggable(components, descriptor); if (component_batch_result.is_err()) { @@ -64,21 +46,6 @@ namespace rerun { return from_batch_with_lengths(component_batch_result.value, lengths); } - /// Creates a new component column from a collection of component instances where each run has a length of one. - /// - /// When used with `rerun::RecordingStream::send_columns`, this is equivalent to `from_loggable(components, std::vector{1, 1, ...})`. - /// I.e. there's a single component for each time point. - /// - /// Automatically registers the component type the first time this type is encountered. - /// - /// \param components Continuous collection of components which is about to be partitioned into runs of length one. - template - [[deprecated("Use from_loggable(components, descriptor) (with explicit descriptor) instead" - )]] static Result - from_loggable(const Collection& components) { - return from_loggable(components, Loggable::Descriptor); - } - /// Creates a new component column from a collection of component instances where each run has a length of one. /// /// When used with `rerun::RecordingStream::send_columns`, this is equivalent to `from_loggable(components, std::vector{1, 1, ...})`. @@ -90,8 +57,7 @@ namespace rerun { /// \param descriptor Descriptor of the component type for this column. template static Result from_loggable( - const Collection& components, - const ComponentDescriptor& descriptor = Loggable::Descriptor + const Collection& components, const ComponentDescriptor& descriptor ) { return ComponentColumn::from_loggable_with_lengths( components, diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index 30293fe296707..b0f0f8ff8f222 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -338,7 +338,7 @@ namespace rerun { /// ``` /// /// The `log` function can flexibly accept an arbitrary number of additional objects which will - /// be merged into the first entity so long as they don't expose conflicting components, for instance: + /// be merged into the first entity, for instance: /// ``` /// // Log three points with arrows sticking out of them: /// rec.log( @@ -349,19 +349,20 @@ namespace rerun { /// ); /// ``` /// - /// Any failures that may occur during serialization are handled with `Error::handle`. + /// Any failures that may are handled with `Error::handle`. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. - /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. + /// \param as_components Any type for which the `AsComponents` trait is implemented. + /// This is the case for any archetype as well as individual or collection of `ComponentBatch`. + /// You can implement `AsComponents` for your own types as well /// /// @see try_log, log_static, try_log_with_static template - void log(std::string_view entity_path, const Ts&... archetypes_or_collections) const { + void log(std::string_view entity_path, const Ts&... as_components) const { if (!is_enabled()) { return; } - try_log_with_static(entity_path, false, archetypes_or_collections...).handle(); + try_log_with_static(entity_path, false, as_components...).handle(); } /// Logs one or more archetype and/or component batches as static data. @@ -373,61 +374,62 @@ namespace rerun { /// Failures are handled with `Error::handle`. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. - /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. + /// \param as_components Any type for which the `AsComponents` trait is implemented. + /// This is the case for any archetype as well as individual or collection of `ComponentBatch`. + /// You can implement `AsComponents` for your own types as well /// /// @see log, try_log_static, try_log_with_static template - void log_static(std::string_view entity_path, const Ts&... archetypes_or_collections) - const { + void log_static(std::string_view entity_path, const Ts&... as_components) const { if (!is_enabled()) { return; } - try_log_with_static(entity_path, true, archetypes_or_collections...).handle(); + try_log_with_static(entity_path, true, as_components...).handle(); } /// Logs one or more archetype and/or component batches. /// /// See `log` for more information. - /// Unlike `log` this method returns an error if an error occurs during serialization or logging. + /// Unlike `log` this method returns an error if an error occurs. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. - /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. + /// \param as_components Any type for which the `AsComponents` trait is implemented. + /// This is the case for any archetype as well as individual or collection of `ComponentBatch`. + /// You can implement `AsComponents` for your own types as well /// /// @see log, try_log_static, try_log_with_static template - Error try_log(std::string_view entity_path, const Ts&... archetypes_or_collections) const { + Error try_log(std::string_view entity_path, const Ts&... as_components) const { if (!is_enabled()) { return Error::ok(); } - return try_log_with_static(entity_path, false, archetypes_or_collections...); + return try_log_with_static(entity_path, false, as_components...); } /// Logs one or more archetype and/or component batches as static data, returning an error. /// /// See `log`/`log_static` for more information. - /// Unlike `log_static` this method returns if an error occurs during serialization or logging. + /// Unlike `log_static` this method returns if an error occurs. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. - /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. - /// \returns An error if an error occurs during serialization or logging. + /// \param as_components Any type for which the `AsComponents` trait is implemented. + /// This is the case for any archetype as well as individual or collection of `ComponentBatch`. + /// You can implement `AsComponents` for your own types as well + /// \returns An error if an error occurs during evaluation of `AsComponents` or logging. /// /// @see log_static, try_log, try_log_with_static template - Error try_log_static(std::string_view entity_path, const Ts&... archetypes_or_collections) - const { + Error try_log_static(std::string_view entity_path, const Ts&... as_components) const { if (!is_enabled()) { return Error::ok(); } - return try_log_with_static(entity_path, true, archetypes_or_collections...); + return try_log_with_static(entity_path, true, as_components...); } /// Logs one or more archetype and/or component batches optionally static, returning an error. /// /// See `log`/`log_static` for more information. - /// Returns an error if an error occurs during serialization or logging. + /// Returns an error if an error occurs during evaluation of `AsComponents` or logging. /// /// \param entity_path Path to the entity in the space hierarchy. /// \param static_ If true, the logged components will be static. @@ -435,21 +437,21 @@ namespace rerun { /// any temporal data of the same type. /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. - /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. - /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. + /// \param as_components Any type for which the `AsComponents` trait is implemented. + /// This is the case for any archetype as well as individual or collection of `ComponentBatch`. + /// You can implement `AsComponents` for your own types as well /// /// @see log, try_log, log_static, try_log_static template - void log_with_static( - std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections - ) const { - try_log_with_static(entity_path, static_, archetypes_or_collections...).handle(); + void log_with_static(std::string_view entity_path, bool static_, const Ts&... as_components) + const { + try_log_with_static(entity_path, static_, as_components...).handle(); } /// Logs one or more archetype and/or component batches optionally static, returning an error. /// /// See `log`/`log_static` for more information. - /// Returns an error if an error occurs during serialization or logging. + /// Returns an error if an error occurs during evaluation of `AsComponents` or logging. /// /// \param entity_path Path to the entity in the space hierarchy. /// \param static_ If true, the logged components will be static. @@ -457,14 +459,15 @@ namespace rerun { /// any temporal data of the same type. /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. - /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. - /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. - /// \returns An error if an error occurs during serialization or logging. + /// \param as_components Any type for which the `AsComponents` trait is implemented. + /// This is the case for any archetype as well as individual or collection of `ComponentBatch`. + /// You can implement `AsComponents` for your own types as well + /// \returns An error if an error occurs during evaluation of `AsComponents` or logging. /// /// @see log, try_log, log_static, try_log_static template Error try_log_with_static( - std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections + std::string_view entity_path, bool static_, const Ts&... as_components ) const { if (!is_enabled()) { return Error::ok(); @@ -478,7 +481,7 @@ namespace rerun { } const Result> serialization_result = - AsComponents().serialize(archetypes_or_collections); + AsComponents().serialize(as_components); if (serialization_result.is_err()) { err = serialization_result.error; return; diff --git a/rerun_cpp/tests/log_empty.cpp b/rerun_cpp/tests/log_empty.cpp index 79a51e6dc8d6e..e202b9bfd8648 100644 --- a/rerun_cpp/tests/log_empty.cpp +++ b/rerun_cpp/tests/log_empty.cpp @@ -15,7 +15,14 @@ SCENARIO("Log empty data", TEST_TAG) { stream.log("empty", rerun::Points3D(std::vector{})); }); } - SECTION("Using an empty component vector") { - check_logged_error([&] { stream.log("empty", std::vector{}); }); + SECTION("Using an empty component batch") { + check_logged_error([&] { + stream.log( + "empty", + rerun::ComponentBatch::empty( + rerun::Loggable::Descriptor + ) + ); + }); } } diff --git a/rerun_cpp/tests/recording_stream.cpp b/rerun_cpp/tests/recording_stream.cpp index c1e77db5ebf58..0cda74b2227f6 100644 --- a/rerun_cpp/tests/recording_stream.cpp +++ b/rerun_cpp/tests/recording_stream.cpp @@ -146,130 +146,82 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE WHEN("creating a new stream") { rerun::RecordingStream stream("test", std::string_view(), kind); - // We can make single components work, but this would make error messages a lot - // worse since we'd have to implement the base `AsComponents` template for this. - // - // THEN("single components can be logged") { - // stream.log( - // "single-components", - // rerun::Position2D{1.0, 2.0}, - // rerun::Color(0x00FF00FF) - // ); - // } - - THEN("components as c-array can be logged") { - rerun::Position2D c_style_array[2] = { - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - }; - - stream.log("as-carray", c_style_array); - stream.log_static("as-carray", c_style_array); - } - THEN("components as std::initializer_list can be logged") { - const auto c_style_array = { - rerun::components::Position2D{1.0, 2.0}, - rerun::components::Position2D{4.0, 5.0}, - }; - stream.log("as-initializer-list", c_style_array); - stream.log_static("as-initializer-list", c_style_array); - } - THEN("components as std::array can be logged") { - stream.log( - "as-array", - std::array{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); - stream.log_static( - "as-array", - std::array{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); + GIVEN("component batches") { + auto batch0 = rerun::ComponentBatch::from_loggable( + {{1.0, 2.0}, {4.0, 5.0}}, + rerun::Loggable::Descriptor + ) + .value_or_throw(); + auto batch1 = rerun::ComponentBatch::from_loggable( + {rerun::Color(0xFF0000FF)}, + rerun::Loggable::Descriptor + ) + .value_or_throw(); + THEN("single component batch can be logged") { + stream.log("log_archetype-splat", batch0); + stream.log_static("log_archetype-splat", batch0); + } + THEN("component batches can be listed out") { + stream.log("log_archetype-splat", batch0, batch1); + stream.log_static("log_archetype-splat", batch0, batch1); + } + THEN("a collection of component batches can be logged") { + rerun::Collection batches = {batch0, batch1}; + stream.log("log_archetype-splat", batches); + stream.log_static("log_archetype-splat", batches); + } } - THEN("components as std::vector can be logged") { - stream.log( - "as-vector", - std::vector{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } + GIVEN("component batches wrapped in `rerun::Result`") { + auto batch0 = rerun::ComponentBatch::from_loggable( + {{1.0, 2.0}, {4.0, 5.0}}, + rerun::Loggable::Descriptor ); - stream.log_static( - "as-vector", - std::vector{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); - } - THEN("several components with a mix of vector, array and c-array can be logged") { - rerun::Text c_style_array[3] = { - rerun::Text("hello"), - rerun::Text("friend"), - rerun::Text("yo"), - }; - stream.log( - "as-mix", - std::vector{ - rerun::Position2D(rerun::Vec2D{0.0, 0.0}), - rerun::Position2D(rerun::Vec2D{1.0, 3.0}), - rerun::Position2D(rerun::Vec2D{5.0, 5.0}), - }, - std::array{ - rerun::Color(0xFF0000FF), - rerun::Color(0x00FF00FF), - rerun::Color(0x0000FFFF), - }, - c_style_array - ); - stream.log_static( - "as-mix", - std::vector{ - rerun::Position2D(rerun::Vec2D{0.0, 0.0}), - rerun::Position2D(rerun::Vec2D{1.0, 3.0}), - rerun::Position2D(rerun::Vec2D{5.0, 5.0}), - }, - std::array{ - rerun::Color(0xFF0000FF), - rerun::Color(0x00FF00FF), - rerun::Color(0x0000FFFF), - }, - c_style_array + auto batch1 = rerun::ComponentBatch::from_loggable( + {rerun::Color(0xFF0000FF)}, + rerun::Loggable::Descriptor ); + THEN("single component batch can be logged") { + stream.log("log_archetype-splat", batch0); + stream.log_static("log_archetype-splat", batch0); + } + THEN("component batches can be listed out") { + stream.log("log_archetype-splat", batch0, batch1); + stream.log_static("log_archetype-splat", batch0, batch1); + } + THEN("collection of component batch results can be logged") { + rerun::Collection> batches = { + batch0, + batch1}; + stream.log("log_archetype-splat", batches); + stream.log_static("log_archetype-splat", batches); + } } - THEN("components with splatting some of them can be logged") { + THEN("an archetype can be logged") { stream.log( - "log-splat", - std::vector{ - rerun::Position2D(rerun::Vec2D{0.0, 0.0}), - rerun::Position2D(rerun::Vec2D{1.0, 3.0}), - }, - std::array{rerun::Color(0xFF0000FF)} + "log_archetype-splat", + rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} + ).with_colors(rerun::Color(0xFF0000FF)) ); stream.log_static( - "log-splat", - std::vector{ - rerun::Position2D(rerun::Vec2D{0.0, 0.0}), - rerun::Position2D(rerun::Vec2D{1.0, 3.0}), - }, - std::array{rerun::Color(0xFF0000FF)} + "log_archetype-splat", + rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} + ).with_colors(rerun::Color(0xFF0000FF)) ); } - - THEN("an archetype can be logged") { + THEN("several archetypes can be logged") { stream.log( "log_archetype-splat", rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} + ).with_colors(rerun::Color(0xFF0000FF)), + rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} ).with_colors(rerun::Color(0xFF0000FF)) ); stream.log_static( "log_archetype-splat", rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} + ).with_colors(rerun::Color(0xFF0000FF)), + rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} ).with_colors(rerun::Color(0xFF0000FF)) ); } @@ -326,23 +278,6 @@ SCENARIO("RecordingStream can log to file", TEST_TAG) { WHEN("saving that one to a different file " << test_rrd1) { REQUIRE(stream1->save(test_rrd1).is_ok()); - WHEN("logging a component to the second stream") { - check_logged_error([&] { - stream1->log( - "as-array", - std::array{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); - }); - - THEN("after destruction, the second stream produced a bigger file") { - stream0.reset(); - stream1.reset(); - CHECK(fs::file_size(test_rrd0) < fs::file_size(test_rrd1)); - } - } WHEN("logging an archetype to the second stream") { check_logged_error([&] { stream1->log( @@ -389,22 +324,6 @@ void test_logging_to_connection(const char* address, const rerun::RecordingStrea THEN("save call with zero timeout returns no error") { REQUIRE(stream.connect_tcp(address, 0.0f).is_ok()); - WHEN("logging a component and then flushing") { - check_logged_error([&] { - stream.log( - "as-array", - std::array{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); - }); - stream.flush_blocking(); - - THEN("does not crash") { - // No easy way to see if it got sent. - } - } WHEN("logging an archetype and then flushing") { check_logged_error([&] { stream.log( @@ -483,42 +402,26 @@ SCENARIO("Recording stream handles serialization failure during logging graceful const char* path = "valid"; auto& expected_error = rerun::Loggable::error; - AND_GIVEN("an component that fails serialization") { + AND_GIVEN("an component batch result that failed serialization") { const auto component = BadComponent(); expected_error.code = GENERATE(rerun::ErrorCode::Unknown, rerun::ErrorCode::ArrowStatusCode_TypeError); - THEN("calling log with an array logs the serialization error") { - check_logged_error( - [&] { - stream.log(path, std::array{component, component}); - }, - expected_error.code - ); + auto batch_result = rerun::ComponentBatch::from_loggable( + component, + rerun::Loggable::Descriptor + ); + + THEN("calling log with that batch logs the serialization error") { + check_logged_error([&] { stream.log(path, batch_result); }, expected_error.code); } - THEN("calling log with a vector logs the serialization error") { + THEN("calling log with a collection wrapping that batch logs the serialization error") { check_logged_error( - [&] { - stream.log(path, std::vector{component, component}); - }, + [&] { stream.log(path, rerun::Collection{batch_result}); }, expected_error.code ); } - THEN("calling log with a c array logs the serialization error") { - const BadComponent components[] = {component, component}; - check_logged_error([&] { stream.log(path, components); }, expected_error.code); - } - THEN("calling try_log with an array forwards the serialization error") { - CHECK(stream.try_log(path, std::array{component, component}) == expected_error); - } - THEN("calling try_log with a vector forwards the serialization error") { - CHECK(stream.try_log(path, std::vector{component, component}) == expected_error); - } - THEN("calling try_log with a c array forwards the serialization error") { - const BadComponent components[] = {component, component}; - CHECK(stream.try_log(path, components) == expected_error); - } } AND_GIVEN("an archetype that fails serialization") { auto archetype = BadArchetype(); @@ -570,88 +473,6 @@ SCENARIO("RecordingStream can set time without errors", TEST_TAG) { } } -// Regression test for https://github.com/rerun-io/cpp-example-opencv-eigen/issues/25 -SCENARIO("Deprecated log_static still works", TEST_TAG) { - rerun::RecordingStream stream("test"); - - // Disable deprecation warnings for this test since this is testing deprecated functionality. - RR_PUSH_WARNINGS - RR_DISABLE_DEPRECATION_WARNING - - GIVEN("a new RecordingStream and valid entity paths") { - THEN("components as std::initializer_list can be logged") { - const auto c_style_array = { - rerun::components::Position2D{1.0, 2.0}, - rerun::components::Position2D{4.0, 5.0}, - }; - stream.log_static("as-initializer-list", c_style_array); - } - - THEN("components as std::array can be logged") { - stream.log_static( - "as-array", - std::array{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); - } - - THEN("components as std::vector can be logged") { - stream.log_static( - "as-vector", - std::vector{ - rerun::Vec2D{1.0, 2.0}, - rerun::Vec2D{4.0, 5.0}, - } - ); - } - - THEN("several components with a mix of vector, array and c-array can be logged") { - rerun::Text c_style_array[3] = { - rerun::Text("hello"), - rerun::Text("friend"), - rerun::Text("yo"), - }; - stream.log_static( - "as-mix", - std::vector{ - rerun::Position2D(rerun::Vec2D{0.0, 0.0}), - rerun::Position2D(rerun::Vec2D{1.0, 3.0}), - rerun::Position2D(rerun::Vec2D{5.0, 5.0}), - }, - std::array{ - rerun::Color(0xFF0000FF), - rerun::Color(0x00FF00FF), - rerun::Color(0x0000FFFF), - }, - c_style_array - ); - } - - THEN("components with splatting some of them can be logged") { - stream.log_static( - "log-splat", - std::vector{ - rerun::Position2D(rerun::Vec2D{0.0, 0.0}), - rerun::Position2D(rerun::Vec2D{1.0, 3.0}), - }, - std::array{rerun::Color(0xFF0000FF)} - ); - } - - THEN("an archetype can be logged") { - stream.log_static( - "log_archetype-splat", - rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} - ).with_colors(rerun::Color(0xFF0000FF)) - ); - } - } - - RR_POP_WARNINGS // For `RR_DISABLE_DEPRECATION_WARNING`. -} - SCENARIO("Global RecordingStream doesn't cause crashes", TEST_TAG) { // This caused a crash on Mac & Linux due to issues with cleanup order of global variables // in Rust vs C++. From 94495bc4de8d6c56077cc6826bba2cb40d758a67 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 30 Jan 2025 10:59:54 +0100 Subject: [PATCH 34/43] Fix cameras with unknown resolution showing (#8856) --- .../re_view_spatial/src/visualizers/cameras.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/viewer/re_view_spatial/src/visualizers/cameras.rs b/crates/viewer/re_view_spatial/src/visualizers/cameras.rs index abd48a18ec2ba..43fd34cbb4fee 100644 --- a/crates/viewer/re_view_spatial/src/visualizers/cameras.rs +++ b/crates/viewer/re_view_spatial/src/visualizers/cameras.rs @@ -60,6 +60,14 @@ impl CamerasVisualizer { pinhole_properties: &CameraComponentDataWithFallbacks, entity_highlight: &ViewOutlineMasks, ) { + // Check for valid resolution. + let w = pinhole_properties.pinhole.resolution.x; + let h = pinhole_properties.pinhole.resolution.y; + let z = pinhole_properties.image_plane_distance; + if !w.is_finite() || !h.is_finite() || w <= 0.0 || h <= 0.0 { + return; + } + let instance = Instance::from(0); let ent_path = &data_result.entity_path; @@ -112,10 +120,6 @@ impl CamerasVisualizer { }); // Setup a RDF frustum (for non-RDF we apply a transformation matrix later). - let w = pinhole_properties.pinhole.resolution.x; - let h = pinhole_properties.pinhole.resolution.y; - let z = pinhole_properties.image_plane_distance; - let corners = [ pinhole_properties.pinhole.unproject(vec3(0.0, 0.0, z)), pinhole_properties.pinhole.unproject(vec3(0.0, h, z)), @@ -331,7 +335,10 @@ impl TypedComponentFallbackProvider for CamerasVisualize // If the Pinhole has no resolution, use the resolution for the image logged at the same path. // See https://github.com/rerun-io/rerun/issues/3852 resolution_of_image_at(ctx.viewer_ctx, ctx.query, ctx.target_entity_path) - .unwrap_or(components::Resolution::from([100.0, 100.0])) + // Zero will be seen as invalid resolution by the visualizer, making it opt out of visualization. + // TODO(andreas): We should display a warning about this somewhere. + // Since it's not a required component, logging a warning about this might be too noisy. + .unwrap_or(components::Resolution::from([0.0, 0.0])) } } From 6c534b2b6d3e1d7a86336ba37042b99f611acc6a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 30 Jan 2025 11:11:51 +0100 Subject: [PATCH 35/43] Run codegen (#8868) Fix main --- rerun_cpp/src/rerun/archetypes/arrows3d.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp index 6f6b888c12773..e258e863e8eae 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp @@ -49,7 +49,7 @@ namespace rerun::archetypes { /// origins.push_back({0, 0, 0}); /// /// float angle = TAU * static_cast(i) * 0.01f; - /// float length = log2f(static_cast(i + 1)); + /// float length = static_cast(log2(i + 1)); /// vectors.push_back({length * sinf(angle), 0.0, length * cosf(angle)}); /// /// uint8_t c = static_cast(round(angle / TAU * 255.0f)); From 9cba2de82eea58657f2b968995f0c2023a331446 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 30 Jan 2025 11:27:44 +0100 Subject: [PATCH 36/43] Show start of large arrow values instead of just their size (#8861) This changes the arrow_ui to always show the actual contents of the data, and never to show the summary of "10.2 MiB of data". The reasons are two-fold: * A) The size estimation was wrong, so we would show the wrong size, and too often * B) It is probably nicer to se the contents of the data instead, even if we can only fit the start of it because it is too long (see screenshot test in PR diff) ## Worries Formatting a huge arrow array as a string may be slow. This is difficult to see in practice, because we special-treat the display of `Blob` in the UI anyways. ## Other changes I also changed nulls to be explicitly formatted as the string `null`. Before they were omitted. --- .gitignore | 1 + ..._query__tests__async_barebones_static.snap | 2 +- ...uery__tests__async_barebones_temporal.snap | 10 ++-- ..._dataframe__query__tests__barebones-2.snap | 10 ++-- ...re_dataframe__query__tests__barebones.snap | 2 +- .../re_dataframe__query__tests__clears-2.snap | 8 +-- .../re_dataframe__query__tests__clears.snap | 8 +-- ...e__query__tests__filtered_index_range.snap | 6 +- ...__query__tests__filtered_index_values.snap | 4 +- ..._query__tests__filtered_is_not_null-3.snap | 10 ++-- ..._query__tests__filtered_is_not_null-4.snap | 4 +- ..._dataframe__query__tests__selection-2.snap | 14 ++--- ..._dataframe__query__tests__selection-3.snap | 14 ++--- ...__sparse_fill_strategy_latestatglobal.snap | 10 ++-- ...e__query__tests__using_index_values-2.snap | 10 ++-- ...ame__query__tests__using_index_values.snap | 14 ++--- ...aframe__query__tests__view_contents-2.snap | 8 +-- ...y__tests__view_contents_and_selection.snap | 8 +-- crates/store/re_format_arrow/src/lib.rs | 2 +- .../VisibleTimeRange_placeholder.png | 4 +- crates/viewer/re_ui/src/arrow_ui.rs | 57 +++++++------------ .../viewer/re_ui/tests/snapshots/arrow_ui.png | 4 +- 22 files changed, 99 insertions(+), 111 deletions(-) diff --git a/.gitignore b/.gitignore index 112556bde8793..6feb525db4736 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ wheels /compare_screenshot **/tests/snapshots/**/*.diff.png **/tests/snapshots/**/*.new.png +**/tests/snapshots/**/*.old.png # Mesa install mesa diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap index bb980973fc58b..db957933033a9 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_static.snap @@ -15,6 +15,6 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ ┆ ┆ ┆ [c] ┆ │ │ +│ │ null ┆ null ┆ null ┆ [c] ┆ null │ │ │ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap index c55b7a8f8b262..7ce18178b1a08 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__async_barebones_temporal.snap @@ -15,17 +15,17 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ │ 20 ┆ null ┆ null ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ null ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ │ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap index c55b7a8f8b262..7ce18178b1a08 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones-2.snap @@ -15,17 +15,17 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ │ 20 ┆ null ┆ null ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ null ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ │ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap index bb980973fc58b..db957933033a9 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__barebones.snap @@ -15,6 +15,6 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ ┆ ┆ ┆ [c] ┆ │ │ +│ │ null ┆ null ┆ null ┆ [c] ┆ null │ │ │ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap index 4093744288f98..99889208a5c1c 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears-2.snap @@ -15,13 +15,13 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ │ 20 ┆ null ┆ null ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap index 4093744288f98..99889208a5c1c 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__clears.snap @@ -15,13 +15,13 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ │ 20 ┆ null ┆ null ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap index 84a2766f38778..b1b085b65851a 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_range.snap @@ -15,12 +15,12 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ null ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap index 10b1dd43ba8d9..14ff3c194dd9f 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_index_values.snap @@ -15,8 +15,8 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ null ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap index c55b7a8f8b262..7ce18178b1a08 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-3.snap @@ -15,17 +15,17 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ │ 20 ┆ null ┆ null ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ null ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ │ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap index aaf0bdc4b57de..f764102f654c5 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__filtered_is_not_null-4.snap @@ -15,9 +15,9 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap index d83074ad4d03c..fc9abb00c5691 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-2.snap @@ -13,18 +13,18 @@ expression: "TransportChunk::from(dataframe)" │ │ index_name: "frame_nr" ┆ index_name: "frame_nr" ┆ index_name: "ATimeColumnThatDoesntExist" │ │ │ │ kind: "index" ┆ kind: "index" ┆ kind: "index" │ │ │ ╞════════════════════════╪════════════════════════╪══════════════════════════════════════════╡ │ -│ │ 10 ┆ 10 ┆ │ │ +│ │ 10 ┆ 10 ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ 20 ┆ │ │ +│ │ 20 ┆ 20 ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ 30 ┆ │ │ +│ │ 30 ┆ 30 ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ 40 ┆ │ │ +│ │ 40 ┆ 40 ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ 50 ┆ │ │ +│ │ 50 ┆ 50 ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ 60 ┆ │ │ +│ │ 60 ┆ 60 ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ 70 ┆ │ │ +│ │ 70 ┆ 70 ┆ null │ │ │ └────────────────────────┴────────────────────────┴──────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap index 9cf62759e3e93..13ed97d7001c0 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__selection-3.snap @@ -14,18 +14,18 @@ expression: "TransportChunk::from(dataframe)" │ │ entity_path: "/this/that" ┆ entity_path: "/this/that" ┆ entity_path: "/non_existing_entity" ┆ entity_path: "/this/that" │ │ │ │ kind: "data" ┆ kind: "data" ┆ kind: "data" ┆ kind: "data" │ │ │ ╞══════════════════════════════╪══════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════════════╡ │ -│ │ ┆ ┆ ┆ │ │ +│ │ null ┆ null ┆ null ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ ┆ ┆ ┆ │ │ +│ │ null ┆ null ┆ null ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [2] ┆ [2] ┆ ┆ │ │ +│ │ [2] ┆ [2] ┆ null ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [3] ┆ [3] ┆ ┆ │ │ +│ │ [3] ┆ [3] ┆ null ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [4] ┆ [4] ┆ ┆ │ │ +│ │ [4] ┆ [4] ┆ null ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ ┆ ┆ ┆ │ │ +│ │ null ┆ null ┆ null ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ [6] ┆ [6] ┆ ┆ │ │ +│ │ [6] ┆ [6] ┆ null ┆ null │ │ │ └──────────────────────────────┴──────────────────────────────┴──────────────────────────────────────┴──────────────────────────────────────────────┘ │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap index 5383fd1d8095a..611b3867fcb07 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__sparse_fill_strategy_latestatglobal.snap @@ -15,17 +15,17 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 10 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 20 ┆ ┆ ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ +│ │ 20 ┆ null ┆ null ┆ [c] ┆ [{x: 1.0, y: 1.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 50 ┆ 1970-01-01T00:00:00.000000050 ┆ [4] ┆ [c] ┆ [{x: 4.0, y: 4.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 70 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ │ └────────────────────────┴───────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap index 981fa36654b7f..0c0c7ebc3a624 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values-2.snap @@ -15,15 +15,15 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪═══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 0 ┆ ┆ ┆ [c] ┆ │ │ +│ │ 0 ┆ null ┆ null ┆ [c] ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 15 ┆ 1970-01-01T00:00:00.000000010 ┆ ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ +│ │ 15 ┆ 1970-01-01T00:00:00.000000010 ┆ null ┆ [c] ┆ [{x: 0.0, y: 0.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 45 ┆ ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ +│ │ 45 ┆ null ┆ [3] ┆ [c] ┆ [{x: 3.0, y: 3.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ [4] ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ 75 ┆ 1970-01-01T00:00:00.000000070 ┆ [6] ┆ [c] ┆ [{x: 8.0, y: 8.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap index ae5ccead81146..bad2cb956e13a 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__using_index_values.snap @@ -15,18 +15,18 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" ┆ kind: "data" │ │ │ │ ┆ ┆ ┆ kind: "data" ┆ │ │ │ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 0 ┆ ┆ ┆ [c] ┆ │ │ +│ │ 0 ┆ null ┆ null ┆ [c] ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 15 ┆ ┆ ┆ [c] ┆ │ │ +│ │ 15 ┆ null ┆ null ┆ [c] ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 30 ┆ ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] ┆ [{x: 2.0, y: 2.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 45 ┆ ┆ ┆ [c] ┆ │ │ +│ │ 45 ┆ null ┆ null ┆ [c] ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 60 ┆ ┆ ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ +│ │ 60 ┆ null ┆ null ┆ [c] ┆ [{x: 5.0, y: 5.0}] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 75 ┆ ┆ ┆ [c] ┆ │ │ +│ │ 75 ┆ null ┆ null ┆ [c] ┆ null │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 90 ┆ ┆ ┆ [c] ┆ │ │ +│ │ 90 ┆ null ┆ null ┆ [c] ┆ null │ │ │ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap index b57174058daa5..a81573d92315f 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents-2.snap @@ -15,12 +15,12 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ kind: "data" ┆ is_static: "yes" │ │ │ │ ┆ ┆ ┆ kind: "data" │ │ │ ╞════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 30 ┆ ┆ [2] ┆ [c] │ │ +│ │ 30 ┆ null ┆ [2] ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ [3] ┆ [c] │ │ +│ │ 40 ┆ null ┆ [3] ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ ┆ [4] ┆ [c] │ │ +│ │ 50 ┆ null ┆ [4] ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ ┆ [6] ┆ [c] │ │ +│ │ 70 ┆ null ┆ [6] ┆ [c] │ │ │ └────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap index e86684ead8103..88cb601328a11 100644 --- a/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap +++ b/crates/store/re_dataframe/src/snapshots/re_dataframe__query__tests__view_contents_and_selection.snap @@ -15,12 +15,12 @@ expression: "TransportChunk::from(dataframe)" │ │ ┆ ┆ ┆ kind: "data" ┆ kind: "data" ┆ is_static: "yes" │ │ │ │ ┆ ┆ ┆ ┆ ┆ kind: "data" │ │ │ ╞════════════════════════╪════════════════════════╪════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╡ │ -│ │ 30 ┆ ┆ ┆ ┆ [2] ┆ [c] │ │ +│ │ 30 ┆ null ┆ null ┆ null ┆ [2] ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 40 ┆ ┆ ┆ ┆ [3] ┆ [c] │ │ +│ │ 40 ┆ null ┆ null ┆ null ┆ [3] ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 50 ┆ ┆ ┆ ┆ [4] ┆ [c] │ │ +│ │ 50 ┆ null ┆ null ┆ null ┆ [4] ┆ [c] │ │ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ -│ │ 70 ┆ ┆ ┆ ┆ [6] ┆ [c] │ │ +│ │ 70 ┆ null ┆ null ┆ null ┆ [6] ┆ [c] │ │ │ └────────────────────────┴────────────────────────┴────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘ │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/crates/store/re_format_arrow/src/lib.rs b/crates/store/re_format_arrow/src/lib.rs index f9b80c626275c..fb1abac13af30 100644 --- a/crates/store/re_format_arrow/src/lib.rs +++ b/crates/store/re_format_arrow/src/lib.rs @@ -41,7 +41,7 @@ fn custom_array_formatter<'a>(field: &Field, array: &'a dyn Array) -> CustomArra } } - match ArrayFormatter::try_new(array, &FormatOptions::default()) { + match ArrayFormatter::try_new(array, &FormatOptions::default().with_null("null")) { Ok(formatter) => Box::new(move |index| Ok(format!("{}", formatter.value(index)))), Err(err) => Box::new(move |_| Err(format!("Failed to format array: {err}"))), } diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/VisibleTimeRange_placeholder.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/VisibleTimeRange_placeholder.png index eddfedd06d7da..01b694b721d66 100644 --- a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/VisibleTimeRange_placeholder.png +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/VisibleTimeRange_placeholder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88ebbe375f988780cc1fd0fa25131246fea60f162bf20c4dee4f65b33e0efa46 -size 11610 +oid sha256:766c8bb910fe5b72c1c89123501faad8ac3a1a0a09ffc114e2859a184c63c8a3 +size 11398 diff --git a/crates/viewer/re_ui/src/arrow_ui.rs b/crates/viewer/re_ui/src/arrow_ui.rs index 19088f0277f16..f30a4cfdd8239 100644 --- a/crates/viewer/re_ui/src/arrow_ui.rs +++ b/crates/viewer/re_ui/src/arrow_ui.rs @@ -6,6 +6,8 @@ use re_arrow_util::ArrowArrayDowncastRef as _; use crate::UiLayout; pub fn arrow_ui(ui: &mut egui::Ui, ui_layout: UiLayout, array: &dyn arrow::array::Array) { + re_tracing::profile_function!(); + use arrow::array::{LargeStringArray, StringArray}; ui.scope(|ui| { @@ -33,46 +35,31 @@ pub fn arrow_ui(ui: &mut egui::Ui, ui_layout: UiLayout, array: &dyn arrow::array } } - let num_bytes = array.get_buffer_memory_size(); - if num_bytes < 3_000 { - let instance_count = array.len(); + let instance_count = array.len(); - let options = FormatOptions::default(); - if let Ok(formatter) = ArrayFormatter::try_new(array, &options) { - if instance_count == 1 { - ui.monospace(formatter.value(0).to_string()); - return; - } else { - let response = ui_layout.label(ui, format!("{instance_count} items")); + let options = FormatOptions::default() + .with_null("null") + .with_display_error(true); + if let Ok(formatter) = ArrayFormatter::try_new(array, &options) { + if instance_count == 1 { + ui.monospace(formatter.value(0).to_string()); + } else { + let response = ui_layout.label(ui, format!("{instance_count} items")); - if instance_count < 100 { - response.on_hover_ui(|ui| { - ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap); - ui.monospace(format!( - "[{}]", - (0..instance_count) - .map(|index| formatter.value(index).to_string()) - .join(", ") - )); - }); - } + if instance_count < 100 { + response.on_hover_ui(|ui| { + ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap); + ui.monospace(format!( + "[{}]", + (0..instance_count) + .map(|index| formatter.value(index).to_string()) + .join(", ") + )); + }); } } - return; - } - - // Fallback: - let bytes = re_format::format_bytes(num_bytes as _); - - // TODO(emilk): pretty-print data type - let data_type_formatted = format!("{:?}", array.data_type()); - - if data_type_formatted.len() < 20 { - // e.g. "4.2 KiB of Float32" - ui_layout.label(ui, format!("{bytes} of {data_type_formatted}")); } else { - // Huge datatype, probably a union horror show - ui_layout.label(ui, format!("{bytes} of data")); + // This is unreachable because we use `.with_display_error(true)` above. } }); } diff --git a/crates/viewer/re_ui/tests/snapshots/arrow_ui.png b/crates/viewer/re_ui/tests/snapshots/arrow_ui.png index 12e6a41fd256d..f8e5187d444c1 100644 --- a/crates/viewer/re_ui/tests/snapshots/arrow_ui.png +++ b/crates/viewer/re_ui/tests/snapshots/arrow_ui.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f43ff3f9d5398d8b4d82b809508bbcd5964efb40dc95ca21f36a5aa5eefd1f8 -size 22125 +oid sha256:22de0f2e8d65a8a1b689aba0e543219e801b8b894f653ad0df0e46387dadf0a9 +size 32520 From 0cc13eb7e22abdc0b506cd0c22d7fd31af7dcbf7 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:35:08 +0100 Subject: [PATCH 37/43] Make it possible to change the contents of a view multiple times per frame (#8854) --- .../re_selection_panel/src/selection_panel.rs | 9 +- .../src/view_entity_picker.rs | 2 +- .../viewer/re_viewport_blueprint/src/view.rs | 2 +- .../src/view_contents.rs | 129 ++++++++++-------- .../src/viewport_blueprint.rs | 4 +- 5 files changed, 84 insertions(+), 62 deletions(-) diff --git a/crates/viewer/re_selection_panel/src/selection_panel.rs b/crates/viewer/re_selection_panel/src/selection_panel.rs index 7222ccda832bb..ff4940c914da2 100644 --- a/crates/viewer/re_selection_panel/src/selection_panel.rs +++ b/crates/viewer/re_selection_panel/src/selection_panel.rs @@ -7,7 +7,7 @@ use re_data_ui::{ DataUi, }; use re_entity_db::{EntityPath, InstancePath}; -use re_log_types::{ComponentPath, EntityPathFilter, ResolvedEntityPathFilter}; +use re_log_types::{ComponentPath, EntityPathFilter, EntityPathSubs, ResolvedEntityPathFilter}; use re_types::blueprint::components::Interactive; use re_ui::{ icons, @@ -383,11 +383,12 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included. ctx, ui, *view_id, - &view.contents.entity_path_filter, + view.contents.entity_path_filter(), &view.space_origin, ) { - view.contents - .set_entity_path_filter(ctx, &new_entity_path_filter); + let path_subs = EntityPathSubs::new_with_origin(&view.space_origin); + let query_filter = new_entity_path_filter.resolve_forgiving(&path_subs); + view.contents.set_entity_path_filter(ctx, query_filter); } }) .header_response diff --git a/crates/viewer/re_selection_panel/src/view_entity_picker.rs b/crates/viewer/re_selection_panel/src/view_entity_picker.rs index 65cebadc678dd..89b98e24e05ca 100644 --- a/crates/viewer/re_selection_panel/src/view_entity_picker.rs +++ b/crates/viewer/re_selection_panel/src/view_entity_picker.rs @@ -62,7 +62,7 @@ fn add_entities_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, view: &ViewBluepr let tree = &ctx.recording().tree(); let query_result = ctx.lookup_query_result(view.id); - let entity_path_filter = &view.contents.entity_path_filter; + let entity_path_filter = view.contents.entity_path_filter(); let entities_add_info = create_entity_add_info(ctx, tree, view, query_result); list_item::list_item_scope(ui, "view_entity_picker", |ui| { diff --git a/crates/viewer/re_viewport_blueprint/src/view.rs b/crates/viewer/re_viewport_blueprint/src/view.rs index 84e14ca6c4a4f..53ee80b87714c 100644 --- a/crates/viewer/re_viewport_blueprint/src/view.rs +++ b/crates/viewer/re_viewport_blueprint/src/view.rs @@ -287,7 +287,7 @@ impl ViewBlueprint { let contents = ViewContents::new( new_id, self.class_identifier, - self.contents.entity_path_filter.clone(), + self.contents.entity_path_filter().clone(), ); Self { diff --git a/crates/viewer/re_viewport_blueprint/src/view_contents.rs b/crates/viewer/re_viewport_blueprint/src/view_contents.rs index 45e50be78a20b..7a1ffa6675a6c 100644 --- a/crates/viewer/re_viewport_blueprint/src/view_contents.rs +++ b/crates/viewer/re_viewport_blueprint/src/view_contents.rs @@ -1,4 +1,7 @@ +use std::sync::Arc; + use nohash_hasher::{IntMap, IntSet}; +use parking_lot::Mutex; use re_log_types::{ResolvedEntityPathFilter, ResolvedEntityPathRule}; use slotmap::SlotMap; use smallvec::SmallVec; @@ -37,8 +40,17 @@ use crate::{ViewBlueprint, ViewProperty}; pub struct ViewContents { pub blueprint_entity_path: EntityPath, - pub view_class_identifier: ViewClassIdentifier, - pub entity_path_filter: ResolvedEntityPathFilter, + view_class_identifier: ViewClassIdentifier, + + /// Deserialized entity path filter. + /// + /// Consider this read-only. + entity_path_filter: ResolvedEntityPathFilter, + + /// Update entity path filter. + /// + /// Mutations go to this value and should be saved to the blueprint store when they occur. + new_entity_path_filter: Arc>, } impl ViewContents { @@ -83,10 +95,13 @@ impl ViewContents { blueprint_archetypes::ViewContents::name().short_name(), )); + let new_entity_path_filter = Arc::new(Mutex::new(entity_path_filter.clone())); + Self { blueprint_entity_path, view_class_identifier, entity_path_filter, + new_entity_path_filter, } } @@ -120,10 +135,13 @@ impl ViewContents { let entity_path_filter = EntityPathFilter::from_query_expressions(query).resolve_forgiving(subst_env); + let new_entity_path_filter = Arc::new(Mutex::new(entity_path_filter.clone())); + Self { blueprint_entity_path: property.blueprint_store_path, view_class_identifier, entity_path_filter, + new_entity_path_filter, } } @@ -137,30 +155,15 @@ impl ViewContents { ctx.save_blueprint_archetype( &self.blueprint_entity_path, &blueprint_archetypes::ViewContents::new( - self.entity_path_filter.iter_unresolved_expressions(), + self.new_entity_path_filter + .lock() + .iter_unresolved_expressions(), ), ); } - /// Set the entity path filter. WARNING: a single mutation is allowed per frame, or data will be - /// lost. - //TODO(#8518): address this massive foot-gun. - pub fn set_entity_path_filter( - &self, - ctx: &ViewerContext<'_>, - new_entity_path_filter: &EntityPathFilter, - ) { - if &self.entity_path_filter.unresolved() == new_entity_path_filter { - return; - } - - ctx.save_blueprint_component( - &self.blueprint_entity_path, - &new_entity_path_filter - .iter_expressions() - .map(|s| QueryExpression(s.into())) - .collect::>(), - ); + pub fn entity_path_filter(&self) -> &ResolvedEntityPathFilter { + &self.entity_path_filter } pub fn build_resolver<'a>( @@ -187,69 +190,87 @@ impl ViewContents { } } - /// Perform arbitrary mutation on the entity path filter. WARNING: a single mutation is allowed - /// per frame, or data will be lost. + /// Sets the entity path filter to the provided one. + pub fn set_entity_path_filter( + &self, + ctx: &ViewerContext<'_>, + entity_path_filter: ResolvedEntityPathFilter, + ) { + *self.new_entity_path_filter.lock() = entity_path_filter; + self.save_entity_path_filter_to_blueprint(ctx); + } + + /// Perform arbitrary mutation on the entity path filter. /// - /// This method exists because of the single mutation per frame limitation. It currently is the - /// only way to perform multiple mutations on the entity path filter in a single frame. - //TODO(#8518): address this massive foot-gun. + /// Using this method avoids triggering multiple writes to the blueprint store. pub fn mutate_entity_path_filter( &self, ctx: &ViewerContext<'_>, f: impl FnOnce(&mut ResolvedEntityPathFilter), ) { - let mut new_entity_path_filter = self.entity_path_filter.clone(); - f(&mut new_entity_path_filter); - self.set_entity_path_filter(ctx, &new_entity_path_filter.unresolved()); + f(&mut self.new_entity_path_filter.lock()); + self.save_entity_path_filter_to_blueprint(ctx); } - /// Remove a subtree and any existing rules that it would match. WARNING: a single mutation is - /// allowed per frame, or data will be lost. + /// Remove a subtree and any existing rules that it would match. /// /// Because most-specific matches win, if we only add a subtree exclusion /// it can still be overridden by existing inclusions. This method ensures /// that not only do we add a subtree exclusion, but clear out any existing /// inclusions or (now redundant) exclusions that would match the subtree. - //TODO(#8518): address this massive foot-gun. pub fn remove_subtree_and_matching_rules(&self, ctx: &ViewerContext<'_>, path: EntityPath) { - let mut new_entity_path_filter = self.entity_path_filter.clone(); - new_entity_path_filter.remove_subtree_and_matching_rules(path); - self.set_entity_path_filter(ctx, &new_entity_path_filter.unresolved()); + self.new_entity_path_filter + .lock() + .remove_subtree_and_matching_rules(path); + + self.save_entity_path_filter_to_blueprint(ctx); } - /// Directly add an exclusion rule to the [`EntityPathFilter`]. WARNING: a single mutation is - /// allowed per frame, or data will be lost. + /// Directly add an exclusion rule to the [`EntityPathFilter`]. /// /// This is a direct modification of the filter and will not do any simplification /// related to overlapping or conflicting rules. /// /// If you are trying to remove an entire subtree, prefer using [`Self::remove_subtree_and_matching_rules`]. - //TODO(#8518): address this massive foot-gun. pub fn raw_add_entity_exclusion(&self, ctx: &ViewerContext<'_>, rule: ResolvedEntityPathRule) { - let mut new_entity_path_filter = self.entity_path_filter.clone(); - new_entity_path_filter.add_rule(RuleEffect::Exclude, rule); - self.set_entity_path_filter(ctx, &new_entity_path_filter.unresolved()); + self.new_entity_path_filter + .lock() + .add_rule(RuleEffect::Exclude, rule); + + self.save_entity_path_filter_to_blueprint(ctx); } - /// Directly add an inclusion rule to the [`EntityPathFilter`]. WARNING: a single mutation is - /// allowed per frame, or data will be lost. + /// Directly add an inclusion rule to the [`EntityPathFilter`]. /// /// This is a direct modification of the filter and will not do any simplification /// related to overlapping or conflicting rules. - //TODO(#8518): address this massive foot-gun. pub fn raw_add_entity_inclusion(&self, ctx: &ViewerContext<'_>, rule: ResolvedEntityPathRule) { - let mut new_entity_path_filter = self.entity_path_filter.clone(); - new_entity_path_filter.add_rule(RuleEffect::Include, rule); - self.set_entity_path_filter(ctx, &new_entity_path_filter.unresolved()); + self.new_entity_path_filter + .lock() + .add_rule(RuleEffect::Include, rule); + + self.save_entity_path_filter_to_blueprint(ctx); } - /// Remove rules for a given entity. WARNING: a single mutation is allowed per frame, or data - /// will be lost. - //TODO(#8518): address this massive foot-gun. + /// Remove rules for a given entity. pub fn remove_filter_rule_for(&self, ctx: &ViewerContext<'_>, ent_path: &EntityPath) { - let mut new_entity_path_filter = self.entity_path_filter.clone(); - new_entity_path_filter.remove_rule_for(ent_path); - self.set_entity_path_filter(ctx, &new_entity_path_filter.unresolved()); + self.new_entity_path_filter.lock().remove_rule_for(ent_path); + + self.save_entity_path_filter_to_blueprint(ctx); + } + + /// Save the entity path filter. + fn save_entity_path_filter_to_blueprint(&self, ctx: &ViewerContext<'_>) { + ctx.save_blueprint_component( + &self.blueprint_entity_path, + &self + .new_entity_path_filter + .lock() + .unresolved() + .iter_expressions() + .map(|s| QueryExpression(s.into())) + .collect::>(), + ); } /// Build up the initial [`DataQueryResult`] for this [`ViewContents`] diff --git a/crates/viewer/re_viewport_blueprint/src/viewport_blueprint.rs b/crates/viewer/re_viewport_blueprint/src/viewport_blueprint.rs index e95bb97ffdd78..793c4a7d5020c 100644 --- a/crates/viewer/re_viewport_blueprint/src/viewport_blueprint.rs +++ b/crates/viewer/re_viewport_blueprint/src/viewport_blueprint.rs @@ -268,7 +268,7 @@ impl ViewportBlueprint { || entity_path.is_descendant_of(&view.space_origin) || view .contents - .entity_path_filter + .entity_path_filter() .matches(&instance_path.entity_path) }) } @@ -359,7 +359,7 @@ impl ViewportBlueprint { .views .values() .filter(|view| view.class_identifier() == class_id) - .map(|view| &view.contents.entity_path_filter) + .map(|view| view.contents.entity_path_filter()) .collect::>(); recommended_views.retain(|(query_filter, _)| { existing_path_filters From 89d3df011d34f689c1b479f4c25ffbfb574c4be0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 30 Jan 2025 12:22:39 +0100 Subject: [PATCH 38/43] Polish manual tagged APIs (#8869) * python how has `described` for component batches * C++ can infer descriptor for explicit component batch/column creation * some snippet niceifications for Rust --------- Co-authored-by: Clement Rey --- .../descriptors/descr_builtin_component.cpp | 5 +---- .../descriptors/descr_builtin_component.py | 6 +++++- .../descriptors/descr_builtin_component.rs | 5 ++--- .../descriptors/descr_custom_archetype.cpp | 8 ++++---- .../all/descriptors/descr_custom_archetype.rs | 2 +- rerun_cpp/src/rerun/component_batch.hpp | 12 +++++++---- rerun_cpp/src/rerun/component_column.hpp | 5 +++-- rerun_cpp/tests/recording_stream.cpp | 20 ++++++------------- rerun_py/rerun_sdk/rerun/_baseclasses.py | 6 ++++++ 9 files changed, 36 insertions(+), 33 deletions(-) diff --git a/docs/snippets/all/descriptors/descr_builtin_component.cpp b/docs/snippets/all/descriptors/descr_builtin_component.cpp index 425f7883bc31d..22b3feb15c043 100644 --- a/docs/snippets/all/descriptors/descr_builtin_component.cpp +++ b/docs/snippets/all/descriptors/descr_builtin_component.cpp @@ -6,10 +6,7 @@ int main() { rec.log_static( "data", - rerun::ComponentBatch::from_loggable( - {1.0f, 2.0f, 3.0f}, - rerun::Loggable::Descriptor - ) + rerun::ComponentBatch::from_loggable(rerun::Position3D(1.0f, 2.0f, 3.0f)) ); // The tags are indirectly checked by the Rust version (have a look over there for more info). diff --git a/docs/snippets/all/descriptors/descr_builtin_component.py b/docs/snippets/all/descriptors/descr_builtin_component.py index 7b206526066ec..c811d7e11e474 100644 --- a/docs/snippets/all/descriptors/descr_builtin_component.py +++ b/docs/snippets/all/descriptors/descr_builtin_component.py @@ -7,6 +7,10 @@ rr.init("rerun_example_descriptors_builtin_component") rr.spawn() -rr.log("data", [rr.components.Position3DBatch([1, 2, 3])], static=True) +rr.log( + "data", + [rr.components.Position3DBatch([1, 2, 3]).described()], + static=True, +) # The tags are indirectly checked by the Rust version (have a look over there for more info). diff --git a/docs/snippets/all/descriptors/descr_builtin_component.rs b/docs/snippets/all/descriptors/descr_builtin_component.rs index dfb391127036a..8b6a3bb0dc214 100644 --- a/docs/snippets/all/descriptors/descr_builtin_component.rs +++ b/docs/snippets/all/descriptors/descr_builtin_component.rs @@ -2,10 +2,9 @@ use rerun::{ChunkStore, ChunkStoreConfig, Component as _, ComponentDescriptor, V fn example(rec: &rerun::RecordingStream) -> Result<(), Box> { use rerun::ComponentBatch as _; - rec.log_serialized_batches( + rec.log_static( "data", - true, - [rerun::components::Position3D::new(1.0, 2.0, 3.0).try_serialized()?], + &[rerun::components::Position3D::new(1.0, 2.0, 3.0).try_serialized()?], )?; Ok(()) diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.cpp b/docs/snippets/all/descriptors/descr_custom_archetype.cpp index a9043b1da4eca..c60fd6183bf98 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.cpp +++ b/docs/snippets/all/descriptors/descr_custom_archetype.cpp @@ -59,10 +59,10 @@ int main() { const auto rec = rerun::RecordingStream("rerun_example_descriptors_custom_archetype"); rec.spawn().exit_on_failure(); - CustomPosition3D positions[1] = {{rerun::components::Position3D{1.0f, 2.0f, 3.0f}}}; - rerun::Color colors[1] = {rerun::Color(0xFF00FFFF)}; - - rec.log_static("data", CustomPoints3D{positions, colors}); + rec.log_static( + "data", + CustomPoints3D{CustomPosition3D{{1.0f, 2.0f, 3.0f}}, rerun::Color(0xFF00FFFF)} + ); // The tags are indirectly checked by the Rust version (have a look over there for more info). } diff --git a/docs/snippets/all/descriptors/descr_custom_archetype.rs b/docs/snippets/all/descriptors/descr_custom_archetype.rs index a4ecd1790b707..54a8fb11860bd 100644 --- a/docs/snippets/all/descriptors/descr_custom_archetype.rs +++ b/docs/snippets/all/descriptors/descr_custom_archetype.rs @@ -47,7 +47,7 @@ fn example(rec: &rerun::RecordingStream) -> Result<(), Box static Result from_loggable( - const rerun::Collection& components, const ComponentDescriptor& descriptor + const rerun::Collection& components, + const ComponentDescriptor& descriptor = rerun::Loggable::Descriptor + ) { static_assert( rerun::is_loggable, @@ -86,7 +88,8 @@ namespace rerun { /// Automatically registers the component type the first time this type is encountered. template static Result from_loggable( - const T& component, const ComponentDescriptor& descriptor + const T& component, + const ComponentDescriptor& descriptor = rerun::Loggable::Descriptor ) { // Collection adapter will automatically borrow for single elements, but let's do this explicitly, avoiding the extra hoop. const auto collection = Collection::borrow(&component, 1); @@ -100,7 +103,8 @@ namespace rerun { /// Automatically registers the component type the first time this type is encountered. template static Result from_loggable( - const std::optional& component, const ComponentDescriptor& descriptor + const std::optional& component, + const ComponentDescriptor& descriptor = rerun::Loggable::Descriptor ) { if (component.has_value()) { return from_loggable(component.value(), descriptor); @@ -117,7 +121,7 @@ namespace rerun { template static Result from_loggable( const std::optional>& components, - const ComponentDescriptor& descriptor + const ComponentDescriptor& descriptor = rerun::Loggable::Descriptor ) { if (components.has_value()) { return from_loggable(components.value(), descriptor); diff --git a/rerun_cpp/src/rerun/component_column.hpp b/rerun_cpp/src/rerun/component_column.hpp index 4ddb2a6d70d1d..307c66f3adfb1 100644 --- a/rerun_cpp/src/rerun/component_column.hpp +++ b/rerun_cpp/src/rerun/component_column.hpp @@ -37,7 +37,7 @@ namespace rerun { template static Result from_loggable_with_lengths( const Collection& components, const Collection& lengths, - const ComponentDescriptor& descriptor + const ComponentDescriptor& descriptor = rerun::Loggable::Descriptor ) { auto component_batch_result = ComponentBatch::from_loggable(components, descriptor); if (component_batch_result.is_err()) { @@ -57,7 +57,8 @@ namespace rerun { /// \param descriptor Descriptor of the component type for this column. template static Result from_loggable( - const Collection& components, const ComponentDescriptor& descriptor + const Collection& components, + const ComponentDescriptor& descriptor = rerun::Loggable::Descriptor ) { return ComponentColumn::from_loggable_with_lengths( components, diff --git a/rerun_cpp/tests/recording_stream.cpp b/rerun_cpp/tests/recording_stream.cpp index 0cda74b2227f6..b8497e1583bee 100644 --- a/rerun_cpp/tests/recording_stream.cpp +++ b/rerun_cpp/tests/recording_stream.cpp @@ -148,13 +148,10 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE GIVEN("component batches") { auto batch0 = rerun::ComponentBatch::from_loggable( - {{1.0, 2.0}, {4.0, 5.0}}, - rerun::Loggable::Descriptor - ) - .value_or_throw(); + {{1.0, 2.0}, {4.0, 5.0}} + ).value_or_throw(); auto batch1 = rerun::ComponentBatch::from_loggable( - {rerun::Color(0xFF0000FF)}, - rerun::Loggable::Descriptor + {rerun::Color(0xFF0000FF)} ) .value_or_throw(); THEN("single component batch can be logged") { @@ -173,12 +170,10 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE } GIVEN("component batches wrapped in `rerun::Result`") { auto batch0 = rerun::ComponentBatch::from_loggable( - {{1.0, 2.0}, {4.0, 5.0}}, - rerun::Loggable::Descriptor + {{1.0, 2.0}, {4.0, 5.0}} ); auto batch1 = rerun::ComponentBatch::from_loggable( - {rerun::Color(0xFF0000FF)}, - rerun::Loggable::Descriptor + {rerun::Color(0xFF0000FF)} ); THEN("single component batch can be logged") { stream.log("log_archetype-splat", batch0); @@ -408,10 +403,7 @@ SCENARIO("Recording stream handles serialization failure during logging graceful expected_error.code = GENERATE(rerun::ErrorCode::Unknown, rerun::ErrorCode::ArrowStatusCode_TypeError); - auto batch_result = rerun::ComponentBatch::from_loggable( - component, - rerun::Loggable::Descriptor - ); + auto batch_result = rerun::ComponentBatch::from_loggable(component); THEN("calling log with that batch logs the serialization error") { check_logged_error([&] { stream.log(path, batch_result); }, expected_error.code); diff --git a/rerun_py/rerun_sdk/rerun/_baseclasses.py b/rerun_py/rerun_sdk/rerun/_baseclasses.py index de07020e73958..891b3f75bd40e 100644 --- a/rerun_py/rerun_sdk/rerun/_baseclasses.py +++ b/rerun_py/rerun_sdk/rerun/_baseclasses.py @@ -491,6 +491,12 @@ def component_descriptor(self) -> ComponentDescriptor: """ return self._COMPONENT_DESCRIPTOR # type: ignore[attr-defined, no-any-return] + def described(self, descriptor: ComponentDescriptor | None = None) -> DescribedComponentBatch: + """Wraps the current `ComponentBatchLike` in a `DescribedComponentBatch` with the given descriptor or, if None, the component's descriptor.""" + if descriptor is None: + descriptor = self.component_descriptor() + return DescribedComponentBatch(self, descriptor) + def with_descriptor(self, descriptor: ComponentDescriptor) -> DescribedComponentBatch: """Wraps the current `ComponentBatchLike` in a `DescribedComponentBatch` with the given descriptor.""" return DescribedComponentBatch(self, descriptor) From f51085f063571b50a776d8dba3be1d0a5b50e4ca Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:28:42 +0100 Subject: [PATCH 39/43] Implement range selection with shift-click in the blueprint tree (#8852) --- .../re_blueprint_tree/src/blueprint_tree.rs | 279 ++++++++++++++---- crates/viewer/re_blueprint_tree/src/data.rs | 119 +++++++- .../re_viewer_context/src/collapsed_id.rs | 18 +- crates/viewer/re_viewer_context/src/lib.rs | 2 + .../re_viewer_context/src/viewer_context.rs | 14 +- .../src/visitor_flow_control.rs | 30 ++ 6 files changed, 402 insertions(+), 60 deletions(-) create mode 100644 crates/viewer/re_viewer_context/src/visitor_flow_control.rs diff --git a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs index 36bc26934d3af..62d9705d492e9 100644 --- a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs +++ b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs @@ -12,12 +12,13 @@ use re_ui::{ use re_viewer_context::{ contents_name_style, icon_for_container_kind, CollapseScope, ContainerId, Contents, DragAndDropFeedback, DragAndDropPayload, HoverHighlight, Item, ItemContext, - SystemCommandSender, ViewId, ViewerContext, + SystemCommandSender, ViewId, ViewerContext, VisitorControlFlow, }; use re_viewport_blueprint::{ui::show_add_view_or_container_modal, ViewportBlueprint}; -use crate::data::BlueprintTreeData; -use crate::data::{ContainerData, ContentsData, DataResultData, DataResultKind, ViewData}; +use crate::data::{ + BlueprintTreeData, ContainerData, ContentsData, DataResultData, DataResultKind, ViewData, +}; /// Holds the state of the blueprint tree UI. #[derive(Default)] @@ -48,6 +49,12 @@ pub struct BlueprintTree { /// Used to invalidate the filter state (aka deactivate it) when the user switches to a /// recording with a different application id. filter_state_app_id: Option, + + /// Range selection anchor item. + /// + /// This is the item we used as a starting point for range selection. It is set and remembered + /// everytime the user clicks on an item _without_ holding shift. + range_selection_anchor_item: Option, } impl BlueprintTree { @@ -135,8 +142,14 @@ impl BlueprintTree { }); list_item::list_item_scope(ui, "blueprint tree", |ui| { - if let Some(root_container) = blueprint_tree_data.root_container { - self.root_container_ui(ctx, viewport_blueprint, ui, &root_container); + if let Some(root_container) = &blueprint_tree_data.root_container { + self.root_container_ui( + ctx, + viewport_blueprint, + &blueprint_tree_data, + ui, + root_container, + ); } }); @@ -167,6 +180,7 @@ impl BlueprintTree { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + blueprint_tree_data: &BlueprintTreeData, ui: &mut egui::Ui, container_data: &ContainerData, ) { @@ -189,22 +203,24 @@ impl BlueprintTree { ); for child in &container_data.children { - self.contents_ui(ctx, viewport_blueprint, ui, child, true); + self.contents_ui( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + child, + true, + ); } - context_menu_ui_for_item_with_context( + self.handle_interactions_for_item( ctx, viewport_blueprint, - &item, - // expand/collapse context menu actions need this information - ItemContext::BlueprintTree { - filter_session_id: self.filter_state.session_id(), - }, + blueprint_tree_data, + ui, + item, &item_response, - SelectionUpdateBehavior::UseSelection, ); - self.scroll_to_me_if_needed(ui, &item, &item_response); - ctx.handle_select_hover_drag_interactions(&item_response, item, true); self.handle_root_container_drag_and_drop_interaction( ctx, @@ -219,16 +235,31 @@ impl BlueprintTree { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + blueprint_tree_data: &BlueprintTreeData, ui: &mut egui::Ui, contents_data: &ContentsData, parent_visible: bool, ) { match contents_data { ContentsData::Container(container_data) => { - self.container_ui(ctx, viewport_blueprint, ui, container_data, parent_visible); + self.container_ui( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + container_data, + parent_visible, + ); } ContentsData::View(view_data) => { - self.view_ui(ctx, viewport_blueprint, ui, view_data, parent_visible); + self.view_ui( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + view_data, + parent_visible, + ); } }; } @@ -236,7 +267,8 @@ impl BlueprintTree { fn container_ui( &mut self, ctx: &ViewerContext<'_>, - viewport: &ViewportBlueprint, + viewport_blueprint: &ViewportBlueprint, + blueprint_tree_data: &BlueprintTreeData, ui: &mut egui::Ui, container_data: &ContainerData, parent_visible: bool, @@ -256,8 +288,8 @@ impl BlueprintTree { let remove_response = remove_button_ui(ui, "Remove container"); if remove_response.clicked() { - viewport.mark_user_interaction(ctx); - viewport.remove_contents(content); + viewport_blueprint.mark_user_interaction(ctx); + viewport_blueprint.remove_contents(content); } remove_response | vis_response @@ -284,32 +316,33 @@ impl BlueprintTree { item_content, |ui| { for child in &container_data.children { - self.contents_ui(ctx, viewport, ui, child, container_visible); + self.contents_ui( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + child, + container_visible, + ); } }, ); + viewport_blueprint.set_content_visibility(ctx, &content, visible); let response = response.on_hover_text(format!("{:?} container", container_data.kind)); - context_menu_ui_for_item_with_context( + self.handle_interactions_for_item( ctx, - viewport, - &item, - // expand/collapse context menu actions need this information - ItemContext::BlueprintTree { - filter_session_id: self.filter_state.session_id(), - }, + viewport_blueprint, + blueprint_tree_data, + ui, + item, &response, - SelectionUpdateBehavior::UseSelection, ); - self.scroll_to_me_if_needed(ui, &item, &response); - ctx.handle_select_hover_drag_interactions(&response, item, true); - - viewport.set_content_visibility(ctx, &content, visible); self.handle_drag_and_drop_interaction( ctx, - viewport, + viewport_blueprint, ui, content, &response, @@ -321,6 +354,7 @@ impl BlueprintTree { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + blueprint_tree_data: &BlueprintTreeData, ui: &mut egui::Ui, view_data: &ViewData, container_visible: bool, @@ -371,6 +405,7 @@ impl BlueprintTree { self.data_result_ui( ctx, viewport_blueprint, + blueprint_tree_data, ui, data_result_data, view_visible, @@ -387,7 +422,14 @@ impl BlueprintTree { ); for projection in &view_data.projection_trees { - self.data_result_ui(ctx, viewport_blueprint, ui, projection, view_visible); + self.data_result_ui( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + projection, + view_visible, + ); } } }); @@ -398,23 +440,18 @@ impl BlueprintTree { viewport_blueprint.focus_tab(view_data.id); } - context_menu_ui_for_item_with_context( + let content = Contents::View(view_data.id); + viewport_blueprint.set_content_visibility(ctx, &content, visible); + + self.handle_interactions_for_item( ctx, viewport_blueprint, - &item, - // expand/collapse context menu actions need this information - ItemContext::BlueprintTree { - filter_session_id: self.filter_state.session_id(), - }, + blueprint_tree_data, + ui, + item, &response, - SelectionUpdateBehavior::UseSelection, ); - self.scroll_to_me_if_needed(ui, &item, &response); - ctx.handle_select_hover_drag_interactions(&response, item, true); - - let content = Contents::View(view_data.id); - viewport_blueprint.set_content_visibility(ctx, &content, visible); self.handle_drag_and_drop_interaction( ctx, viewport_blueprint, @@ -427,9 +464,10 @@ impl BlueprintTree { #[allow(clippy::too_many_arguments)] fn data_result_ui( - &self, + &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + blueprint_tree_data: &BlueprintTreeData, ui: &mut egui::Ui, data_result_data: &DataResultData, view_visible: bool, @@ -537,7 +575,14 @@ impl BlueprintTree { item_content, |ui| { for child in &data_result_data.children { - self.data_result_ui(ctx, viewport_blueprint, ui, child, view_visible); + self.data_result_ui( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + child, + view_visible, + ); } }, ) @@ -568,6 +613,28 @@ impl BlueprintTree { } }); + self.handle_interactions_for_item( + ctx, + viewport_blueprint, + blueprint_tree_data, + ui, + item, + &response, + ); + } + + // ---------------------------------------------------------------------------- + // item interactions + + fn handle_interactions_for_item( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + blueprint_tree_data: &BlueprintTreeData, + ui: &egui::Ui, + item: Item, + response: &Response, + ) { context_menu_ui_for_item_with_context( ctx, viewport_blueprint, @@ -576,11 +643,117 @@ impl BlueprintTree { ItemContext::BlueprintTree { filter_session_id: self.filter_state.session_id(), }, - &response, + response, SelectionUpdateBehavior::UseSelection, ); - self.scroll_to_me_if_needed(ui, &item, &response); - ctx.handle_select_hover_drag_interactions(&response, item, true); + self.scroll_to_me_if_needed(ui, &item, response); + ctx.handle_select_hover_drag_interactions(response, item.clone(), true); + + self.handle_range_selection(ctx, blueprint_tree_data, item, response); + } + + /// Handle setting/extending the selection based on shift-clicking. + fn handle_range_selection( + &mut self, + ctx: &ViewerContext<'_>, + blueprint_tree_data: &BlueprintTreeData, + item: Item, + response: &Response, + ) { + // Early out if we're not being clicked. + if !response.clicked() { + return; + } + + let modifiers = ctx.egui_ctx.input(|i| i.modifiers); + + if modifiers.shift { + if let Some(anchor_item) = &self.range_selection_anchor_item { + let items_in_range = Self::items_in_range( + ctx, + blueprint_tree_data, + self.collapse_scope(), + anchor_item, + &item, + ); + + if items_in_range.is_empty() { + // This can happen if the last clicked item became invisible due to collapsing, or if + // the user switched to another recording. In either case, we invalidate it. + self.range_selection_anchor_item = None; + } else { + let items_iterator = items_in_range.into_iter().map(|item| { + ( + item, + Some(ItemContext::BlueprintTree { + filter_session_id: self.filter_state.session_id(), + }), + ) + }); + + if modifiers.command { + ctx.selection_state.extend_selection(items_iterator); + } else { + ctx.selection_state.set_selection(items_iterator); + } + } + } + } else { + self.range_selection_anchor_item = Some(item); + } + } + + /// Selects a range of items in the blueprint tree. + /// + /// This method selects all [`Item`]s displayed between the provided shift-clicked item and the + /// existing last-clicked item (if any). It takes into account the collapsed state, so only + /// actually visible items may be selected. + fn items_in_range( + ctx: &ViewerContext<'_>, + blueprint_tree_data: &BlueprintTreeData, + collapse_scope: CollapseScope, + anchor_item: &Item, + shift_clicked_item: &Item, + ) -> Vec { + let mut items_in_range = vec![]; + let mut found_anchor_item = false; + let mut found_shift_clicked_items = false; + + blueprint_tree_data.visit(|blueprint_tree_item| { + let item = blueprint_tree_item.item(); + + if &item == anchor_item { + found_anchor_item = true; + } + + if &item == shift_clicked_item { + found_shift_clicked_items = true; + } + + if found_anchor_item || found_shift_clicked_items { + items_in_range.push(item); + } + + if found_anchor_item && found_shift_clicked_items { + return VisitorControlFlow::Break(()); + } + + let is_expanded = blueprint_tree_item + .is_open(ctx.egui_ctx, collapse_scope) + .unwrap_or(false); + + if is_expanded { + VisitorControlFlow::Continue + } else { + VisitorControlFlow::SkipBranch + } + }); + + if !found_anchor_item || !found_shift_clicked_items { + vec![] + } else { + items_in_range + } } /// Check if the provided item should be scrolled to. @@ -596,7 +769,7 @@ impl BlueprintTree { } // ---------------------------------------------------------------------------- - // drag and drop support + // view/container drag and drop support fn handle_root_container_drag_and_drop_interaction( &mut self, diff --git a/crates/viewer/re_blueprint_tree/src/data.rs b/crates/viewer/re_blueprint_tree/src/data.rs index 63c5a36f0b623..86449bb86d2e5 100644 --- a/crates/viewer/re_blueprint_tree/src/data.rs +++ b/crates/viewer/re_blueprint_tree/src/data.rs @@ -8,7 +8,7 @@ //! to the overall cost of having large blueprint trees (a.k.a the many-entities performance //! issues: ). -use std::ops::Range; +use std::ops::{ControlFlow, Range}; use itertools::Itertools; use smallvec::SmallVec; @@ -19,7 +19,8 @@ use re_log_types::{EntityPath, EntityPathPart}; use re_types::blueprint::components::Visible; use re_ui::filter_widget::FilterMatcher; use re_viewer_context::{ - ContainerId, Contents, ContentsName, DataQueryResult, DataResultNode, ViewId, ViewerContext, + CollapseScope, ContainerId, Contents, ContentsName, DataQueryResult, DataResultNode, Item, + ViewId, ViewerContext, VisitorControlFlow, }; use re_viewport_blueprint::{ContainerBlueprint, ViewBlueprint, ViewportBlueprint}; @@ -53,6 +54,17 @@ impl BlueprintTreeData { }), } } + + pub fn visit( + &self, + mut visitor: impl FnMut(BlueprintTreeItem<'_>) -> VisitorControlFlow, + ) -> ControlFlow { + if let Some(root_container) = &self.root_container { + root_container.visit(&mut visitor) + } else { + ControlFlow::Continue(()) + } + } } // --- @@ -65,6 +77,18 @@ pub enum ContentsData { View(ViewData), } +impl ContentsData { + pub fn visit( + &self, + visitor: &mut impl FnMut(BlueprintTreeItem<'_>) -> VisitorControlFlow, + ) -> ControlFlow { + match &self { + Self::Container(container_data) => container_data.visit(visitor), + Self::View(view_data) => view_data.visit(visitor), + } + } +} + /// Data related to a single container and its children. #[derive(Debug)] #[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] @@ -131,6 +155,23 @@ impl ContainerData { children, }) } + + pub fn visit( + &self, + visitor: &mut impl FnMut(BlueprintTreeItem<'_>) -> VisitorControlFlow, + ) -> ControlFlow { + if visitor(BlueprintTreeItem::Container(self)).visit_children()? { + for child in &self.children { + child.visit(visitor)?; + } + } + + ControlFlow::Continue(()) + } + + pub fn item(&self) -> Item { + Item::Container(self.id) + } } // --- @@ -255,6 +296,27 @@ impl ViewData { projection_trees, }) } + + pub fn visit( + &self, + visitor: &mut impl FnMut(BlueprintTreeItem<'_>) -> VisitorControlFlow, + ) -> ControlFlow { + if visitor(BlueprintTreeItem::View(self)).visit_children()? { + if let Some(origin_tree) = &self.origin_tree { + origin_tree.visit(visitor)?; + } + + for projection_tree in &self.projection_trees { + projection_tree.visit(visitor)?; + } + } + + ControlFlow::Continue(()) + } + + pub fn item(&self) -> Item { + Item::View(self.id) + } } // --- @@ -471,6 +533,23 @@ impl DataResultData { result } + pub fn visit( + &self, + visitor: &mut impl FnMut(BlueprintTreeItem<'_>) -> VisitorControlFlow, + ) -> ControlFlow { + if visitor(BlueprintTreeItem::DataResult(self)).visit_children()? { + for child in &self.children { + child.visit(visitor)?; + } + } + + ControlFlow::Continue(()) + } + + pub fn item(&self) -> Item { + Item::DataResult(self.view_id, self.instance_path()) + } + pub fn instance_path(&self) -> InstancePath { self.entity_path.clone().into() } @@ -507,3 +586,39 @@ impl DataResultData { fn default_open_for_data_result(num_children: usize) -> bool { 2 <= num_children && num_children <= 3 } + +// --- + +/// Wrapper structure used for the closure of [`BlueprintTreeData::visit`] and friends. +#[derive(Debug, Clone, Copy)] +pub enum BlueprintTreeItem<'a> { + Container(&'a ContainerData), + View(&'a ViewData), + DataResult(&'a DataResultData), +} + +impl BlueprintTreeItem<'_> { + pub fn item(&self) -> Item { + match self { + BlueprintTreeItem::Container(container_data) => container_data.item(), + BlueprintTreeItem::View(view_data) => view_data.item(), + BlueprintTreeItem::DataResult(data_result_data) => data_result_data.item(), + } + } + + pub fn default_open(&self) -> bool { + match self { + BlueprintTreeItem::Container(container_data) => container_data.default_open, + BlueprintTreeItem::View(view_data) => view_data.default_open, + BlueprintTreeItem::DataResult(data_result_data) => data_result_data.default_open, + } + } + + pub fn is_open(&self, ctx: &egui::Context, collapse_scope: CollapseScope) -> Option { + collapse_scope.item(self.item()).map(|collapse_id| { + collapse_id + .is_open(ctx) + .unwrap_or_else(|| self.default_open()) + }) + } +} diff --git a/crates/viewer/re_viewer_context/src/collapsed_id.rs b/crates/viewer/re_viewer_context/src/collapsed_id.rs index 3471c1532926f..7001cc5704be3 100644 --- a/crates/viewer/re_viewer_context/src/collapsed_id.rs +++ b/crates/viewer/re_viewer_context/src/collapsed_id.rs @@ -5,7 +5,7 @@ use std::hash::Hash; use re_log_types::EntityPath; -use crate::{ContainerId, ViewId}; +use crate::{ContainerId, Item, ViewId}; /// The various scopes for which we want to track collapsed state. #[derive(Debug, Clone, Copy, Hash)] @@ -35,6 +35,22 @@ impl CollapseScope { // convenience functions + /// Create a [`CollapsedId`] for an [`Item`] of supported kind. + pub fn item(self, item: Item) -> Option { + match item { + Item::InstancePath(instance_path) => Some(self.entity(instance_path.entity_path)), + Item::Container(container_id) => Some(self.container(container_id)), + Item::View(view_id) => Some(self.view(view_id)), + Item::DataResult(view_id, instance_path) => { + Some(self.data_result(view_id, instance_path.entity_path)) + } + + Item::AppId(_) | Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) => { + None + } + } + } + /// Create a [`CollapsedId`] for a container in this scope. pub fn container(self, container_id: ContainerId) -> CollapsedId { CollapsedId { diff --git a/crates/viewer/re_viewer_context/src/lib.rs b/crates/viewer/re_viewer_context/src/lib.rs index c45f189f6b26e..62709a4078649 100644 --- a/crates/viewer/re_viewer_context/src/lib.rs +++ b/crates/viewer/re_viewer_context/src/lib.rs @@ -36,6 +36,7 @@ pub mod test_context; // TODO(andreas): Move to its own crate? pub mod gpu_bridge; +mod visitor_flow_control; pub use self::{ annotations::{AnnotationMap, Annotations, ResolvedAnnotationInfo, ResolvedAnnotationInfos}, @@ -87,6 +88,7 @@ pub use self::{ VisualizableFilterContext, VisualizerCollection, VisualizerQueryInfo, VisualizerSystem, }, viewer_context::{RecordingConfig, ViewerContext}, + visitor_flow_control::VisitorControlFlow, }; pub use re_ui::UiLayout; // Historical reasons diff --git a/crates/viewer/re_viewer_context/src/viewer_context.rs b/crates/viewer/re_viewer_context/src/viewer_context.rs index b7359189926d5..8d92d94f09cf3 100644 --- a/crates/viewer/re_viewer_context/src/viewer_context.rs +++ b/crates/viewer/re_viewer_context/src/viewer_context.rs @@ -209,10 +209,16 @@ impl ViewerContext<'_> { } } - if response.ctx.input(|i| i.modifiers.command) { - selection_state.toggle_selection(interacted_items); - } else { - selection_state.set_selection(interacted_items); + let modifiers = response.ctx.input(|i| i.modifiers); + + // Shift-clicking means extending the selection. This generally requires local context, + // so we don't handle it here. + if !modifiers.shift { + if modifiers.command { + selection_state.toggle_selection(interacted_items); + } else { + selection_state.set_selection(interacted_items); + } } } } diff --git a/crates/viewer/re_viewer_context/src/visitor_flow_control.rs b/crates/viewer/re_viewer_context/src/visitor_flow_control.rs new file mode 100644 index 0000000000000..5d8b5602f1096 --- /dev/null +++ b/crates/viewer/re_viewer_context/src/visitor_flow_control.rs @@ -0,0 +1,30 @@ +//! Companion to [`std::ops::ControlFlow`] useful to implement visitor patterns. + +use std::ops::ControlFlow; + +/// Type to be returned by visitor closure to control the tree traversal flow. +pub enum VisitorControlFlow { + /// Continue tree traversal + Continue, + + /// Continue tree traversal but skip the children of the current item. + SkipBranch, + + /// Stop traversal and return this value. + Break(B), +} + +impl VisitorControlFlow { + /// Indicates whether we should visit the children of the current node—or entirely stop + /// traversal. + /// + /// Returning a [`ControlFlow`] enables key ergonomics by allowing the use of the short circuit + /// operator (`?`) while extracting the flag to control traversal of children. + pub fn visit_children(self) -> ControlFlow { + match self { + Self::Break(val) => ControlFlow::Break(val), + Self::Continue => ControlFlow::Continue(true), + Self::SkipBranch => ControlFlow::Continue(false), + } + } +} From ceafc8780e800de36dd43b538415284ce4b2e941 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:58:11 +0100 Subject: [PATCH 40/43] Filter entities in the UI (part 7): Refactor and optimize `re_time_panel` and add more tests (#8863) --- Cargo.lock | 1 + crates/viewer/re_data_ui/src/item_ui.rs | 3 +- crates/viewer/re_time_panel/Cargo.toml | 1 + .../re_time_panel/src/data_density_graph.rs | 11 +- crates/viewer/re_time_panel/src/lib.rs | 314 ++++++++---------- .../re_time_panel/src/streams_tree_data.rs | 152 +++++++++ crates/viewer/re_time_panel/src/time_axis.rs | 3 + .../time_panel_filter_test_active_query.png | 4 +- .../various_entity_kinds_timeline_a_0.png | 3 + .../various_entity_kinds_timeline_a_5.png | 3 + ...y_kinds_timeline_a_9223372036854775807.png | 3 + .../various_entity_kinds_timeline_b_0.png | 3 + .../various_entity_kinds_timeline_b_5.png | 3 + ...y_kinds_timeline_b_9223372036854775807.png | 3 + .../re_time_panel/tests/time_panel_tests.rs | 244 ++++++++++---- .../re_viewer_context/src/viewer_context.rs | 2 - 16 files changed, 493 insertions(+), 260 deletions(-) create mode 100644 crates/viewer/re_time_panel/src/streams_tree_data.rs create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_0.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_5.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_9223372036854775807.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_0.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_5.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_9223372036854775807.png diff --git a/Cargo.lock b/Cargo.lock index 68944fa4819db..581a3f74b78e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6570,6 +6570,7 @@ dependencies = [ "re_viewer_context", "re_viewport_blueprint", "serde", + "smallvec", "vec1", ] diff --git a/crates/viewer/re_data_ui/src/item_ui.rs b/crates/viewer/re_data_ui/src/item_ui.rs index 1005e60fb5aeb..3654b95578c10 100644 --- a/crates/viewer/re_data_ui/src/item_ui.rs +++ b/crates/viewer/re_data_ui/src/item_ui.rs @@ -185,8 +185,7 @@ pub fn instance_path_icon( if db .storage_engine() .store() - .all_components_on_timeline(timeline, &instance_path.entity_path) - .is_some() + .entity_has_data_on_timeline(timeline, &instance_path.entity_path) { &icons::ENTITY } else { diff --git a/crates/viewer/re_time_panel/Cargo.toml b/crates/viewer/re_time_panel/Cargo.toml index 626c8fa8b575a..efa8d2341ac03 100644 --- a/crates/viewer/re_time_panel/Cargo.toml +++ b/crates/viewer/re_time_panel/Cargo.toml @@ -38,6 +38,7 @@ itertools.workspace = true nohash-hasher.workspace = true once_cell.workspace = true serde.workspace = true +smallvec.workspace = true vec1.workspace = true [dev-dependencies] diff --git a/crates/viewer/re_time_panel/src/data_density_graph.rs b/crates/viewer/re_time_panel/src/data_density_graph.rs index ccdcfc9ebd35d..6c8f539665bd2 100644 --- a/crates/viewer/re_time_panel/src/data_density_graph.rs +++ b/crates/viewer/re_time_panel/src/data_density_graph.rs @@ -3,7 +3,6 @@ //! The data density is the number of data points per unit of time. //! We collect this into a histogram, blur it, and then paint it. -use std::ops::RangeInclusive; use std::sync::Arc; use egui::emath::Rangef; @@ -211,7 +210,6 @@ impl DensityGraph { y_range: Rangef, painter: &egui::Painter, full_color: Color32, - hovered_x_range: RangeInclusive, ) { re_tracing::profile_function!(); @@ -270,11 +268,8 @@ impl DensityGraph { let inner_radius = (max_radius * normalized_density).at_least(MIN_RADIUS) - feather_radius; - let inner_color = if hovered_x_range.contains(&x) { - Color32::WHITE - } else { - full_color.gamma_multiply(lerp(0.5..=1.0, normalized_density)) - }; + let inner_color = full_color.gamma_multiply(lerp(0.5..=1.0, normalized_density)); + (inner_radius, inner_color) }; let outer_radius = inner_radius + feather_radius; @@ -417,8 +412,6 @@ pub fn data_density_graph_ui( row_rect.y_range(), time_area_painter, graph_color(ctx, &item.to_item(), ui), - // TODO(jprochazk): completely remove `hovered_x_range` and associated code from painter - 0f32..=0f32, ); if tooltips_enabled { diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 69a110f676ad6..9227bce26426d 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -3,12 +3,10 @@ //! This crate provides a panel that shows all entities in the store and allows control of time and //! timelines, as well as all necessary ui elements that make it up. -// TODO(#6330): remove unwrap() -#![expect(clippy::unwrap_used)] - mod data_density_graph; mod paint_ticks; mod recursive_chunks_per_timeline_subscriber; +mod streams_tree_data; mod time_axis; mod time_control_ui; mod time_ranges_ui; @@ -24,12 +22,13 @@ use re_context_menu::{ }; use re_data_ui::DataUi as _; use re_data_ui::{item_ui::guess_instance_path_icon, sorted_component_list_for_ui}; -use re_entity_db::{EntityDb, EntityTree, InstancePath}; +use re_entity_db::{EntityDb, InstancePath}; use re_log_types::{ external::re_types_core::ComponentName, ApplicationId, ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, TimeReal, TimeType, }; use re_types::blueprint::components::PanelState; +use re_ui::filter_widget::format_matching_text; use re_ui::{filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _}; use re_viewer_context::{ CollapseScope, HoverHighlight, Item, ItemContext, RecordingConfig, TimeControl, TimeView, @@ -37,6 +36,7 @@ use re_viewer_context::{ }; use re_viewport_blueprint::ViewportBlueprint; +use crate::streams_tree_data::EntityData; use recursive_chunks_per_timeline_subscriber::PathRecursiveChunksPerTimelineStoreSubscriber; use time_axis::TimelineAxis; use time_control_ui::TimeControlUi; @@ -88,7 +88,7 @@ impl TimePanelItem { } } -#[derive(Clone, Copy, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)] enum TimePanelSource { #[default] Recording, @@ -620,44 +620,33 @@ impl TimePanel { ui.scroll_with_delta(Vec2::Y * time_area_response.drag_delta().y); } - // Show "/" on top only for recording streams, because the `/` entity in blueprint - // is always empty, so it's just lost space. This works around an issue where the - // selection/hover state of the `/` entity is wrongly synchronized between both - // stores, due to `Item::*` not tracking stores for entity paths. - let show_root = self.source == TimePanelSource::Recording; - let filter_matcher = self.filter_state.filter(); - if show_root { - self.show_tree( + let entity_tree_data = + crate::streams_tree_data::StreamsTreeData::from_source_and_filter( ctx, - viewport_blueprint, - entity_db, - time_ctrl, - time_area_response, - time_area_painter, - entity_db.tree(), + self.source, &filter_matcher, - ui, ); - } else { - self.show_children( + + for child in &entity_tree_data.children { + self.show_entity( ctx, viewport_blueprint, entity_db, time_ctrl, time_area_response, time_area_painter, - entity_db.tree(), - &filter_matcher, + child, ui, ); } }); } + /// Display the list item for an entity. #[expect(clippy::too_many_arguments)] - fn show_tree( + fn show_entity( &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, @@ -665,68 +654,13 @@ impl TimePanel { time_ctrl: &mut TimeControl, time_area_response: &egui::Response, time_area_painter: &egui::Painter, - tree: &EntityTree, - filter_matcher: &filter_widget::FilterMatcher, + entity_data: &EntityData, ui: &mut egui::Ui, ) { - // We traverse and display this tree only if it contains a matching entity part. - 'early_exit: { - if filter_matcher.matches_nothing() { - return; - } - - // Filter is inactive or otherwise whitelisting everything. - if filter_matcher.matches_everything() { - break 'early_exit; - } - - // The current path is a match. - if tree - .path - .iter() - .any(|entity_part| filter_matcher.matches(&entity_part.ui_string())) - { - break 'early_exit; - } - - // Our subtree contains a match. - if tree - .find_first_child_recursive(|entity_path| { - entity_path - .last() - .is_some_and(|entity_part| filter_matcher.matches(&entity_part.ui_string())) - }) - .is_some() - { - break 'early_exit; - } - - // No match to be found, so nothing to display. - return; - } - - let db = match self.source { - TimePanelSource::Recording => ctx.recording(), - TimePanelSource::Blueprint => ctx.store_context.blueprint, - }; - - // The last part of the path component - let last_path_part = tree.path.last(); - let text = if let Some(last_path_part) = last_path_part { - let part_text = if tree.is_leaf() { - last_path_part.ui_string() - } else { - format!("{}/", last_path_part.ui_string()) // show we have children with a / - }; - - filter_matcher - .matches_formatted(ui.ctx(), &part_text) - .unwrap_or_else(|| part_text.into()) - } else { - "/".into() - }; + re_tracing::profile_function!(); - let item = TimePanelItem::entity_path(tree.path.clone()); + let entity_path = &entity_data.entity_path; + let item = TimePanelItem::entity_path(entity_path.clone()); let is_selected = ctx.selection().contains_item(&item.to_item()); let is_item_hovered = ctx .selection_state() @@ -735,24 +669,22 @@ impl TimePanel { let collapse_scope = self.collapse_scope(); - // expand if children is focused + // Expand if one of the children is focused let focused_entity_path = ctx .focused_item .as_ref() .and_then(|item| item.entity_path()); - if focused_entity_path.is_some_and(|entity_path| entity_path.is_descendant_of(&tree.path)) { + if focused_entity_path.is_some_and(|entity_path| entity_path.is_descendant_of(entity_path)) + { collapse_scope - .entity(tree.path.clone()) + .entity(entity_path.clone()) .set_open(ui.ctx(), true); } // Globally unique id that is dependent on the "nature" of the tree (recording or blueprint, // in a filter session or not) - let id = collapse_scope.entity(tree.path.clone()).into(); - - let is_short_path = tree.path.len() <= 1 && !tree.is_leaf(); - let default_open = self.filter_state.is_active() || is_short_path; + let id = collapse_scope.entity(entity_path.clone()).into(); let list_item::ShowCollapsingResponse { item_response: response, @@ -767,23 +699,27 @@ impl TimePanel { .show_hierarchical_with_children( ui, id, - default_open, - list_item::LabelContent::new(text) - .with_icon(guess_instance_path_icon( - ctx, - &InstancePath::from(tree.path.clone()), - )) - .truncate(false), + entity_data.default_open, + list_item::LabelContent::new(format_matching_text( + ctx.egui_ctx, + &entity_data.label, + entity_data.highlight_sections.iter().cloned(), + None, + )) + .with_icon(guess_instance_path_icon( + ctx, + &InstancePath::from(entity_path.clone()), + )) + .truncate(false), |ui| { - self.show_children( + self.show_entity_contents( ctx, viewport_blueprint, entity_db, time_ctrl, time_area_response, time_area_painter, - tree, - filter_matcher, + entity_data, ui, ); }, @@ -795,13 +731,13 @@ impl TimePanel { ui, ctx, &time_ctrl.current_query(), - db, - &tree.path, + entity_db, + entity_path, include_subtree, ); }); - if Some(&tree.path) == focused_entity_path { + if Some(entity_path) == focused_entity_path { // Scroll only if the entity isn't already visible. This is important because that's what // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be // annoying to induce a scroll motion. @@ -828,6 +764,10 @@ impl TimePanel { let response_rect = response.rect; self.next_col_right = self.next_col_right.max(response_rect.right()); + // + // Display the data density graph only if it is visible. + // + // From the left of the label, all the way to the right-most of the time panel let full_width_rect = Rect::from_x_y_ranges( response_rect.left()..=ui.max_rect().right(), @@ -835,41 +775,42 @@ impl TimePanel { ); let is_visible = ui.is_rect_visible(full_width_rect); + if is_visible { + let tree_has_data_in_current_timeline = entity_db.subtree_has_data_on_timeline( + &entity_db.storage_engine(), + time_ctrl.timeline(), + entity_path, + ); + if tree_has_data_in_current_timeline { + let row_rect = Rect::from_x_y_ranges( + time_area_response.rect.x_range(), + response_rect.y_range(), + ); - // ---------------------------------------------- - - // show the data in the time area: - let tree_has_data_in_current_timeline = entity_db.subtree_has_data_on_timeline( - &entity_db.storage_engine(), - time_ctrl.timeline(), - &tree.path, - ); - if is_visible && tree_has_data_in_current_timeline { - let row_rect = - Rect::from_x_y_ranges(time_area_response.rect.x_range(), response_rect.y_range()); - - highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); + highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); - // show the density graph only if that item is closed - if is_closed { - data_density_graph::data_density_graph_ui( - &mut self.data_density_graph_painter, - ctx, - time_ctrl, - db, - time_area_painter, - ui, - &self.time_ranges_ui, - row_rect, - &item, - true, - ); + // show the density graph only if that item is closed + if is_closed { + data_density_graph::data_density_graph_ui( + &mut self.data_density_graph_painter, + ctx, + time_ctrl, + entity_db, + time_area_painter, + ui, + &self.time_ranges_ui, + row_rect, + &item, + true, + ); + } } } } + /// Display the contents of an entity, i.e. its sub-entities and its components. #[expect(clippy::too_many_arguments)] - fn show_children( + fn show_entity_contents( &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, @@ -877,12 +818,13 @@ impl TimePanel { time_ctrl: &mut TimeControl, time_area_response: &egui::Response, time_area_painter: &egui::Painter, - tree: &EntityTree, - filter_matcher: &filter_widget::FilterMatcher, + entity_data: &EntityData, ui: &mut egui::Ui, ) { - for child in tree.children.values() { - self.show_tree( + re_tracing::profile_function!(); + + for child in &entity_data.children { + self.show_entity( ctx, viewport_blueprint, entity_db, @@ -890,40 +832,24 @@ impl TimePanel { time_area_response, time_area_painter, child, - filter_matcher, ui, ); } + let entity_path = &entity_data.entity_path; let engine = entity_db.storage_engine(); let store = engine.store(); // If this is an entity: - if let Some(components) = store.all_components_for_entity(&tree.path) { + if let Some(components) = store.all_components_for_entity(entity_path) { for component_name in sorted_component_list_for_ui(components.iter()) { - let is_static = store.entity_has_static_component(&tree.path, &component_name); + let is_static = store.entity_has_static_component(entity_path, &component_name); - let component_path = ComponentPath::new(tree.path.clone(), component_name); + let component_path = ComponentPath::new(entity_path.clone(), component_name); let short_component_name = component_path.component_name.short_name(); let item = TimePanelItem::component_path(component_path.clone()); let timeline = time_ctrl.timeline(); - let component_has_data_in_current_timeline = store - .entity_has_component_on_timeline( - time_ctrl.timeline(), - &tree.path, - &component_name, - ); - - let num_static_messages = - store.num_static_events_for_component(&tree.path, component_name); - let num_temporal_messages = store.num_temporal_events_for_component_on_timeline( - time_ctrl.timeline(), - &tree.path, - component_name, - ); - let total_num_messages = num_static_messages + num_temporal_messages; - let response = ui .list_item() .render_offscreen(false) @@ -956,6 +882,16 @@ impl TimePanel { let response_rect = response.rect; response.on_hover_ui(|ui| { + let num_static_messages = + store.num_static_events_for_component(entity_path, component_name); + let num_temporal_messages = store + .num_temporal_events_for_component_on_timeline( + time_ctrl.timeline(), + entity_path, + component_name, + ); + let total_num_messages = num_static_messages + num_temporal_messages; + if total_num_messages == 0 { ui.label(ui.ctx().warning_text(format!( "No event logged on timeline {:?}", @@ -1018,32 +954,48 @@ impl TimePanel { ); let is_visible = ui.is_rect_visible(full_width_rect); - if is_visible && component_has_data_in_current_timeline { - // show the data in the time area: - let row_rect = Rect::from_x_y_ranges( - time_area_response.rect.x_range(), - response_rect.y_range(), - ); - - highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); - - 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, - db, - time_area_painter, - ui, - &self.time_ranges_ui, - row_rect, - &item, - true, - ); + if is_visible { + let component_has_data_in_current_timeline = store + .entity_has_component_on_timeline( + time_ctrl.timeline(), + entity_path, + &component_name, + ); + + if component_has_data_in_current_timeline { + // show the data in the time area: + let row_rect = Rect::from_x_y_ranges( + time_area_response.rect.x_range(), + response_rect.y_range(), + ); + + highlight_timeline_row( + ui, + ctx, + time_area_painter, + &item.to_item(), + &row_rect, + ); + + 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, + db, + time_area_painter, + ui, + &self.time_ranges_ui, + row_rect, + &item, + true, + ); + } } } } diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs new file mode 100644 index 0000000000000..596750fcf7f79 --- /dev/null +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -0,0 +1,152 @@ +use std::ops::Range; + +use itertools::Itertools as _; +use smallvec::SmallVec; + +use re_entity_db::EntityTree; +use re_log_types::EntityPath; +use re_ui::filter_widget::FilterMatcher; +use re_viewer_context::ViewerContext; + +use crate::TimePanelSource; + +#[derive(Debug)] +pub struct StreamsTreeData { + pub children: Vec, +} + +impl StreamsTreeData { + pub fn from_source_and_filter( + ctx: &ViewerContext<'_>, + source: TimePanelSource, + filter_matcher: &FilterMatcher, + ) -> Self { + re_tracing::profile_function!(); + + let db = match source { + TimePanelSource::Recording => ctx.recording(), + TimePanelSource::Blueprint => ctx.blueprint_db(), + }; + + let root_data = EntityData::from_entity_tree_and_filter(db.tree(), filter_matcher, false); + + // We show "/" on top only for recording streams, because the `/` entity in blueprint + // is always empty, so it's just lost space. This works around an issue where the + // selection/hover state of the `/` entity is wrongly synchronized between both + // stores, due to `Item::*` not tracking stores for entity paths. + + Self { + children: match source { + TimePanelSource::Recording => root_data + .map(|entity_part_data| vec![entity_part_data]) + .unwrap_or_default(), + TimePanelSource::Blueprint => root_data + .map(|entity_part_data| entity_part_data.children) + .unwrap_or_default(), + }, + } + } +} + +// --- + +#[derive(Debug)] +pub struct EntityData { + pub entity_path: EntityPath, + + pub label: String, + pub highlight_sections: SmallVec<[Range; 1]>, + + pub default_open: bool, + + pub children: Vec, +} + +impl EntityData { + pub fn from_entity_tree_and_filter( + entity_tree: &EntityTree, + filter_matcher: &FilterMatcher, + mut is_already_a_match: bool, + ) -> Option { + // Early out + if filter_matcher.matches_nothing() { + return None; + } + + let mut label = entity_tree + .path + .last() + .map(|entity_part| entity_part.ui_string()) + .unwrap_or("/".to_owned()); + + // + // Filtering + // + + let (entity_part_matches, highlight_sections) = if filter_matcher.matches_everything() { + // fast path (filter is inactive) + (true, SmallVec::new()) + } else if let Some(entity_part) = entity_tree.path.last() { + // Nominal case of matching the hierarchy. + if let Some(match_sections) = filter_matcher.find_matches(&entity_part.ui_string()) { + (true, match_sections.collect()) + } else { + (false, SmallVec::new()) + } + } else { + // we are the root, it can never match anything + (false, SmallVec::new()) + }; + + // We want to keep entire branches if a single of its node matches. So we must propagate the + // "matched" state so we can make the right call when we reach leaf nodes. + is_already_a_match |= entity_part_matches; + + // + // Recurse + // + + if entity_tree.children.is_empty() { + // Discard a leaf item unless it is already a match. + is_already_a_match.then(|| { + // Leaf items are always collapsed by default, even when the filter is active. + let default_open = false; + + Self { + entity_path: entity_tree.path.clone(), + label, + highlight_sections, + default_open, + children: vec![], + } + }) + } else { + let children = entity_tree + .children + .values() + .filter_map(|sub_tree| { + Self::from_entity_tree_and_filter(sub_tree, filter_matcher, is_already_a_match) + }) + .collect_vec(); + + (is_already_a_match || !children.is_empty()).then(|| { + // Only top-level non-leaf entities are expanded by default, unless the filter is + // active. + let default_open = filter_matcher.is_active() || entity_tree.path.len() <= 1; + Self { + entity_path: entity_tree.path.clone(), + label: if children.is_empty() || entity_tree.path.is_root() { + label + } else { + // Indicate that we have children + label.push('/'); + label + }, + highlight_sections, + default_open, + children, + } + }) + } + } +} diff --git a/crates/viewer/re_time_panel/src/time_axis.rs b/crates/viewer/re_time_panel/src/time_axis.rs index fe7b0252203a5..41aeedbfc6663 100644 --- a/crates/viewer/re_time_panel/src/time_axis.rs +++ b/crates/viewer/re_time_panel/src/time_axis.rs @@ -1,3 +1,6 @@ +// TODO(#6330): remove unwrap() +#![expect(clippy::unwrap_used)] + use re_entity_db::TimeHistogram; use re_log_types::{ResolvedTimeRange, TimeInt, TimeType}; diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_test_active_query.png b/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_test_active_query.png index 8c19583c7280f..7a1ce0daf8ca2 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_test_active_query.png +++ b/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_test_active_query.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17c40bafbc465fe68335737b608569126c437c29319b42d49e7b38e87f027ee1 -size 27073 +oid sha256:7de7ddd6c3b874dd17ae124dd89b2ba396360fb8e9ad96102ec3571c56da158d +size 21810 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_0.png b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_0.png new file mode 100644 index 0000000000000..44ea90e980fb5 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f25d6bba58b9aeab6bc25d55ff2d7d5d7a72892c038257624650eabba7d774a +size 144221 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_5.png b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_5.png new file mode 100644 index 0000000000000..42859a51b67e7 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4398719c591105cdbcd9eb904acdc487e2630a6b19a7ecf522a681c1f555469 +size 144429 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_9223372036854775807.png b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_9223372036854775807.png new file mode 100644 index 0000000000000..560fd161b6f33 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_a_9223372036854775807.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20a045edfc9294e5ac7a483f7d47177c3721865906eb37a6aa1e2cdd4e668e1a +size 144551 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_0.png b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_0.png new file mode 100644 index 0000000000000..395baf84496ba --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eee17ecdc118609f31ff0285acdfa49061ccdf7dd403e14c364532750470f699 +size 142735 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_5.png b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_5.png new file mode 100644 index 0000000000000..f251e93726674 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba32eb0898dfd66fbd3a287fd21405772258a705427ee7f4678b6adb1bbf6a7a +size 142918 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_9223372036854775807.png b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_9223372036854775807.png new file mode 100644 index 0000000000000..16a34356368b2 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_entity_kinds_timeline_b_9223372036854775807.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f56e3ef65134aa7785ef9d88101bdf0e66f7258d86bfc80b764c47cb17e10a8 +size 143213 diff --git a/crates/viewer/re_time_panel/tests/time_panel_tests.rs b/crates/viewer/re_time_panel/tests/time_panel_tests.rs index 9bf24f3863b84..25a5235965fa6 100644 --- a/crates/viewer/re_time_panel/tests/time_panel_tests.rs +++ b/crates/viewer/re_time_panel/tests/time_panel_tests.rs @@ -1,14 +1,14 @@ -use std::sync::Arc; - use egui::Vec2; -use re_chunk_store::{Chunk, LatestAtQuery, RowId}; -use re_log_types::example_components::MyPoint; -use re_log_types::external::re_types_core::Component; -use re_log_types::{build_frame_nr, EntityPath}; +use re_chunk_store::{LatestAtQuery, RowId}; +use re_entity_db::InstancePath; +use re_log_types::{ + build_frame_nr, example_components::MyPoint, external::re_types_core::Component, EntityPath, + TimeInt, TimePoint, TimeType, Timeline, +}; use re_time_panel::TimePanel; -use re_viewer_context::blueprint_timeline; -use re_viewer_context::test_context::TestContext; +use re_types::archetypes::Points2D; +use re_viewer_context::{blueprint_timeline, test_context::TestContext, CollapseScope, TimeView}; use re_viewport_blueprint::ViewportBlueprint; #[test] @@ -18,24 +18,24 @@ pub fn time_panel_two_sections_should_match_snapshot() { let points1 = MyPoint::from_iter(0..1); for i in 0..2 { - let entity_path = EntityPath::from(format!("/entity/{i}")); - let mut builder = Chunk::builder(entity_path.clone()); - for frame in [10, 11, 12, 15, 18, 100, 102, 104].map(|frame| frame + i) { - builder = builder.with_sparse_component_batches( - RowId::new(), - [build_frame_nr(frame)], - [(MyPoint::descriptor(), Some(&points1 as _))], - ); - } - test_context - .recording_store - .add_chunk(&Arc::new(builder.build().unwrap())) - .unwrap(); + test_context.log_entity(format!("/entity/{i}").into(), |mut builder| { + for frame in [10, 11, 12, 15, 18, 100, 102, 104].map(|frame| frame + i) { + builder = builder.with_sparse_component_batches( + RowId::new(), + [build_frame_nr(frame)], + [(MyPoint::descriptor(), Some(&points1 as _))], + ); + } + + builder + }); } run_time_panel_and_save_snapshot( test_context, TimePanel::default(), + 300.0, + false, "time_panel_two_sections", ); } @@ -55,27 +55,33 @@ pub fn time_panel_dense_data_should_match_snapshot() { rng_seed.wrapping_mul(0x2545_f491_4f6c_dd1d) }; - let entity_path = EntityPath::from("/entity"); - let mut builder = Chunk::builder(entity_path.clone()); - for frame in 0..1_000 { - if rng() & 0b1 == 0 { - continue; + test_context.log_entity("/entity".into(), |mut builder| { + for frame in 0..1_000 { + if rng() & 0b1 == 0 { + continue; + } + + builder = builder.with_sparse_component_batches( + RowId::new(), + [build_frame_nr(frame)], + [(MyPoint::descriptor(), Some(&points1 as _))], + ); } - builder = builder.with_sparse_component_batches( - RowId::new(), - [build_frame_nr(frame)], - [(MyPoint::descriptor(), Some(&points1 as _))], - ); - } - test_context - .recording_store - .add_chunk(&Arc::new(builder.build().unwrap())) - .unwrap(); + builder + }); - run_time_panel_and_save_snapshot(test_context, TimePanel::default(), "time_panel_dense_data"); + run_time_panel_and_save_snapshot( + test_context, + TimePanel::default(), + 300.0, + false, + "time_panel_dense_data", + ); } +// --- + #[test] pub fn time_panel_filter_test_inactive_should_match_snapshot() { run_time_panel_filter_tests(false, "", "time_panel_filter_test_inactive"); @@ -98,35 +104,27 @@ pub fn run_time_panel_filter_tests(filter_active: bool, query: &str, snapshot_na let points1 = MyPoint::from_iter(0..1); for i in 0..2 { - let entity_path = EntityPath::from(format!("/entity/{i}")); - let mut builder = Chunk::builder(entity_path.clone()); + test_context.log_entity(format!("/entity/{i}").into(), |mut builder| { + builder = builder.with_sparse_component_batches( + RowId::new(), + [build_frame_nr(1)], + [(MyPoint::descriptor(), Some(&points1 as _))], + ); - builder = builder.with_sparse_component_batches( - RowId::new(), - [build_frame_nr(1)], - [(MyPoint::descriptor(), Some(&points1 as _))], - ); - - test_context - .recording_store - .add_chunk(&Arc::new(builder.build().unwrap())) - .unwrap(); + builder + }); } for i in 0..2 { - let entity_path = EntityPath::from(format!("/path/{i}")); - let mut builder = Chunk::builder(entity_path.clone()); + test_context.log_entity(format!("/path/{i}").into(), |mut builder| { + builder = builder.with_sparse_component_batches( + RowId::new(), + [build_frame_nr(1)], + [(MyPoint::descriptor(), Some(&points1 as _))], + ); - builder = builder.with_sparse_component_batches( - RowId::new(), - [build_frame_nr(1)], - [(MyPoint::descriptor(), Some(&points1 as _))], - ); - - test_context - .recording_store - .add_chunk(&Arc::new(builder.build().unwrap())) - .unwrap(); + builder + }); } let mut time_panel = TimePanel::default(); @@ -134,20 +132,138 @@ pub fn run_time_panel_filter_tests(filter_active: bool, query: &str, snapshot_na time_panel.activate_filter(query); } - run_time_panel_and_save_snapshot(test_context, time_panel, snapshot_name); + run_time_panel_and_save_snapshot(test_context, time_panel, 300.0, false, snapshot_name); +} + +// -- + +/// This test focuses on various kinds of entities and ensures their representation in the tree is +/// correct regardless of the selected timeline and current time. +//TODO(ab): we should also test what happens when GC kicks in. +#[test] +pub fn test_various_entity_kinds_in_time_panel() { + TimePanel::ensure_registered_subscribers(); + + for timeline in ["timeline_a", "timeline_b"] { + for time in [0, 5, i64::MAX] { + let mut test_context = TestContext::default(); + + log_data_for_various_entity_kinds_tests(&mut test_context); + + test_context + .recording_config + .time_ctrl + .write() + .set_timeline_and_time(Timeline::new(timeline, TimeType::Sequence), time); + + test_context + .recording_config + .time_ctrl + .write() + .set_time_view(TimeView { + min: 0.into(), + time_spanned: 10.0, + }); + + let time_panel = TimePanel::default(); + + run_time_panel_and_save_snapshot( + test_context, + time_panel, + 1200.0, + true, + &format!("various_entity_kinds_{timeline}_{time}"), + ); + } + } +} + +pub fn log_data_for_various_entity_kinds_tests(test_context: &mut TestContext) { + let timeline_a = "timeline_a"; + let timeline_b = "timeline_b"; + + // just your average static entity + log_static_data(test_context, "static_entity"); + + // static data is over-logged multiple times + for _ in 0..3 { + log_static_data(test_context, "static_entity_multiple"); + } + + // static data overrides data logged on timeline a + log_data(test_context, "static_overrides_temporal", timeline_a, 3); + log_static_data(test_context, "static_overrides_temporal"); + + // data in single timeline + log_data(test_context, "timeline_a_only", timeline_a, 3); + log_data(test_context, "timeline_b_only", timeline_b, 3); + + // data in both timelines + log_data(test_context, "timeline_a_and_b", timeline_a, 2); + log_data(test_context, "timeline_a_and_b", timeline_b, 5); + + // nested entity with parent empty + log_data(test_context, "/empty/parent/of/entity", timeline_a, 3); + + // nested entity with data in a parent + log_data(test_context, "/parent_with_data/of/entity", timeline_a, 3); + log_data(test_context, "/parent_with_data", timeline_a, 1); + + // some entity with data logged "late" on the timeline + log_data(test_context, "/late_data", timeline_a, 9); + log_data(test_context, "/late_data", timeline_a, 10); +} + +pub fn log_data( + test_context: &mut TestContext, + entity_path: impl Into, + timeline: &str, + time: i64, +) { + test_context.log_entity(entity_path.into(), |builder| { + builder.with_archetype( + RowId::new(), + [( + Timeline::new(timeline, TimeType::Sequence), + TimeInt::try_from(time).expect("time must be valid"), + )], + &Points2D::new([[0.0, 0.0]]), + ) + }); +} + +pub fn log_static_data(test_context: &mut TestContext, entity_path: impl Into) { + test_context.log_entity(entity_path.into(), |builder| { + builder.with_archetype( + RowId::new(), + TimePoint::from(std::collections::BTreeMap::default()), + &Points2D::new([[0.0, 0.0]]), + ) + }); } fn run_time_panel_and_save_snapshot( mut test_context: TestContext, mut time_panel: TimePanel, + height: f32, + expand_all: bool, snapshot_name: &str, ) { - //TODO(ab): this contains a lot of boilerplate which should be provided by helpers let mut harness = test_context .setup_kittest_for_rendering() - .with_size(Vec2::new(700.0, 300.0)) + .with_size(Vec2::new(700.0, height)) .build_ui(|ui| { test_context.run(&ui.ctx().clone(), |viewer_ctx| { + if expand_all { + re_context_menu::collapse_expand::collapse_expand_instance_path( + viewer_ctx, + viewer_ctx.recording(), + &InstancePath::entity_all("/".into()), + CollapseScope::StreamsTree, + true, + ); + } + let blueprint = ViewportBlueprint::try_from_db( viewer_ctx.store_context.blueprint, &LatestAtQuery::latest(blueprint_timeline()), diff --git a/crates/viewer/re_viewer_context/src/viewer_context.rs b/crates/viewer/re_viewer_context/src/viewer_context.rs index 8d92d94f09cf3..4a65f1c152a7e 100644 --- a/crates/viewer/re_viewer_context/src/viewer_context.rs +++ b/crates/viewer/re_viewer_context/src/viewer_context.rs @@ -162,8 +162,6 @@ impl ViewerContext<'_> { interacted_items: impl Into, draggable: bool, ) { - re_tracing::profile_function!(); - let interacted_items = interacted_items.into().into_mono_instance_path_items(self); let selection_state = self.selection_state(); From 46225f78b9d3abc80592c31b16872f33b5d38ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20G=C3=B6rtler?= Date: Thu, 30 Jan 2025 17:23:34 +0100 Subject: [PATCH 41/43] Clickable URLs in named components / `AnyValues` (#8864) ### Related * Supersedes #8567. * Closes #8837. ### What Title. https://github.com/user-attachments/assets/a08fd640-254b-45d1-9ba2-d83802980dd9 Minor problems before this can be merged * [x] The component name disappears when hovering over the URI entry, and maybe related * [x] The chunk store browser crashes with a panic. * [x] Correct ellipsis in narrow views. --------- Co-authored-by: Antoine Beyeler <49431240+abey79@users.noreply.github.com> --- Cargo.lock | 1 + .../re_component_ui/src/datatype_uis/mod.rs | 4 +- .../src/datatype_uis/singleline_string.rs | 75 +------------------ crates/viewer/re_component_ui/src/lib.rs | 12 +-- ...stom_empty_array_any_value_empty_array.png | 3 + ...custom_large_blob_any_value_large_blob.png | 3 + ...stom_small_array_any_value_small_array.png | 3 + .../custom_string_any_value_string.png | 3 + ...custom_url_string_any_value_url_string.png | 3 + ...stom_empty_array_any_value_empty_array.png | 3 + ...custom_large_blob_any_value_large_blob.png | 3 + ...stom_small_array_any_value_small_array.png | 3 + .../custom_string_any_value_string.png | 3 + ...custom_url_string_any_value_url_string.png | 3 + .../tests/test_all_components_ui.rs | 25 +++++++ crates/viewer/re_data_ui/src/component.rs | 4 +- .../re_data_ui/src/component_ui_registry.rs | 9 +-- crates/viewer/re_ui/Cargo.toml | 4 +- crates/viewer/re_ui/src/arrow_ui.rs | 17 +++-- crates/viewer/re_ui/src/ui_ext.rs | 35 +++++---- crates/viewer/re_ui/src/ui_layout.rs | 26 ++++--- .../src/component_ui_registry.rs | 21 +++--- docs/content/howto/logging/custom-data.md | 9 ++- docs/snippets/all/tutorials/any_values.py | 3 + docs/snippets/all/tutorials/any_values.rs | 20 ++++- rerun_py/rerun_sdk/rerun/any_value.py | 3 + 26 files changed, 156 insertions(+), 142 deletions(-) create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_empty_array_any_value_empty_array.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_large_blob_any_value_large_blob.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_small_array_any_value_small_array.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_string_any_value_string.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_url_string_any_value_url_string.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_empty_array_any_value_empty_array.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_large_blob_any_value_large_blob.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_small_array_any_value_small_array.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_string_any_value_string.png create mode 100644 crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_url_string_any_value_url_string.png diff --git a/Cargo.lock b/Cargo.lock index 581a3f74b78e4..ddaa39c683fac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6729,6 +6729,7 @@ dependencies = [ "strum_macros", "sublime_fuzzy", "time", + "url", ] [[package]] diff --git a/crates/viewer/re_component_ui/src/datatype_uis/mod.rs b/crates/viewer/re_component_ui/src/datatype_uis/mod.rs index b355a9e0aeae0..9c4356f50dcda 100644 --- a/crates/viewer/re_component_ui/src/datatype_uis/mod.rs +++ b/crates/viewer/re_component_ui/src/datatype_uis/mod.rs @@ -20,9 +20,7 @@ pub use float_drag::{ }; pub use int_drag::edit_u64_range; pub use range1d::edit_view_range1d; -pub use singleline_string::{ - display_name_ui, display_text_ui, edit_multiline_string, edit_singleline_string, -}; +pub use singleline_string::{edit_multiline_string, edit_singleline_string}; pub use vec::{edit_or_view_vec2d, edit_or_view_vec3d, edit_or_view_vec3d_raw}; pub use view_id::view_view_id; pub use view_uuid::view_uuid; diff --git a/crates/viewer/re_component_ui/src/datatype_uis/singleline_string.rs b/crates/viewer/re_component_ui/src/datatype_uis/singleline_string.rs index 510ca3755bfae..b0f4d8b96be5d 100644 --- a/crates/viewer/re_component_ui/src/datatype_uis/singleline_string.rs +++ b/crates/viewer/re_component_ui/src/datatype_uis/singleline_string.rs @@ -1,17 +1,6 @@ -use re_types::{ - components::{Name, Text}, - datatypes::Utf8, - Loggable as _, -}; -use re_ui::UiExt as _; -use re_viewer_context::{ - external::{ - re_chunk_store::{LatestAtQuery, RowId}, - re_entity_db::EntityDb, - re_log_types::EntityPath, - }, - MaybeMutRef, UiLayout, ViewerContext, -}; +use re_types::datatypes::Utf8; + +use re_viewer_context::{MaybeMutRef, UiLayout}; /// Generic singleline string editor. pub fn edit_singleline_string( @@ -72,61 +61,3 @@ fn edit_multiline_string_impl( UiLayout::SelectionPanel.data_label(ui, value.as_str()) } } - -// TODO(#6661): Should be merged with edit_singleline_string. -#[allow(clippy::too_many_arguments)] -pub fn display_text_ui( - _ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - ui_layout: UiLayout, - _query: &LatestAtQuery, - _db: &EntityDb, - _path: &EntityPath, - _row_id: Option, - data: &dyn arrow::array::Array, -) { - let text = match Text::from_arrow(data) { - Ok(text) => text.first().cloned(), - Err(err) => { - ui.error_label("Failed to deserialize") - .on_hover_text(err.to_string()); - return; - } - }; - - let Some(text) = text else { - ui.weak("(none)"); - return; - }; - - ui_layout.data_label(ui, text); -} - -// TODO(#6661): Should be merged with edit_singleline_string. -#[allow(clippy::too_many_arguments)] -pub fn display_name_ui( - _ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - ui_layout: UiLayout, - _query: &LatestAtQuery, - _db: &EntityDb, - _path: &EntityPath, - _row_id: Option, - data: &dyn arrow::array::Array, -) { - let name = match Name::from_arrow(data) { - Ok(name) => name.first().cloned(), - Err(err) => { - ui.error_label("Failed to deserialize") - .on_hover_text(err.to_string()); - return; - } - }; - - let Some(name) = name else { - ui.weak("(none)"); - return; - }; - - ui_layout.data_label(ui, name); -} diff --git a/crates/viewer/re_component_ui/src/lib.rs b/crates/viewer/re_component_ui/src/lib.rs index bbed24bfd956d..49058447275c3 100644 --- a/crates/viewer/re_component_ui/src/lib.rs +++ b/crates/viewer/re_component_ui/src/lib.rs @@ -27,11 +27,10 @@ mod visual_bounds2d; mod zoom_level; use datatype_uis::{ - display_name_ui, display_text_ui, edit_bool, edit_f32_min_to_max_float, edit_f32_zero_to_max, - edit_f32_zero_to_one, edit_f64_min_to_max_float, edit_f64_zero_to_max, edit_multiline_string, - edit_or_view_vec2d, edit_or_view_vec3d, edit_singleline_string, edit_u64_range, edit_ui_points, - edit_view_enum, edit_view_enum_with_variant_available, edit_view_range1d, view_uuid, - view_view_id, + edit_bool, edit_f32_min_to_max_float, edit_f32_zero_to_max, edit_f32_zero_to_one, + edit_f64_min_to_max_float, edit_f64_zero_to_max, edit_multiline_string, edit_or_view_vec2d, + edit_or_view_vec3d, edit_singleline_string, edit_u64_range, edit_ui_points, edit_view_enum, + edit_view_enum_with_variant_available, edit_view_range1d, view_uuid, view_view_id, }; use re_types::blueprint::components::{RootContainer, ViewMaximized}; @@ -46,7 +45,6 @@ use re_types::{ Name, Opacity, Position2D, Range1D, Scale3D, ShowLabels, StrokeWidth, Text, TransformRelation, Translation3D, ValueRange, }, - Component as _, }; use re_viewer_context::gpu_bridge::colormap_edit_or_view_ui; @@ -100,10 +98,8 @@ pub fn create_component_ui_registry() -> re_viewer_context::ComponentUiRegistry registry.add_singleline_edit_or_view::(edit_bool); // Text components: - registry.add_legacy_display_ui(Text::name(), Box::new(display_text_ui)); // TODO(andreas): Why is there a display ui? registry.add_singleline_edit_or_view::(edit_singleline_string); registry.add_multiline_edit_or_view::(edit_multiline_string); - registry.add_legacy_display_ui(Name::name(), Box::new(display_name_ui)); // TODO(andreas): Why is there a display ui? registry.add_singleline_edit_or_view::(edit_singleline_string); registry.add_multiline_edit_or_view::(edit_multiline_string); diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_empty_array_any_value_empty_array.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_empty_array_any_value_empty_array.png new file mode 100644 index 0000000000000..6af9cbab3558a --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_empty_array_any_value_empty_array.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dea974eca9fbcb8e2a1856af3c2c0e641226f83d1f48cb753daf22d98d9aca7 +size 2821 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_large_blob_any_value_large_blob.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_large_blob_any_value_large_blob.png new file mode 100644 index 0000000000000..f1fd7873f5e9e --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_large_blob_any_value_large_blob.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:332d2c7cd473e80dce545435f0e213217a1d2225242c6200b73083471f737cf0 +size 4201 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_small_array_any_value_small_array.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_small_array_any_value_small_array.png new file mode 100644 index 0000000000000..d836101a8f745 --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_small_array_any_value_small_array.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d608dad302362e2ac9b7525fa106620621a126fef875dd13983ba2e9eff753de +size 3711 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_string_any_value_string.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_string_any_value_string.png new file mode 100644 index 0000000000000..d54ad172bd96e --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_string_any_value_string.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d52738e737330966e8fc68c87fe5feb99e4283a3528bb47cd98d15e3d02ccfd +size 4017 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_url_string_any_value_url_string.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_url_string_any_value_url_string.png new file mode 100644 index 0000000000000..7281ce5e13b1a --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_narrow/custom_url_string_any_value_url_string.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba9a64bdeae41071931993a6f172c9f17c5d24282fe74e2d7a044256b51359de +size 4240 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_empty_array_any_value_empty_array.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_empty_array_any_value_empty_array.png new file mode 100644 index 0000000000000..2ad2c3352512b --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_empty_array_any_value_empty_array.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1004374b793fcd1a5c3db6ece69eeaf396665ee6ffa0d4b116fb97340819d164 +size 3139 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_large_blob_any_value_large_blob.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_large_blob_any_value_large_blob.png new file mode 100644 index 0000000000000..e5c75739ada4f --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_large_blob_any_value_large_blob.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24409beb25693128f8beb6440ccb990e841a99a390b93a9f0ca7914cd87a0b67 +size 4513 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_small_array_any_value_small_array.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_small_array_any_value_small_array.png new file mode 100644 index 0000000000000..f63baf4234214 --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_small_array_any_value_small_array.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61a70fc2fb1bc7b6bc0444503c9572fc060d432f55bc91d8723848d1303415b5 +size 4024 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_string_any_value_string.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_string_any_value_string.png new file mode 100644 index 0000000000000..8cb13fe0a4457 --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_string_any_value_string.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14d625ada59c12b4fb80de7cf91daa3327ddbfb7b7108479950b3677a167439a +size 4694 diff --git a/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_url_string_any_value_url_string.png b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_url_string_any_value_url_string.png new file mode 100644 index 0000000000000..22c26039ef5fd --- /dev/null +++ b/crates/viewer/re_component_ui/tests/snapshots/all_components_list_item_wide/custom_url_string_any_value_url_string.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e24b436ea7616d1355b6a3f36b939abb0257affac45bda5f55e0c220bdc3d4be +size 5344 diff --git a/crates/viewer/re_component_ui/tests/test_all_components_ui.rs b/crates/viewer/re_component_ui/tests/test_all_components_ui.rs index b2a7f9fa48b7e..65539d940eece 100644 --- a/crates/viewer/re_component_ui/tests/test_all_components_ui.rs +++ b/crates/viewer/re_component_ui/tests/test_all_components_ui.rs @@ -78,6 +78,31 @@ fn test_cases(reflection: &Reflection) -> Vec { ), "any_value_f64", ), + TestCase::from_arrow( + ComponentName::from("custom_string"), + arrow::array::StringArray::from(vec!["Hello World!"]), + "any_value_string", + ), + TestCase::from_arrow( + ComponentName::from("custom_url_string"), + arrow::array::StringArray::from(vec!["https://rerun.io"]), + "any_value_url_string", + ), + TestCase::from_arrow( + ComponentName::from("custom_empty_array"), + arrow::array::UInt8Array::from(vec![] as Vec), + "any_value_empty_array", + ), + TestCase::from_arrow( + ComponentName::from("custom_small_array"), + arrow::array::UInt8Array::from(vec![42; 10]), + "any_value_small_array", + ), + TestCase::from_arrow( + ComponentName::from("custom_large_blob"), + arrow::array::UInt8Array::from(vec![42; 3001]), + "any_value_large_blob", + ), ]; // diff --git a/crates/viewer/re_data_ui/src/component.rs b/crates/viewer/re_data_ui/src/component.rs index 663923ddb5cda..5bbc5dc9c0cb4 100644 --- a/crates/viewer/re_data_ui/src/component.rs +++ b/crates/viewer/re_data_ui/src/component.rs @@ -127,9 +127,7 @@ impl DataUi for ComponentPathLatestAtResults<'_> { max_row.saturating_sub(1) }; - if num_instances == 0 { - ui.weak("(empty)"); - } else if num_instances == 1 { + if num_instances <= 1 { ctx.component_ui_registry.ui( ctx, ui, diff --git a/crates/viewer/re_data_ui/src/component_ui_registry.rs b/crates/viewer/re_data_ui/src/component_ui_registry.rs index 041242a3de140..8ab5ea2f0cc33 100644 --- a/crates/viewer/re_data_ui/src/component_ui_registry.rs +++ b/crates/viewer/re_data_ui/src/component_ui_registry.rs @@ -1,4 +1,4 @@ -use re_ui::UiExt; +use re_ui::{arrow_ui, UiExt}; use re_viewer_context::ComponentUiRegistry; use super::EntityDataUi; @@ -27,9 +27,6 @@ pub fn add_to_registry(registry: &mut Com component_raw, ) { Ok(components) => match components.len() { - 0 => { - ui.weak("(empty)"); - } 1 => { components[0].entity_data_ui( ctx, @@ -41,9 +38,7 @@ pub fn add_to_registry(registry: &mut Com db, ); } - i => { - ui.label(format!("{} values", re_format::format_uint(i))); - } + _ => arrow_ui(ui, ui_layout, component_raw), }, Err(err) => { ui.error_with_details_on_hover("(failed to deserialize)") diff --git a/crates/viewer/re_ui/Cargo.toml b/crates/viewer/re_ui/Cargo.toml index 461293cc5246f..f3dff6fd0f3c8 100644 --- a/crates/viewer/re_ui/Cargo.toml +++ b/crates/viewer/re_ui/Cargo.toml @@ -41,6 +41,7 @@ re_log.workspace = true re_log_types.workspace = true # syntax-highlighting for EntityPath re_tracing.workspace = true +arrow = { workspace = true, optional = true } eframe = { workspace = true, default-features = false, features = ["wgpu"] } egui_commonmark = { workspace = true, features = ["pulldown_cmark"] } egui_extras.workspace = true @@ -57,8 +58,7 @@ strum_macros.workspace = true strum.workspace = true sublime_fuzzy.workspace = true time = { workspace = true, features = ["formatting", "local-offset"] } - -arrow = { workspace = true, optional = true } +url.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/viewer/re_ui/src/arrow_ui.rs b/crates/viewer/re_ui/src/arrow_ui.rs index f30a4cfdd8239..b837c31db8810 100644 --- a/crates/viewer/re_ui/src/arrow_ui.rs +++ b/crates/viewer/re_ui/src/arrow_ui.rs @@ -1,4 +1,7 @@ -use arrow::util::display::{ArrayFormatter, FormatOptions}; +use arrow::{ + array::Array, + util::display::{ArrayFormatter, FormatOptions}, +}; use itertools::Itertools as _; use re_arrow_util::ArrowArrayDowncastRef as _; @@ -20,16 +23,16 @@ pub fn arrow_ui(ui: &mut egui::Ui, ui_layout: UiLayout, array: &dyn arrow::array // Special-treat text. // Note: we match on the raw data here, so this works for any component containing text. - if let Some(utf8) = array.downcast_array_ref::() { - if utf8.values().len() == 1 { - let string = utf8.value(0); + if let Some(entries) = array.downcast_array_ref::() { + if entries.len() == 1 { + let string = entries.value(0); ui_layout.data_label(ui, string); return; } } - if let Some(utf8) = array.downcast_array_ref::() { - if utf8.values().len() == 1 { - let string = utf8.value(0); + if let Some(entries) = array.downcast_array_ref::() { + if entries.len() == 1 { + let string = entries.value(0); ui_layout.data_label(ui, string); return; } diff --git a/crates/viewer/re_ui/src/ui_ext.rs b/crates/viewer/re_ui/src/ui_ext.rs index 1a645758ab382..9448b5e764ed7 100644 --- a/crates/viewer/re_ui/src/ui_ext.rs +++ b/crates/viewer/re_ui/src/ui_ext.rs @@ -2,14 +2,10 @@ use std::hash::Hash; use egui::{ emath::{GuiRounding, Rot2}, - pos2, Align2, CollapsingResponse, Color32, NumExt, Rangef, Rect, Vec2, Widget, + pos2, Align2, Button, CollapsingResponse, Color32, NumExt, Rangef, Rect, Vec2, Widget, }; -use crate::{ - design_tokens, icons, - list_item::{self, LabelContent, ListItem}, - DesignTokens, Icon, LabelStyle, SUCCESS_COLOR, -}; +use crate::{design_tokens, icons, list_item, DesignTokens, Icon, LabelStyle, SUCCESS_COLOR}; static FULL_SPAN_TAG: &str = "rerun_full_span"; @@ -973,16 +969,23 @@ pub trait UiExt { url: impl ToString, ) -> egui::Response { let ui = self.ui_mut(); - let response = ListItem::new() - .show_flat( - ui, - LabelContent::new(text).with_icon(&crate::icons::EXTERNAL_LINK), - ) - .on_hover_cursor(egui::CursorIcon::PointingHand); - if response.clicked() { - ui.ctx().open_url(egui::OpenUrl::new_tab(url)); - } - response + ui.scope(|ui| { + let style = ui.style_mut(); + style.visuals.button_frame = false; + + let tint = ui.style().visuals.widgets.noninteractive.fg_stroke.color; + let image = crate::icons::EXTERNAL_LINK.as_image().tint(tint); + let response = ui + .add(Button::image_and_text(image, text)) + .on_hover_cursor(egui::CursorIcon::PointingHand); + + if response.clicked() { + ui.ctx().open_url(egui::OpenUrl::new_tab(url)); + } + + response + }) + .response } /// Show some close/maximize/minimize buttons for the native window. diff --git a/crates/viewer/re_ui/src/ui_layout.rs b/crates/viewer/re_ui/src/ui_layout.rs index 4c6772b479d0d..3cec146fe151c 100644 --- a/crates/viewer/re_ui/src/ui_layout.rs +++ b/crates/viewer/re_ui/src/ui_layout.rs @@ -1,3 +1,7 @@ +use std::sync::Arc; + +use crate::UiExt as _; + /// Specifies the context in which the UI is used and the constraints it should follow. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UiLayout { @@ -95,6 +99,14 @@ impl UiLayout { self.data_label_impl(ui, string.as_ref()) } + fn decorate_url(ui: &mut egui::Ui, text: &str, galley: Arc) -> egui::Response { + if url::Url::parse(text).is_ok() { + ui.re_hyperlink(text, text) + } else { + ui.label(galley) + } + } + fn data_label_impl(self, ui: &mut egui::Ui, string: &str) -> egui::Response { let font_id = egui::TextStyle::Monospace.resolve(ui.style()); let color = ui.visuals().text_color(); @@ -102,8 +114,6 @@ impl UiLayout { let mut layout_job = egui::text::LayoutJob::simple(string.to_owned(), font_id, color, wrap_width); - let mut needs_scroll_area = false; - match self { Self::List => { layout_job.wrap.max_rows = 1; // We must fit on one line @@ -118,19 +128,11 @@ impl UiLayout { Self::Tooltip => { layout_job.wrap.max_rows = 3; } - Self::SelectionPanel => { - needs_scroll_area = false; - } + Self::SelectionPanel => {} } let galley = ui.fonts(|f| f.layout_job(layout_job)); // We control the text layout; not the label - if needs_scroll_area { - egui::ScrollArea::vertical() - .show(ui, |ui| ui.label(galley)) - .inner - } else { - ui.label(galley) - } + Self::decorate_url(ui, string, galley) } } diff --git a/crates/viewer/re_viewer_context/src/component_ui_registry.rs b/crates/viewer/re_viewer_context/src/component_ui_registry.rs index c8fda4abfc794..a83ef8b874b34 100644 --- a/crates/viewer/re_viewer_context/src/component_ui_registry.rs +++ b/crates/viewer/re_viewer_context/src/component_ui_registry.rs @@ -259,7 +259,7 @@ impl ComponentUiRegistry { // Component UI can only show a single instance. if array.len() == 0 || (instance.is_all() && array.len() > 1) { - none_or_many_values_ui(ui, array.len()); + (*self.fallback_ui)(ctx, ui, ui_layout, query, db, entity_path, None, &array); return; } @@ -305,7 +305,16 @@ impl ComponentUiRegistry { re_tracing::profile_function!(component_name.full_name()); if component_raw.len() != 1 { - none_or_many_values_ui(ui, component_raw.len()); + (*self.fallback_ui)( + ctx, + ui, + ui_layout, + query, + db, + entity_path, + row_id, + component_raw, + ); return; } @@ -548,11 +557,3 @@ fn try_deserialize(value: &dyn arrow::array::Array) -> O } } } - -fn none_or_many_values_ui(ui: &mut egui::Ui, num_instances: usize) { - if num_instances == 0 { - ui.label("(empty)"); - } else { - ui.label(format!("{} values", re_format::format_uint(num_instances))); - } -} diff --git a/docs/content/howto/logging/custom-data.md b/docs/content/howto/logging/custom-data.md index 93636ebad1028..477034f29aeec 100644 --- a/docs/content/howto/logging/custom-data.md +++ b/docs/content/howto/logging/custom-data.md @@ -3,15 +3,19 @@ title: Send user-defined data order: 200 description: How to use Rerun with custom data --- + Rerun comes with many pre-built [Types](../../reference/types.md) that you can use out of the box. As long as your own data can be decomposed into Rerun [components](../../reference/types/components.md) or can be serialized with [Apache Arrow](https://arrow.apache.org/), you can log it directly without needing to recompile Rerun. For Python we have a helper for this, called [`AnyValues`](https://ref.rerun.io/docs/python/main/common/custom_data/), allowing you to easily attach custom values to any entity instance: -``` +```python rr.log( "my_entity", rr.AnyValues( confidence=[1.2, 3.4, 5.6], description="Bla bla bla…", + # URIs will become clickable links + homepage="https://www.rerun.io", + repository="https://github.com/rerun-io/rerun", ), ) ``` @@ -19,7 +23,9 @@ rr.log( You can also create your own component by implementing the `AsComponents` [Python protocol](https://ref.rerun.io/docs/python/0.9.0/common/interfaces/#rerun.AsComponents) or [Rust trait](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html), which means implementing the function, `as_component_batches()`. ## Remapping to a Rerun archetype + Let's start with a simple example where you have your own point cloud class that is perfectly representable as a Rerun archetype. + ```python @dataclass class LabeledPoints: @@ -47,6 +53,7 @@ rr.log("points/classified", classified) ``` ## Custom archetypes and components + You can also define and log your own custom archetypes and components completely from user code, without rebuilding Rerun. In this example we extend the Rerun Points3D archetype with custom confidence and indicator components. diff --git a/docs/snippets/all/tutorials/any_values.py b/docs/snippets/all/tutorials/any_values.py index 156cc56f1d69b..4a31762900dca 100644 --- a/docs/snippets/all/tutorials/any_values.py +++ b/docs/snippets/all/tutorials/any_values.py @@ -9,5 +9,8 @@ rr.AnyValues( confidence=[1.2, 3.4, 5.6], description="Bla bla bla…", + # URIs will become clickable links + homepage="https://www.rerun.io", + repository="https://github.com/rerun-io/rerun", ), ) diff --git a/docs/snippets/all/tutorials/any_values.rs b/docs/snippets/all/tutorials/any_values.rs index 198484d16fa89..ef90c9a8b870e 100644 --- a/docs/snippets/all/tutorials/any_values.rs +++ b/docs/snippets/all/tutorials/any_values.rs @@ -17,7 +17,25 @@ fn main() -> Result<(), Box> { rerun::ComponentDescriptor::new("description"), ); - rec.log("any_values", &[confidences, description])?; + // URIs will become clickable links + let homepage = rerun::SerializedComponentBatch::new( + Arc::new(arrow::array::StringArray::from(vec![ + "https://www.rerun.io", + ])), + rerun::ComponentDescriptor::new("homepage"), + ); + + let repository = rerun::SerializedComponentBatch::new( + Arc::new(arrow::array::StringArray::from(vec![ + "https://github.com/rerun-io/rerun", + ])), + rerun::ComponentDescriptor::new("repository"), + ); + + rec.log( + "any_values", + &[confidences, description, homepage, repository], + )?; Ok(()) } diff --git a/rerun_py/rerun_sdk/rerun/any_value.py b/rerun_py/rerun_sdk/rerun/any_value.py index 9178738d99ec3..51e8bb84c6b11 100644 --- a/rerun_py/rerun_sdk/rerun/any_value.py +++ b/rerun_py/rerun_sdk/rerun/any_value.py @@ -160,6 +160,9 @@ class AnyValues(AsComponents): "any_values", rr.AnyValues( confidence=[1.2, 3.4, 5.6], description="Bla bla bla…", + # URIs will become clickable links + homepage="https://www.rerun.io", + repository="https://github.com/rerun-io/rerun", ), ) ``` From f85eb755ac4695ad8a76b92d7068c08179fc6680 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 30 Jan 2025 17:47:03 +0100 Subject: [PATCH 42/43] Implement range selection with shift-click in the time panel (#8870) --- Cargo.lock | 1 + crates/viewer/re_time_panel/Cargo.toml | 3 +- crates/viewer/re_time_panel/src/lib.rs | 469 ++++++++++++------ .../re_time_panel/src/streams_tree_data.rs | 81 ++- 4 files changed, 383 insertions(+), 171 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ddaa39c683fac..918a384072397 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6566,6 +6566,7 @@ dependencies = [ "re_log_types", "re_tracing", "re_types", + "re_types_core", "re_ui", "re_viewer_context", "re_viewport_blueprint", diff --git a/crates/viewer/re_time_panel/Cargo.toml b/crates/viewer/re_time_panel/Cargo.toml index efa8d2341ac03..bbd635ef16ea1 100644 --- a/crates/viewer/re_time_panel/Cargo.toml +++ b/crates/viewer/re_time_panel/Cargo.toml @@ -25,10 +25,11 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_format.workspace = true re_int_histogram.workspace = true -re_log_types.workspace = true re_log.workspace = true +re_log_types.workspace = true re_tracing.workspace = true re_types.workspace = true +re_types_core.workspace = true re_ui.workspace = true re_viewer_context.workspace = true re_viewport_blueprint.workspace = true diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 9227bce26426d..ccd6451b5c044 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -15,28 +15,27 @@ mod time_selection_ui; use std::sync::Arc; use egui::emath::Rangef; -use egui::{pos2, Color32, CursorIcon, NumExt, Painter, PointerButton, Rect, Shape, Ui, Vec2}; - -use re_context_menu::{ - context_menu_ui_for_item, context_menu_ui_for_item_with_context, SelectionUpdateBehavior, +use egui::{ + pos2, Color32, CursorIcon, NumExt, Painter, PointerButton, Rect, Response, Shape, Ui, Vec2, }; +use re_context_menu::{context_menu_ui_for_item_with_context, SelectionUpdateBehavior}; +use re_data_ui::item_ui::guess_instance_path_icon; use re_data_ui::DataUi as _; -use re_data_ui::{item_ui::guess_instance_path_icon, sorted_component_list_for_ui}; use re_entity_db::{EntityDb, InstancePath}; use re_log_types::{ - external::re_types_core::ComponentName, ApplicationId, ComponentPath, EntityPath, - ResolvedTimeRange, TimeInt, TimeReal, TimeType, + ApplicationId, ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, TimeReal, TimeType, }; use re_types::blueprint::components::PanelState; +use re_types_core::ComponentName; use re_ui::filter_widget::format_matching_text; use re_ui::{filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _}; use re_viewer_context::{ CollapseScope, HoverHighlight, Item, ItemContext, RecordingConfig, TimeControl, TimeView, - UiLayout, ViewerContext, + UiLayout, ViewerContext, VisitorControlFlow, }; use re_viewport_blueprint::ViewportBlueprint; -use crate::streams_tree_data::EntityData; +use crate::streams_tree_data::{components_for_entity, EntityData, StreamsTreeData}; use recursive_chunks_per_timeline_subscriber::PathRecursiveChunksPerTimelineStoreSubscriber; use time_axis::TimelineAxis; use time_control_ui::TimeControlUi; @@ -148,6 +147,13 @@ pub struct TimePanel { /// recording with a different application id. #[serde(skip)] filter_state_app_id: Option, + + /// Range selection anchor item. + /// + /// This is the item we used as a starting point for range selection. It is set and remembered + /// everytime the user clicks on an item _without_ holding shift. + #[serde(skip)] + range_selection_anchor_item: Option, } impl Default for TimePanel { @@ -163,6 +169,7 @@ impl Default for TimePanel { source: TimePanelSource::Recording, filter_state: Default::default(), filter_state_app_id: None, + range_selection_anchor_item: None, } } } @@ -622,17 +629,18 @@ impl TimePanel { let filter_matcher = self.filter_state.filter(); - let entity_tree_data = + let streams_tree_data = crate::streams_tree_data::StreamsTreeData::from_source_and_filter( ctx, self.source, &filter_matcher, ); - for child in &entity_tree_data.children { + for child in &streams_tree_data.children { self.show_entity( ctx, viewport_blueprint, + &streams_tree_data, entity_db, time_ctrl, time_area_response, @@ -650,6 +658,7 @@ impl TimePanel { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + streams_tree_data: &StreamsTreeData, entity_db: &re_entity_db::EntityDb, time_ctrl: &mut TimeControl, time_area_response: &egui::Response, @@ -715,6 +724,7 @@ impl TimePanel { self.show_entity_contents( ctx, viewport_blueprint, + streams_tree_data, entity_db, time_ctrl, time_area_response, @@ -746,19 +756,15 @@ impl TimePanel { } } - context_menu_ui_for_item_with_context( + self.handle_interactions_for_item( ctx, viewport_blueprint, - &item.to_item(), - // expand/collapse context menu actions need this information - ItemContext::StreamsTree { - store_kind: self.source.into(), - filter_session_id: self.filter_state.session_id(), - }, + streams_tree_data, + entity_db, + item.to_item(), &response, - SelectionUpdateBehavior::UseSelection, + true, ); - ctx.handle_select_hover_drag_interactions(&response, item.to_item(), true); let is_closed = body_response.is_none(); let response_rect = response.rect; @@ -814,6 +820,7 @@ impl TimePanel { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + streams_tree_data: &StreamsTreeData, entity_db: &re_entity_db::EntityDb, time_ctrl: &mut TimeControl, time_area_response: &egui::Response, @@ -827,6 +834,7 @@ impl TimePanel { self.show_entity( ctx, viewport_blueprint, + streams_tree_data, entity_db, time_ctrl, time_area_response, @@ -840,164 +848,297 @@ impl TimePanel { let engine = entity_db.storage_engine(); let store = engine.store(); - // If this is an entity: - if let Some(components) = store.all_components_for_entity(entity_path) { - for component_name in sorted_component_list_for_ui(components.iter()) { - let is_static = store.entity_has_static_component(entity_path, &component_name); + for component_name in components_for_entity(store, entity_path) { + let is_static = store.entity_has_static_component(entity_path, &component_name); + + let component_path = ComponentPath::new(entity_path.clone(), component_name); + let short_component_name = component_path.component_name.short_name(); + let item = TimePanelItem::component_path(component_path.clone()); + let timeline = time_ctrl.timeline(); + + let response = ui + .list_item() + .render_offscreen(false) + .selected(ctx.selection().contains_item(&item.to_item())) + .force_hovered( + ctx.selection_state() + .highlight_for_ui_element(&item.to_item()) + == HoverHighlight::Hovered, + ) + .show_hierarchical( + ui, + list_item::LabelContent::new(short_component_name) + .with_icon(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT_TEMPORAL + }) + .truncate(false), + ); - let component_path = ComponentPath::new(entity_path.clone(), component_name); - let short_component_name = component_path.component_name.short_name(); - let item = TimePanelItem::component_path(component_path.clone()); - let timeline = time_ctrl.timeline(); + self.handle_interactions_for_item( + ctx, + viewport_blueprint, + streams_tree_data, + entity_db, + item.to_item(), + &response, + false, + ); - let response = ui - .list_item() - .render_offscreen(false) - .selected(ctx.selection().contains_item(&item.to_item())) - .force_hovered( - ctx.selection_state() - .highlight_for_ui_element(&item.to_item()) - == HoverHighlight::Hovered, - ) - .show_hierarchical( + let response_rect = response.rect; + + response.on_hover_ui(|ui| { + let num_static_messages = + store.num_static_events_for_component(entity_path, component_name); + let num_temporal_messages = store.num_temporal_events_for_component_on_timeline( + time_ctrl.timeline(), + entity_path, + component_name, + ); + let total_num_messages = num_static_messages + num_temporal_messages; + + if total_num_messages == 0 { + ui.label(ui.ctx().warning_text(format!( + "No event logged on timeline {:?}", + timeline.name() + ))); + } else { + list_item::list_item_scope(ui, "hover tooltip", |ui| { + let kind = if is_static { "Static" } else { "Temporal" }; + + let num_messages = if is_static { + num_static_messages + } else { + num_temporal_messages + }; + + let num_messages = if num_messages == 1 { + "once".to_owned() + } else { + format!("{} times", re_format::format_uint(num_messages)) + }; + + ui.list_item() + .interactive(false) + .render_offscreen(false) + .show_flat( + ui, + list_item::LabelContent::new(format!( + "{kind} component, logged {num_messages}" + )) + .truncate(false) + .with_icon(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT_TEMPORAL + }), + ); + + // Static components are not displayed at all on the timeline, so cannot be + // previewed there. So we display their content in this tooltip instead. + // Conversely, temporal components change over time, and so showing a specific instance here + // can be confusing. + if is_static { + let query = re_chunk_store::LatestAtQuery::new( + *time_ctrl.timeline(), + TimeInt::MAX, + ); + let ui_layout = UiLayout::Tooltip; + component_path.data_ui(ctx, ui, ui_layout, &query, entity_db); + } + }); + } + }); + + self.next_col_right = self.next_col_right.max(response_rect.right()); + + // From the left of the label, all the way to the right-most of the time panel + let full_width_rect = Rect::from_x_y_ranges( + response_rect.left()..=ui.max_rect().right(), + response_rect.y_range(), + ); + + let is_visible = ui.is_rect_visible(full_width_rect); + + if is_visible { + let component_has_data_in_current_timeline = store + .entity_has_component_on_timeline( + time_ctrl.timeline(), + entity_path, + &component_name, + ); + + if component_has_data_in_current_timeline { + // show the data in the time area: + let row_rect = Rect::from_x_y_ranges( + time_area_response.rect.x_range(), + response_rect.y_range(), + ); + + highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); + + 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, + db, + time_area_painter, ui, - list_item::LabelContent::new(short_component_name) - .with_icon(if is_static { - &re_ui::icons::COMPONENT_STATIC - } else { - &re_ui::icons::COMPONENT_TEMPORAL - }) - .truncate(false), + &self.time_ranges_ui, + row_rect, + &item, + true, ); + } + } + } + } - context_menu_ui_for_item( + #[expect(clippy::too_many_arguments)] + fn handle_interactions_for_item( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + item: Item, + response: &egui::Response, + is_draggable: bool, + ) { + context_menu_ui_for_item_with_context( + ctx, + viewport_blueprint, + &item, + // expand/collapse context menu actions need this information + ItemContext::StreamsTree { + store_kind: self.source.into(), + filter_session_id: self.filter_state.session_id(), + }, + response, + SelectionUpdateBehavior::UseSelection, + ); + ctx.handle_select_hover_drag_interactions(response, item.clone(), is_draggable); + + self.handle_range_selection(ctx, streams_tree_data, entity_db, item, response); + } + + /// Handle setting/extending the selection based on shift-clicking. + fn handle_range_selection( + &mut self, + ctx: &ViewerContext<'_>, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + item: Item, + response: &Response, + ) { + // Early out if we're not being clicked. + if !response.clicked() { + return; + } + + let modifiers = ctx.egui_ctx.input(|i| i.modifiers); + + if modifiers.shift { + if let Some(anchor_item) = &self.range_selection_anchor_item { + let items_in_range = Self::items_in_range( ctx, - viewport_blueprint, - &item.to_item(), - &response, - SelectionUpdateBehavior::UseSelection, + streams_tree_data, + entity_db, + self.collapse_scope(), + anchor_item, + &item, ); - ctx.handle_select_hover_drag_interactions(&response, item.to_item(), false); - - let response_rect = response.rect; - - response.on_hover_ui(|ui| { - let num_static_messages = - store.num_static_events_for_component(entity_path, component_name); - let num_temporal_messages = store - .num_temporal_events_for_component_on_timeline( - time_ctrl.timeline(), - entity_path, - component_name, - ); - let total_num_messages = num_static_messages + num_temporal_messages; - - if total_num_messages == 0 { - ui.label(ui.ctx().warning_text(format!( - "No event logged on timeline {:?}", - timeline.name() - ))); + + if items_in_range.is_empty() { + // This can happen if the last clicked item became invisible due to collapsing, or if + // the user switched to another recording. In either case, we invalidate it. + self.range_selection_anchor_item = None; + } else { + let items_iterator = items_in_range.into_iter().map(|item| { + ( + item, + Some(ItemContext::BlueprintTree { + filter_session_id: self.filter_state.session_id(), + }), + ) + }); + + if modifiers.command { + ctx.selection_state.extend_selection(items_iterator); } else { - list_item::list_item_scope(ui, "hover tooltip", |ui| { - let kind = if is_static { "Static" } else { "Temporal" }; - - let num_messages = if is_static { - num_static_messages - } else { - num_temporal_messages - }; - - let num_messages = if num_messages == 1 { - "once".to_owned() - } else { - format!("{} times", re_format::format_uint(num_messages)) - }; - - ui.list_item() - .interactive(false) - .render_offscreen(false) - .show_flat( - ui, - list_item::LabelContent::new(format!( - "{kind} component, logged {num_messages}" - )) - .truncate(false) - .with_icon(if is_static { - &re_ui::icons::COMPONENT_STATIC - } else { - &re_ui::icons::COMPONENT_TEMPORAL - }), - ); - - // Static components are not displayed at all on the timeline, so cannot be - // previewed there. So we display their content in this tooltip instead. - // Conversely, temporal components change over time, and so showing a specific instance here - // can be confusing. - if is_static { - let query = re_chunk_store::LatestAtQuery::new( - *time_ctrl.timeline(), - TimeInt::MAX, - ); - let ui_layout = UiLayout::Tooltip; - component_path.data_ui(ctx, ui, ui_layout, &query, entity_db); - } - }); + ctx.selection_state.set_selection(items_iterator); } - }); + } + } + } else { + self.range_selection_anchor_item = Some(item); + } + } - self.next_col_right = self.next_col_right.max(response_rect.right()); + /// Selects a range of items in the streams tree. + /// + /// This method selects all [`Item`]s displayed between the provided shift-clicked item and the + /// existing last-clicked item (if any). It takes into account the collapsed state, so only + /// actually visible items may be selected. + fn items_in_range( + ctx: &ViewerContext<'_>, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + collapse_scope: CollapseScope, + anchor_item: &Item, + shift_clicked_item: &Item, + ) -> Vec { + let mut items_in_range = vec![]; + let mut found_last_clicked_items = false; + let mut found_shift_clicked_items = false; + + streams_tree_data.visit(entity_db, |entity_data, component_name| { + let item = if let Some(component_name) = component_name { + Item::ComponentPath(ComponentPath::new( + entity_data.entity_path.clone(), + component_name, + )) + } else { + entity_data.item() + }; - // From the left of the label, all the way to the right-most of the time panel - let full_width_rect = Rect::from_x_y_ranges( - response_rect.left()..=ui.max_rect().right(), - response_rect.y_range(), - ); + if &item == anchor_item { + found_last_clicked_items = true; + } - let is_visible = ui.is_rect_visible(full_width_rect); - - if is_visible { - let component_has_data_in_current_timeline = store - .entity_has_component_on_timeline( - time_ctrl.timeline(), - entity_path, - &component_name, - ); - - if component_has_data_in_current_timeline { - // show the data in the time area: - let row_rect = Rect::from_x_y_ranges( - time_area_response.rect.x_range(), - response_rect.y_range(), - ); - - highlight_timeline_row( - ui, - ctx, - time_area_painter, - &item.to_item(), - &row_rect, - ); - - let db = match self.source { - TimePanelSource::Recording => ctx.recording(), - TimePanelSource::Blueprint => ctx.store_context.blueprint, - }; + if &item == shift_clicked_item { + found_shift_clicked_items = true; + } - data_density_graph::data_density_graph_ui( - &mut self.data_density_graph_painter, - ctx, - time_ctrl, - db, - time_area_painter, - ui, - &self.time_ranges_ui, - row_rect, - &item, - true, - ); - } - } + if found_last_clicked_items || found_shift_clicked_items { + items_in_range.push(item); + } + + if found_last_clicked_items && found_shift_clicked_items { + return VisitorControlFlow::Break(()); } + + let is_expanded = entity_data + .is_open(ctx.egui_ctx, collapse_scope) + .unwrap_or(false); + + if is_expanded { + VisitorControlFlow::Continue + } else { + VisitorControlFlow::SkipBranch + } + }); + + if !found_last_clicked_items { + vec![] + } else { + items_in_range } } diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs index 596750fcf7f79..c498cbb5a9ee5 100644 --- a/crates/viewer/re_time_panel/src/streams_tree_data.rs +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -1,14 +1,16 @@ -use std::ops::Range; +use std::ops::{ControlFlow, Range}; use itertools::Itertools as _; -use smallvec::SmallVec; -use re_entity_db::EntityTree; +use crate::TimePanelSource; +use re_chunk_store::ChunkStore; +use re_data_ui::sorted_component_list_for_ui; +use re_entity_db::{EntityTree, InstancePath}; use re_log_types::EntityPath; +use re_types_core::ComponentName; use re_ui::filter_widget::FilterMatcher; -use re_viewer_context::ViewerContext; - -use crate::TimePanelSource; +use re_viewer_context::{CollapseScope, Item, ViewerContext, VisitorControlFlow}; +use smallvec::SmallVec; #[derive(Debug)] pub struct StreamsTreeData { @@ -46,6 +48,31 @@ impl StreamsTreeData { }, } } + + /// Visit the entire tree. + /// + /// Note that we ALSO visit components, despite them not being part of the data structures. This + /// is because _currently_, we rarely need to visit, but when we do, we need to components, and + /// having them in the structure would be too expensive for the cases where it's unnecessary + /// (e.g., when the tree is collapsed). + /// + /// The provided closure is called once for each entity with `None` as component name argument. + /// Then, consistent with the display order, its children entities are visited, and then its + /// components are visited. + pub fn visit( + &self, + entity_db: &re_entity_db::EntityDb, + mut visitor: impl FnMut(&EntityData, Option) -> VisitorControlFlow, + ) -> ControlFlow { + let engine = entity_db.storage_engine(); + let store = engine.store(); + + for child in &self.children { + child.visit(store, &mut visitor)?; + } + + ControlFlow::Continue(()) + } } // --- @@ -149,4 +176,46 @@ impl EntityData { }) } } + + /// Visit this entity, included its components in the provided store. + pub fn visit( + &self, + store: &ChunkStore, + visitor: &mut impl FnMut(&Self, Option) -> VisitorControlFlow, + ) -> ControlFlow { + if visitor(self, None).visit_children()? { + for child in &self.children { + child.visit(store, visitor)?; + } + + for component_name in components_for_entity(store, &self.entity_path) { + // these cannot have children + let _ = visitor(self, Some(component_name)).visit_children()?; + } + } + + ControlFlow::Continue(()) + } + + pub fn item(&self) -> Item { + Item::InstancePath(InstancePath::entity_all(self.entity_path.clone())) + } + + pub fn is_open(&self, ctx: &egui::Context, collapse_scope: CollapseScope) -> Option { + collapse_scope + .item(self.item()) + .map(|collapse_id| collapse_id.is_open(ctx).unwrap_or(self.default_open)) + } +} + +/// Lists the components to be displayed for the given entity +pub fn components_for_entity( + store: &ChunkStore, + entity_path: &EntityPath, +) -> impl Iterator { + if let Some(components) = store.all_components_for_entity(entity_path) { + itertools::Either::Left(sorted_component_list_for_ui(components.iter()).into_iter()) + } else { + itertools::Either::Right(std::iter::empty()) + } } From a83ba77cca4affe0b6d0944971a007eeb7154abd Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 30 Jan 2025 18:41:29 +0100 Subject: [PATCH 43/43] `re_time_panel`: no longer cram everything in `lib.rs` (#8873) --- .../re_time_panel/src/data_density_graph.rs | 2 +- crates/viewer/re_time_panel/src/lib.rs | 1739 +---------------- .../re_time_panel/src/streams_tree_data.rs | 5 +- crates/viewer/re_time_panel/src/time_panel.rs | 1739 +++++++++++++++++ 4 files changed, 1746 insertions(+), 1739 deletions(-) create mode 100644 crates/viewer/re_time_panel/src/time_panel.rs diff --git a/crates/viewer/re_time_panel/src/data_density_graph.rs b/crates/viewer/re_time_panel/src/data_density_graph.rs index 6c8f539665bd2..6fbaeb51b651a 100644 --- a/crates/viewer/re_time_panel/src/data_density_graph.rs +++ b/crates/viewer/re_time_panel/src/data_density_graph.rs @@ -14,7 +14,7 @@ use re_log_types::{ComponentPath, ResolvedTimeRange, TimeInt, Timeline}; use re_viewer_context::{Item, TimeControl, UiLayout, ViewerContext}; use crate::recursive_chunks_per_timeline_subscriber::PathRecursiveChunksPerTimelineStoreSubscriber; -use crate::TimePanelItem; +use crate::time_panel::TimePanelItem; use super::time_ranges_ui::TimeRangesUi; diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index ccd6451b5c044..a5d367f1a42f7 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -9,1748 +9,15 @@ mod recursive_chunks_per_timeline_subscriber; mod streams_tree_data; mod time_axis; mod time_control_ui; +mod time_panel; mod time_ranges_ui; mod time_selection_ui; -use std::sync::Arc; - -use egui::emath::Rangef; -use egui::{ - pos2, Color32, CursorIcon, NumExt, Painter, PointerButton, Rect, Response, Shape, Ui, Vec2, -}; -use re_context_menu::{context_menu_ui_for_item_with_context, SelectionUpdateBehavior}; -use re_data_ui::item_ui::guess_instance_path_icon; -use re_data_ui::DataUi as _; -use re_entity_db::{EntityDb, InstancePath}; -use re_log_types::{ - ApplicationId, ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, TimeReal, TimeType, -}; -use re_types::blueprint::components::PanelState; -use re_types_core::ComponentName; -use re_ui::filter_widget::format_matching_text; -use re_ui::{filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _}; -use re_viewer_context::{ - CollapseScope, HoverHighlight, Item, ItemContext, RecordingConfig, TimeControl, TimeView, - UiLayout, ViewerContext, VisitorControlFlow, -}; -use re_viewport_blueprint::ViewportBlueprint; - -use crate::streams_tree_data::{components_for_entity, EntityData, StreamsTreeData}; -use recursive_chunks_per_timeline_subscriber::PathRecursiveChunksPerTimelineStoreSubscriber; -use time_axis::TimelineAxis; -use time_control_ui::TimeControlUi; -use time_ranges_ui::TimeRangesUi; +pub use time_panel::TimePanel; #[doc(hidden)] pub mod __bench { pub use crate::data_density_graph::*; + pub use crate::time_panel::TimePanelItem; pub use crate::time_ranges_ui::TimeRangesUi; - pub use crate::TimePanelItem; -} - -#[derive(Debug, Clone)] -pub struct TimePanelItem { - pub entity_path: EntityPath, - pub component_name: Option, -} - -impl TimePanelItem { - pub fn entity_path(entity_path: EntityPath) -> Self { - Self { - entity_path, - component_name: None, - } - } - - pub fn component_path(component_path: ComponentPath) -> Self { - let ComponentPath { - entity_path, - component_name, - } = component_path; - Self { - entity_path, - component_name: Some(component_name), - } - } - - pub fn to_item(&self) -> Item { - let Self { - entity_path, - component_name, - } = self; - - if let Some(component_name) = component_name { - Item::ComponentPath(ComponentPath::new(entity_path.clone(), *component_name)) - } else { - Item::InstancePath(InstancePath::entity_all(entity_path.clone())) - } - } -} - -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)] -enum TimePanelSource { - #[default] - Recording, - Blueprint, -} - -impl From for egui::Id { - fn from(source: TimePanelSource) -> Self { - match source { - TimePanelSource::Recording => "recording".into(), - TimePanelSource::Blueprint => "blueprint".into(), - } - } -} - -impl From for re_log_types::StoreKind { - fn from(source: TimePanelSource) -> Self { - match source { - TimePanelSource::Recording => Self::Recording, - TimePanelSource::Blueprint => Self::Blueprint, - } - } -} - -/// A panel that shows entity names to the left, time on the top. -/// -/// This includes the timeline controls and streams view. -#[derive(serde::Deserialize, serde::Serialize)] -#[serde(default)] -pub struct TimePanel { - data_density_graph_painter: data_density_graph::DataDensityGraphPainter, - - /// Width of the entity name columns previous frame. - prev_col_width: f32, - - /// The right side of the entity name column; updated during its painting. - #[serde(skip)] - next_col_right: f32, - - /// The time axis view, regenerated each frame. - #[serde(skip)] - time_ranges_ui: TimeRangesUi, - - /// Ui elements for controlling time. - time_control_ui: TimeControlUi, - - /// Which source is the time panel controlling? - source: TimePanelSource, - - /// Filtering of entity paths shown in the panel (when expanded). - #[serde(skip)] - filter_state: filter_widget::FilterState, - - /// The store id the filter widget relates to. - /// - /// Used to invalidate the filter state (aka deactivate it) when the user switches to a - /// recording with a different application id. - #[serde(skip)] - filter_state_app_id: Option, - - /// Range selection anchor item. - /// - /// This is the item we used as a starting point for range selection. It is set and remembered - /// everytime the user clicks on an item _without_ holding shift. - #[serde(skip)] - range_selection_anchor_item: Option, -} - -impl Default for TimePanel { - fn default() -> Self { - Self::ensure_registered_subscribers(); - - Self { - data_density_graph_painter: Default::default(), - prev_col_width: 400.0, - next_col_right: 0.0, - time_ranges_ui: Default::default(), - time_control_ui: TimeControlUi, - source: TimePanelSource::Recording, - filter_state: Default::default(), - filter_state_app_id: None, - range_selection_anchor_item: None, - } - } -} - -impl TimePanel { - /// Ensures that all required store subscribers are correctly set up. - /// - /// This is implicitly called by [`Self::default`], but may need to be explicitly called in, - /// e.g., testing context. - pub fn ensure_registered_subscribers() { - PathRecursiveChunksPerTimelineStoreSubscriber::ensure_registered(); - } - - pub fn new_blueprint_panel() -> Self { - Self { - source: TimePanelSource::Blueprint, - ..Default::default() - } - } - - /// Activates the search filter (for e.g. test purposes). - pub fn activate_filter(&mut self, query: &str) { - self.filter_state.activate(query); - } - - #[allow(clippy::too_many_arguments)] - pub fn show_panel( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - entity_db: &re_entity_db::EntityDb, - rec_cfg: &RecordingConfig, - ui: &mut egui::Ui, - state: PanelState, - mut panel_frame: egui::Frame, - ) { - if state.is_hidden() { - return; - } - - // Invalidate the filter widget if the store id has changed. - if self.filter_state_app_id.as_ref() != Some(&ctx.store_context.app_id) { - self.filter_state = Default::default(); - self.filter_state_app_id = Some(ctx.store_context.app_id.clone()); - } - - self.data_density_graph_painter.begin_frame(ui.ctx()); - - // Naturally, many parts of the time panel need the time control. - // Copy it once, read/edit, and then write back at the end if there was a change. - let time_ctrl_before = rec_cfg.time_ctrl.read().clone(); - let mut time_ctrl_after = time_ctrl_before.clone(); - - // this is the size of everything above the central panel (window title bar, top bar on web, - // etc.) - let screen_header_height = ui.cursor().top(); - - if state.is_expanded() { - // Since we use scroll bars we want to fill the whole vertical space downwards: - panel_frame.inner_margin.bottom = 0; - - // Similarly, let the data get close to the right edge: - panel_frame.inner_margin.right = 0; - } - - let window_height = ui.ctx().screen_rect().height(); - - let id: egui::Id = self.source.into(); - - let collapsed = egui::TopBottomPanel::bottom(id.with("time_panel_collapsed")) - .resizable(false) - .show_separator_line(false) - .frame(panel_frame) - .default_height(44.0); - - let min_height = 150.0; - let min_top_space = 150.0 + screen_header_height; - let expanded = egui::TopBottomPanel::bottom(id.with("time_panel_expanded")) - .resizable(true) - .show_separator_line(false) - .frame(panel_frame) - .min_height(min_height) - .max_height((window_height - min_top_space).at_least(min_height).round()) - .default_height((0.25 * window_height).clamp(min_height, 250.0).round()); - - egui::TopBottomPanel::show_animated_between_inside( - ui, - state.is_expanded(), - collapsed, - expanded, - |ui: &mut egui::Ui, expansion: f32| { - if expansion < 1.0 { - // Collapsed or animating - ui.horizontal(|ui| { - ui.spacing_mut().interact_size = - Vec2::splat(re_ui::DesignTokens::top_bar_height()); - ui.visuals_mut().button_frame = true; - self.collapsed_ui(ctx, entity_db, ui, &mut time_ctrl_after); - }); - } else { - // Expanded: - self.show_expanded_with_header( - ctx, - viewport_blueprint, - entity_db, - &mut time_ctrl_after, - ui, - ); - } - }, - ); - - // Apply time control if there were any changes. - // This means that if anyone else meanwhile changed the time control, these changes are lost now. - // At least though we don't overwrite them if we didn't change anything at all. - // Since changes on the time control via the time panel are rare, this should be fine. - if time_ctrl_before != time_ctrl_after { - *rec_cfg.time_ctrl.write() = time_ctrl_after; - } - } - - pub fn show_expanded_with_header( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - entity_db: &EntityDb, - time_ctrl_after: &mut TimeControl, - ui: &mut Ui, - ) { - ui.vertical(|ui| { - // Add back the margin we removed from the panel: - let mut top_row_frame = egui::Frame::default(); - let margin = DesignTokens::bottom_panel_margin(); - top_row_frame.inner_margin.right = margin.right; - top_row_frame.inner_margin.bottom = margin.bottom; - let top_row_rect = top_row_frame - .show(ui, |ui| { - ui.horizontal(|ui| { - ui.spacing_mut().interact_size = - Vec2::splat(re_ui::DesignTokens::top_bar_height()); - ui.visuals_mut().button_frame = true; - self.top_row_ui(ctx, entity_db, ui, time_ctrl_after); - }); - }) - .response - .rect; - - // Draw separator between top bar and the rest: - ui.painter().hline( - 0.0..=top_row_rect.right(), - top_row_rect.bottom(), - ui.visuals().widgets.noninteractive.bg_stroke, - ); - - ui.spacing_mut().scroll.bar_outer_margin = 4.0; // needed, because we have no panel margin on the right side. - - // Add extra margin on the left which was intentionally missing on the controls. - let mut streams_frame = egui::Frame::default(); - streams_frame.inner_margin.left = margin.left; - streams_frame.show(ui, |ui| { - self.expanded_ui(ctx, viewport_blueprint, entity_db, ui, time_ctrl_after); - }); - }); - } - - #[allow(clippy::unused_self)] - fn collapsed_ui( - &mut self, - ctx: &ViewerContext<'_>, - entity_db: &re_entity_db::EntityDb, - ui: &mut egui::Ui, - time_ctrl: &mut TimeControl, - ) { - ui.spacing_mut().item_spacing.x = 18.0; // from figma - - let time_range = entity_db.time_range_for(time_ctrl.timeline()); - let has_more_than_one_time_point = - time_range.is_some_and(|time_range| time_range.min() != time_range.max()); - - if ui.max_rect().width() < 600.0 && has_more_than_one_time_point { - // Responsive ui for narrow screens, e.g. mobile. Split the controls into two rows. - ui.vertical(|ui| { - if has_more_than_one_time_point { - ui.horizontal(|ui| { - let times_per_timeline = entity_db.times_per_timeline(); - self.time_control_ui - .play_pause_ui(time_ctrl, times_per_timeline, ui); - - self.time_control_ui.playback_speed_ui(time_ctrl, ui); - self.time_control_ui.fps_ui(time_ctrl, ui); - }); - } - ui.horizontal(|ui| { - self.time_control_ui.timeline_selector_ui( - time_ctrl, - entity_db.times_per_timeline(), - ui, - ); - collapsed_time_marker_and_time( - ui, - ctx, - &mut self.data_density_graph_painter, - entity_db, - time_ctrl, - ); - }); - }); - } else { - // One row: - let times_per_timeline = entity_db.times_per_timeline(); - - if has_more_than_one_time_point { - self.time_control_ui - .play_pause_ui(time_ctrl, times_per_timeline, ui); - } - - self.time_control_ui - .timeline_selector_ui(time_ctrl, times_per_timeline, ui); - - if has_more_than_one_time_point { - self.time_control_ui.playback_speed_ui(time_ctrl, ui); - self.time_control_ui.fps_ui(time_ctrl, ui); - } - - collapsed_time_marker_and_time( - ui, - ctx, - &mut self.data_density_graph_painter, - entity_db, - time_ctrl, - ); - } - } - - fn expanded_ui( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - entity_db: &re_entity_db::EntityDb, - ui: &mut egui::Ui, - time_ctrl: &mut TimeControl, - ) { - re_tracing::profile_function!(); - - // |timeline | - // ------------------------------------ - // tree |streams | - // | . . . . . . | - // | . . . . | - // ▲ - // └ tree_max_y (= time_x_left) - - // We use this to track what the rightmost coordinate for the tree section should be. We - // clamp it to a minimum of 150.0px for the filter widget to behave correctly even when the - // tree is fully collapsed (and thus narrow). - self.next_col_right = ui.min_rect().left() + 150.0; - - let time_x_left = - (ui.min_rect().left() + self.prev_col_width + ui.spacing().item_spacing.x) - .at_most(ui.max_rect().right() - 100.0) - .at_least(80.); // cover the empty recording case - - // Where the time will be shown. - let time_bg_x_range = Rangef::new(time_x_left, ui.max_rect().right()); - let time_fg_x_range = { - // Painting to the right of the scroll bar (if any) looks bad: - let right = ui.max_rect().right() - ui.spacing_mut().scroll.bar_outer_margin; - debug_assert!(time_x_left < right); - Rangef::new(time_x_left, right) - }; - - let side_margin = 26.0; // chosen so that the scroll bar looks approximately centered in the default gap - self.time_ranges_ui = initialize_time_ranges_ui( - entity_db, - time_ctrl, - Rangef::new( - time_fg_x_range.min + side_margin, - time_fg_x_range.max - side_margin, - ), - time_ctrl.time_view(), - ); - let full_y_range = Rangef::new(ui.min_rect().bottom(), ui.max_rect().bottom()); - - let timeline_rect = { - let top = ui.min_rect().bottom(); - - ui.add_space(-4.0); // hack to vertically center the text - - let size = egui::vec2(self.prev_col_width, 27.0); - ui.allocate_ui_with_layout(size, egui::Layout::top_down(egui::Align::LEFT), |ui| { - ui.set_min_size(size); - ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend); - ui.spacing_mut().item_spacing.y = 0.0; - - ui.full_span_scope(0.0..=time_x_left, |ui| { - self.filter_state.ui( - ui, - egui::RichText::new(if self.source == TimePanelSource::Blueprint { - "Blueprint Streams" - } else { - "Streams" - }) - .strong(), - ); - }); - }) - .response - .on_hover_text( - "A hierarchical view of the paths used during logging.\n\ - \n\ - On the right you can see when there was a log event for a stream.", - ); - - let bottom = ui.min_rect().bottom(); - Rect::from_x_y_ranges(time_fg_x_range, top..=bottom) - }; - - let streams_rect = Rect::from_x_y_ranges( - time_fg_x_range, - timeline_rect.bottom()..=ui.max_rect().bottom(), - ); - - // includes the timeline and streams areas. - let time_bg_area_rect = Rect::from_x_y_ranges(time_bg_x_range, full_y_range); - let time_fg_area_rect = Rect::from_x_y_ranges(time_fg_x_range, full_y_range); - let time_bg_area_painter = ui.painter().with_clip_rect(time_bg_area_rect); - let time_area_painter = ui.painter().with_clip_rect(time_fg_area_rect); - - if let Some(highlighted_range) = time_ctrl.highlighted_range { - paint_range_highlight( - highlighted_range, - &self.time_ranges_ui, - ui.painter(), - time_fg_area_rect, - ); - } - - ui.painter().hline( - 0.0..=ui.max_rect().right(), - timeline_rect.bottom(), - ui.visuals().widgets.noninteractive.bg_stroke, - ); - - paint_ticks::paint_time_ranges_and_ticks( - &self.time_ranges_ui, - ui, - &time_area_painter, - timeline_rect.top()..=timeline_rect.bottom(), - time_ctrl.time_type(), - ctx.app_options.time_zone, - ); - paint_time_ranges_gaps( - &self.time_ranges_ui, - ui, - &time_bg_area_painter, - full_y_range, - ); - time_selection_ui::loop_selection_ui( - time_ctrl, - &self.time_ranges_ui, - ui, - &time_bg_area_painter, - &timeline_rect, - ); - let time_area_response = interact_with_streams_rect( - &self.time_ranges_ui, - time_ctrl, - ui, - &time_bg_area_rect, - &streams_rect, - ); - - // Don't draw on top of the time ticks - let lower_time_area_painter = ui.painter().with_clip_rect(Rect::from_x_y_ranges( - time_fg_x_range, - ui.min_rect().bottom()..=ui.max_rect().bottom(), - )); - - // All the entity rows and their data density graphs - ui.full_span_scope(0.0..=time_x_left, |ui| { - list_item::list_item_scope(ui, "streams_tree", |ui| { - self.tree_ui( - ctx, - viewport_blueprint, - entity_db, - time_ctrl, - &time_area_response, - &lower_time_area_painter, - ui, - ); - }); - }); - - { - // Paint a shadow between the stream names on the left - // and the data on the right: - let shadow_width = 30.0; - - // In the design the shadow starts under the time markers. - //let shadow_y_start = - // timeline_rect.bottom() + ui.visuals().widgets.noninteractive.bg_stroke.width; - // This looks great but only if there are still time markers. - // When they move to the right (or have a cut) one expects the shadow to go all the way up. - // But that's quite complicated so let's have the shadow all the way - let shadow_y_start = full_y_range.min; - - let shadow_y_end = full_y_range.max; - let rect = egui::Rect::from_x_y_ranges( - time_x_left..=(time_x_left + shadow_width), - shadow_y_start..=shadow_y_end, - ); - ui.draw_shadow_line(rect, egui::Direction::LeftToRight); - } - - // Put time-marker on top and last, so that you can always drag it - time_marker_ui( - &self.time_ranges_ui, - time_ctrl, - ui, - Some(&time_area_response), - &time_area_painter, - &timeline_rect, - ); - - self.time_ranges_ui.snap_time_control(time_ctrl); - - // remember where to show the time for next frame: - self.prev_col_width = self.next_col_right - ui.min_rect().left(); - } - - // All the entity rows and their data density graphs: - #[expect(clippy::too_many_arguments)] - fn tree_ui( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - entity_db: &re_entity_db::EntityDb, - time_ctrl: &mut TimeControl, - time_area_response: &egui::Response, - time_area_painter: &egui::Painter, - ui: &mut egui::Ui, - ) { - re_tracing::profile_function!(); - - egui::ScrollArea::vertical() - .auto_shrink([false; 2]) - // We turn off `drag_to_scroll` so that the `ScrollArea` don't steal input from - // the earlier `interact_with_time_area`. - // We implement drag-to-scroll manually instead! - .drag_to_scroll(false) - .show(ui, |ui| { - ui.spacing_mut().item_spacing.y = 0.0; // no spacing needed for ListItems - - if time_area_response.dragged_by(PointerButton::Primary) { - ui.scroll_with_delta(Vec2::Y * time_area_response.drag_delta().y); - } - - let filter_matcher = self.filter_state.filter(); - - let streams_tree_data = - crate::streams_tree_data::StreamsTreeData::from_source_and_filter( - ctx, - self.source, - &filter_matcher, - ); - - for child in &streams_tree_data.children { - self.show_entity( - ctx, - viewport_blueprint, - &streams_tree_data, - entity_db, - time_ctrl, - time_area_response, - time_area_painter, - child, - ui, - ); - } - }); - } - - /// Display the list item for an entity. - #[expect(clippy::too_many_arguments)] - fn show_entity( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - streams_tree_data: &StreamsTreeData, - entity_db: &re_entity_db::EntityDb, - time_ctrl: &mut TimeControl, - time_area_response: &egui::Response, - time_area_painter: &egui::Painter, - entity_data: &EntityData, - ui: &mut egui::Ui, - ) { - re_tracing::profile_function!(); - - let entity_path = &entity_data.entity_path; - let item = TimePanelItem::entity_path(entity_path.clone()); - let is_selected = ctx.selection().contains_item(&item.to_item()); - let is_item_hovered = ctx - .selection_state() - .highlight_for_ui_element(&item.to_item()) - == HoverHighlight::Hovered; - - let collapse_scope = self.collapse_scope(); - - // Expand if one of the children is focused - let focused_entity_path = ctx - .focused_item - .as_ref() - .and_then(|item| item.entity_path()); - - if focused_entity_path.is_some_and(|entity_path| entity_path.is_descendant_of(entity_path)) - { - collapse_scope - .entity(entity_path.clone()) - .set_open(ui.ctx(), true); - } - - // Globally unique id that is dependent on the "nature" of the tree (recording or blueprint, - // in a filter session or not) - let id = collapse_scope.entity(entity_path.clone()).into(); - - let list_item::ShowCollapsingResponse { - item_response: response, - body_response, - .. - } = ui - .list_item() - .render_offscreen(false) - .selected(is_selected) - .draggable(true) - .force_hovered(is_item_hovered) - .show_hierarchical_with_children( - ui, - id, - entity_data.default_open, - list_item::LabelContent::new(format_matching_text( - ctx.egui_ctx, - &entity_data.label, - entity_data.highlight_sections.iter().cloned(), - None, - )) - .with_icon(guess_instance_path_icon( - ctx, - &InstancePath::from(entity_path.clone()), - )) - .truncate(false), - |ui| { - self.show_entity_contents( - ctx, - viewport_blueprint, - streams_tree_data, - entity_db, - time_ctrl, - time_area_response, - time_area_painter, - entity_data, - ui, - ); - }, - ); - - let response = response.on_hover_ui(|ui| { - let include_subtree = true; - re_data_ui::item_ui::entity_hover_card_ui( - ui, - ctx, - &time_ctrl.current_query(), - entity_db, - entity_path, - include_subtree, - ); - }); - - if Some(entity_path) == focused_entity_path { - // Scroll only if the entity isn't already visible. This is important because that's what - // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be - // annoying to induce a scroll motion. - if !ui.clip_rect().contains_rect(response.rect) { - response.scroll_to_me(Some(egui::Align::Center)); - } - } - - self.handle_interactions_for_item( - ctx, - viewport_blueprint, - streams_tree_data, - entity_db, - item.to_item(), - &response, - true, - ); - - let is_closed = body_response.is_none(); - let response_rect = response.rect; - self.next_col_right = self.next_col_right.max(response_rect.right()); - - // - // Display the data density graph only if it is visible. - // - - // From the left of the label, all the way to the right-most of the time panel - let full_width_rect = Rect::from_x_y_ranges( - response_rect.left()..=ui.max_rect().right(), - response_rect.y_range(), - ); - - let is_visible = ui.is_rect_visible(full_width_rect); - if is_visible { - let tree_has_data_in_current_timeline = entity_db.subtree_has_data_on_timeline( - &entity_db.storage_engine(), - time_ctrl.timeline(), - entity_path, - ); - if tree_has_data_in_current_timeline { - let row_rect = Rect::from_x_y_ranges( - time_area_response.rect.x_range(), - response_rect.y_range(), - ); - - highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); - - // show the density graph only if that item is closed - if is_closed { - data_density_graph::data_density_graph_ui( - &mut self.data_density_graph_painter, - ctx, - time_ctrl, - entity_db, - time_area_painter, - ui, - &self.time_ranges_ui, - row_rect, - &item, - true, - ); - } - } - } - } - - /// Display the contents of an entity, i.e. its sub-entities and its components. - #[expect(clippy::too_many_arguments)] - fn show_entity_contents( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - streams_tree_data: &StreamsTreeData, - entity_db: &re_entity_db::EntityDb, - time_ctrl: &mut TimeControl, - time_area_response: &egui::Response, - time_area_painter: &egui::Painter, - entity_data: &EntityData, - ui: &mut egui::Ui, - ) { - re_tracing::profile_function!(); - - for child in &entity_data.children { - self.show_entity( - ctx, - viewport_blueprint, - streams_tree_data, - entity_db, - time_ctrl, - time_area_response, - time_area_painter, - child, - ui, - ); - } - - let entity_path = &entity_data.entity_path; - let engine = entity_db.storage_engine(); - let store = engine.store(); - - for component_name in components_for_entity(store, entity_path) { - let is_static = store.entity_has_static_component(entity_path, &component_name); - - let component_path = ComponentPath::new(entity_path.clone(), component_name); - let short_component_name = component_path.component_name.short_name(); - let item = TimePanelItem::component_path(component_path.clone()); - let timeline = time_ctrl.timeline(); - - let response = ui - .list_item() - .render_offscreen(false) - .selected(ctx.selection().contains_item(&item.to_item())) - .force_hovered( - ctx.selection_state() - .highlight_for_ui_element(&item.to_item()) - == HoverHighlight::Hovered, - ) - .show_hierarchical( - ui, - list_item::LabelContent::new(short_component_name) - .with_icon(if is_static { - &re_ui::icons::COMPONENT_STATIC - } else { - &re_ui::icons::COMPONENT_TEMPORAL - }) - .truncate(false), - ); - - self.handle_interactions_for_item( - ctx, - viewport_blueprint, - streams_tree_data, - entity_db, - item.to_item(), - &response, - false, - ); - - let response_rect = response.rect; - - response.on_hover_ui(|ui| { - let num_static_messages = - store.num_static_events_for_component(entity_path, component_name); - let num_temporal_messages = store.num_temporal_events_for_component_on_timeline( - time_ctrl.timeline(), - entity_path, - component_name, - ); - let total_num_messages = num_static_messages + num_temporal_messages; - - if total_num_messages == 0 { - ui.label(ui.ctx().warning_text(format!( - "No event logged on timeline {:?}", - timeline.name() - ))); - } else { - list_item::list_item_scope(ui, "hover tooltip", |ui| { - let kind = if is_static { "Static" } else { "Temporal" }; - - let num_messages = if is_static { - num_static_messages - } else { - num_temporal_messages - }; - - let num_messages = if num_messages == 1 { - "once".to_owned() - } else { - format!("{} times", re_format::format_uint(num_messages)) - }; - - ui.list_item() - .interactive(false) - .render_offscreen(false) - .show_flat( - ui, - list_item::LabelContent::new(format!( - "{kind} component, logged {num_messages}" - )) - .truncate(false) - .with_icon(if is_static { - &re_ui::icons::COMPONENT_STATIC - } else { - &re_ui::icons::COMPONENT_TEMPORAL - }), - ); - - // Static components are not displayed at all on the timeline, so cannot be - // previewed there. So we display their content in this tooltip instead. - // Conversely, temporal components change over time, and so showing a specific instance here - // can be confusing. - if is_static { - let query = re_chunk_store::LatestAtQuery::new( - *time_ctrl.timeline(), - TimeInt::MAX, - ); - let ui_layout = UiLayout::Tooltip; - component_path.data_ui(ctx, ui, ui_layout, &query, entity_db); - } - }); - } - }); - - self.next_col_right = self.next_col_right.max(response_rect.right()); - - // From the left of the label, all the way to the right-most of the time panel - let full_width_rect = Rect::from_x_y_ranges( - response_rect.left()..=ui.max_rect().right(), - response_rect.y_range(), - ); - - let is_visible = ui.is_rect_visible(full_width_rect); - - if is_visible { - let component_has_data_in_current_timeline = store - .entity_has_component_on_timeline( - time_ctrl.timeline(), - entity_path, - &component_name, - ); - - if component_has_data_in_current_timeline { - // show the data in the time area: - let row_rect = Rect::from_x_y_ranges( - time_area_response.rect.x_range(), - response_rect.y_range(), - ); - - highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); - - 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, - db, - time_area_painter, - ui, - &self.time_ranges_ui, - row_rect, - &item, - true, - ); - } - } - } - } - - #[expect(clippy::too_many_arguments)] - fn handle_interactions_for_item( - &mut self, - ctx: &ViewerContext<'_>, - viewport_blueprint: &ViewportBlueprint, - streams_tree_data: &StreamsTreeData, - entity_db: &re_entity_db::EntityDb, - item: Item, - response: &egui::Response, - is_draggable: bool, - ) { - context_menu_ui_for_item_with_context( - ctx, - viewport_blueprint, - &item, - // expand/collapse context menu actions need this information - ItemContext::StreamsTree { - store_kind: self.source.into(), - filter_session_id: self.filter_state.session_id(), - }, - response, - SelectionUpdateBehavior::UseSelection, - ); - ctx.handle_select_hover_drag_interactions(response, item.clone(), is_draggable); - - self.handle_range_selection(ctx, streams_tree_data, entity_db, item, response); - } - - /// Handle setting/extending the selection based on shift-clicking. - fn handle_range_selection( - &mut self, - ctx: &ViewerContext<'_>, - streams_tree_data: &StreamsTreeData, - entity_db: &re_entity_db::EntityDb, - item: Item, - response: &Response, - ) { - // Early out if we're not being clicked. - if !response.clicked() { - return; - } - - let modifiers = ctx.egui_ctx.input(|i| i.modifiers); - - if modifiers.shift { - if let Some(anchor_item) = &self.range_selection_anchor_item { - let items_in_range = Self::items_in_range( - ctx, - streams_tree_data, - entity_db, - self.collapse_scope(), - anchor_item, - &item, - ); - - if items_in_range.is_empty() { - // This can happen if the last clicked item became invisible due to collapsing, or if - // the user switched to another recording. In either case, we invalidate it. - self.range_selection_anchor_item = None; - } else { - let items_iterator = items_in_range.into_iter().map(|item| { - ( - item, - Some(ItemContext::BlueprintTree { - filter_session_id: self.filter_state.session_id(), - }), - ) - }); - - if modifiers.command { - ctx.selection_state.extend_selection(items_iterator); - } else { - ctx.selection_state.set_selection(items_iterator); - } - } - } - } else { - self.range_selection_anchor_item = Some(item); - } - } - - /// Selects a range of items in the streams tree. - /// - /// This method selects all [`Item`]s displayed between the provided shift-clicked item and the - /// existing last-clicked item (if any). It takes into account the collapsed state, so only - /// actually visible items may be selected. - fn items_in_range( - ctx: &ViewerContext<'_>, - streams_tree_data: &StreamsTreeData, - entity_db: &re_entity_db::EntityDb, - collapse_scope: CollapseScope, - anchor_item: &Item, - shift_clicked_item: &Item, - ) -> Vec { - let mut items_in_range = vec![]; - let mut found_last_clicked_items = false; - let mut found_shift_clicked_items = false; - - streams_tree_data.visit(entity_db, |entity_data, component_name| { - let item = if let Some(component_name) = component_name { - Item::ComponentPath(ComponentPath::new( - entity_data.entity_path.clone(), - component_name, - )) - } else { - entity_data.item() - }; - - if &item == anchor_item { - found_last_clicked_items = true; - } - - if &item == shift_clicked_item { - found_shift_clicked_items = true; - } - - if found_last_clicked_items || found_shift_clicked_items { - items_in_range.push(item); - } - - if found_last_clicked_items && found_shift_clicked_items { - return VisitorControlFlow::Break(()); - } - - let is_expanded = entity_data - .is_open(ctx.egui_ctx, collapse_scope) - .unwrap_or(false); - - if is_expanded { - VisitorControlFlow::Continue - } else { - VisitorControlFlow::SkipBranch - } - }); - - if !found_last_clicked_items { - vec![] - } else { - items_in_range - } - } - - fn top_row_ui( - &self, - ctx: &ViewerContext<'_>, - entity_db: &re_entity_db::EntityDb, - ui: &mut egui::Ui, - time_ctrl: &mut TimeControl, - ) { - ui.spacing_mut().item_spacing.x = 18.0; // from figma - - if ui.max_rect().width() < 600.0 { - // Responsive ui for narrow screens, e.g. mobile. Split the controls into two rows. - ui.vertical(|ui| { - ui.horizontal(|ui| { - let times_per_timeline = entity_db.times_per_timeline(); - self.time_control_ui - .play_pause_ui(time_ctrl, times_per_timeline, ui); - self.time_control_ui.playback_speed_ui(time_ctrl, ui); - self.time_control_ui.fps_ui(time_ctrl, ui); - }); - ui.horizontal(|ui| { - self.time_control_ui.timeline_selector_ui( - time_ctrl, - entity_db.times_per_timeline(), - ui, - ); - - current_time_ui(ctx, ui, time_ctrl); - - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - help_button(ui); - }); - }); - }); - } else { - // One row: - let times_per_timeline = entity_db.times_per_timeline(); - - self.time_control_ui - .play_pause_ui(time_ctrl, times_per_timeline, ui); - self.time_control_ui - .timeline_selector_ui(time_ctrl, times_per_timeline, ui); - self.time_control_ui.playback_speed_ui(time_ctrl, ui); - self.time_control_ui.fps_ui(time_ctrl, ui); - current_time_ui(ctx, ui, time_ctrl); - - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - help_button(ui); - }); - } - } - - fn collapse_scope(&self) -> CollapseScope { - match (self.source, self.filter_state.session_id()) { - (TimePanelSource::Recording, None) => CollapseScope::StreamsTree, - - (TimePanelSource::Blueprint, None) => CollapseScope::BlueprintStreamsTree, - - (TimePanelSource::Recording, Some(session_id)) => { - CollapseScope::StreamsTreeFiltered { session_id } - } - - (TimePanelSource::Blueprint, Some(session_id)) => { - CollapseScope::BlueprintStreamsTreeFiltered { session_id } - } - } - } -} - -/// Draw the hovered/selected highlight background for a timeline row. -fn highlight_timeline_row( - ui: &Ui, - ctx: &ViewerContext<'_>, - painter: &Painter, - item: &Item, - row_rect: &Rect, -) { - let item_hovered = - ctx.selection_state().highlight_for_ui_element(item) == HoverHighlight::Hovered; - let item_selected = ctx.selection().contains_item(item); - let bg_color = if item_selected { - Some(ui.visuals().selection.bg_fill.gamma_multiply(0.4)) - } else if item_hovered { - Some( - ui.visuals() - .widgets - .hovered - .weak_bg_fill - .gamma_multiply(0.3), - ) - } else { - None - }; - if let Some(bg_color) = bg_color { - painter.rect_filled(*row_rect, egui::Rounding::ZERO, bg_color); - } -} - -fn collapsed_time_marker_and_time( - ui: &mut egui::Ui, - ctx: &ViewerContext<'_>, - data_density_graph_painter: &mut data_density_graph::DataDensityGraphPainter, - entity_db: &re_entity_db::EntityDb, - time_ctrl: &mut TimeControl, -) { - let timeline = time_ctrl.timeline(); - - let Some(time_range) = entity_db.time_range_for(timeline) else { - // We have no data on this timeline - return; - }; - - if time_range.min() == time_range.max() { - // Only one time point - showing a slider that can't be moved is just annoying - } else { - let space_needed_for_current_time = match timeline.typ() { - re_chunk_store::TimeType::Time => 220.0, - re_chunk_store::TimeType::Sequence => 100.0, - }; - - let mut time_range_rect = ui.available_rect_before_wrap(); - time_range_rect.max.x -= space_needed_for_current_time; - - if time_range_rect.width() > 50.0 { - ui.allocate_rect(time_range_rect, egui::Sense::hover()); - - let time_ranges_ui = - initialize_time_ranges_ui(entity_db, time_ctrl, time_range_rect.x_range(), None); - time_ranges_ui.snap_time_control(time_ctrl); - - let painter = ui.painter_at(time_range_rect.expand(4.0)); - - if let Some(highlighted_range) = time_ctrl.highlighted_range { - paint_range_highlight( - highlighted_range, - &time_ranges_ui, - &painter, - time_range_rect, - ); - } - - painter.hline( - time_range_rect.x_range(), - time_range_rect.center().y, - ui.visuals().widgets.noninteractive.fg_stroke, - ); - - data_density_graph::data_density_graph_ui( - data_density_graph_painter, - ctx, - time_ctrl, - entity_db, - ui.painter(), - ui, - &time_ranges_ui, - time_range_rect.shrink2(egui::vec2(0.0, 10.0)), - &TimePanelItem::entity_path(EntityPath::root()), - false, - ); - - time_marker_ui( - &time_ranges_ui, - time_ctrl, - ui, - None, - &painter, - &time_range_rect, - ); - } - } - - current_time_ui(ctx, ui, time_ctrl); -} - -fn paint_range_highlight( - highlighted_range: ResolvedTimeRange, - time_ranges_ui: &TimeRangesUi, - painter: &egui::Painter, - rect: Rect, -) { - let x_from = time_ranges_ui.x_from_time_f32(highlighted_range.min().into()); - let x_to = time_ranges_ui.x_from_time_f32(highlighted_range.max().into()); - - if let (Some(x_from), Some(x_to)) = (x_from, x_to) { - let visible_history_area_rect = - Rect::from_x_y_ranges(x_from..=x_to, rect.y_range()).intersect(rect); - - painter.rect( - visible_history_area_rect, - 0.0, - egui::Color32::WHITE.gamma_multiply(0.1), - egui::Stroke::NONE, - ); - } -} - -fn help_button(ui: &mut egui::Ui) { - // TODO(andreas): Nicer help text like on views. - ui.help_hover_button().on_hover_text( - "\ - In the top row you can drag to move the time, or shift-drag to select a loop region.\n\ - \n\ - Drag main area to pan.\n\ - Zoom: Ctrl/cmd + scroll, or drag up/down with secondary mouse button.\n\ - Double-click to reset view.\n\ - \n\ - Press the space bar to play/pause.", - ); -} - -fn current_time_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, time_ctrl: &mut TimeControl) { - if let Some(time_int) = time_ctrl.time_int() { - let time_type = time_ctrl.time_type(); - match time_type { - re_log_types::TimeType::Time => { - // TODO(#7653): parse time stamps - ui.monospace(time_type.format(time_int, ctx.app_options.time_zone)); - } - re_log_types::TimeType::Sequence => { - // NOTE: egui uses `f64` for all numbers internally, so we get precision problems if the integer gets too big. - if time_int.as_f64() as i64 == time_int.as_i64() { - let mut int = time_int.as_i64(); - let drag_value = egui::DragValue::new(&mut int) - .custom_formatter(|x, _range| { - TimeType::format_sequence(TimeInt::new_temporal(x as i64)) - }) - .custom_parser(|s| TimeType::parse_sequence(s).map(TimeInt::as_f64)); - let response = ui.add(drag_value); - if response.changed() { - time_ctrl.set_time(TimeInt::new_temporal(int)); - } - } else { - // Avoid the precision problems by just displaying the number without the ability to change it (here). - ui.monospace(time_type.format(time_int, ctx.app_options.time_zone)); - } - } - } - } -} - -// ---------------------------------------------------------------------------- - -fn initialize_time_ranges_ui( - entity_db: &re_entity_db::EntityDb, - time_ctrl: &TimeControl, - time_x_range: Rangef, - mut time_view: Option, -) -> TimeRangesUi { - re_tracing::profile_function!(); - - let mut time_range = Vec::new(); - - if let Some(times) = entity_db.time_histogram(time_ctrl.timeline()) { - // NOTE: `times` can be empty if a GC wiped everything. - if !times.is_empty() { - let timeline_axis = TimelineAxis::new(time_ctrl.time_type(), times); - time_view = time_view.or_else(|| Some(view_everything(&time_x_range, &timeline_axis))); - time_range.extend(timeline_axis.ranges); - } - } - - TimeRangesUi::new( - time_x_range, - time_view.unwrap_or(TimeView { - min: TimeReal::from(0), - time_spanned: 1.0, - }), - &time_range, - ) -} - -/// Find a nice view of everything. -fn view_everything(x_range: &Rangef, timeline_axis: &TimelineAxis) -> TimeView { - let gap_width = time_ranges_ui::gap_width(x_range, &timeline_axis.ranges) as f32; - let num_gaps = timeline_axis.ranges.len().saturating_sub(1); - let width = x_range.span(); - let width_sans_gaps = width - num_gaps as f32 * gap_width; - - let factor = if width_sans_gaps > 0.0 { - width / width_sans_gaps - } else { - 1.0 // too narrow to fit everything anyway - }; - - let min = timeline_axis.min(); - let time_spanned = timeline_axis.sum_time_lengths() as f64 * factor as f64; - - TimeView { - min: min.into(), - time_spanned, - } -} - -/// Visually separate the different time segments -fn paint_time_ranges_gaps( - time_ranges_ui: &TimeRangesUi, - ui: &egui::Ui, - painter: &egui::Painter, - y_range: Rangef, -) { - re_tracing::profile_function!(); - - // For each gap we are painting this: - // - // zig width - // | - // <-> - // \ / ^ - // \ / | zig height - // \ / v - // / \ - // / \ - // / \ - // \ / - // \ / - // \ / - // / \ - // / \ - // / \ - // - // <---------> - // gap width - // - // Filled with a dark color, plus a stroke and a small drop shadow to the left. - - use itertools::Itertools as _; - - let Rangef { - min: top, - max: bottom, - } = y_range; - - let fill_color = ui.visuals().widgets.noninteractive.bg_fill; - let stroke = ui.visuals().widgets.noninteractive.bg_stroke; - - let paint_time_gap = |gap_left: f32, gap_right: f32| { - let gap_width = gap_right - gap_left; - let zig_width = 4.0_f32.at_most(gap_width / 3.0).at_least(1.0); - let zig_height = zig_width; - let shadow_width = 12.0; - - let mut y = top; - let mut row = 0; // 0 = start wide, 1 = start narrow - - let mut mesh = egui::Mesh::default(); - let mut shadow_mesh = egui::Mesh::default(); - let mut left_line_strip = vec![]; - let mut right_line_strip = vec![]; - - while y - zig_height <= bottom { - let (left, right) = if row % 2 == 0 { - // full width - (gap_left, gap_right) - } else { - // contracted - (gap_left + zig_width, gap_right - zig_width) - }; - - let left_pos = pos2(left, y); - let right_pos = pos2(right, y); - - if !mesh.is_empty() { - let next_left_vidx = mesh.vertices.len() as u32; - let next_right_vidx = next_left_vidx + 1; - let prev_left_vidx = next_left_vidx - 2; - let prev_right_vidx = next_right_vidx - 2; - - mesh.add_triangle(prev_left_vidx, next_left_vidx, prev_right_vidx); - mesh.add_triangle(next_left_vidx, prev_right_vidx, next_right_vidx); - } - - mesh.colored_vertex(left_pos, fill_color); - mesh.colored_vertex(right_pos, fill_color); - - shadow_mesh.colored_vertex(pos2(right - shadow_width, y), Color32::TRANSPARENT); - shadow_mesh - .colored_vertex(right_pos, re_ui::design_tokens().shadow_gradient_dark_start); - - left_line_strip.push(left_pos); - right_line_strip.push(right_pos); - - y += zig_height; - row += 1; - } - - // Regular & shadow mesh have the same topology! - shadow_mesh.indices.clone_from(&mesh.indices); - - painter.add(Shape::Mesh(Arc::new(mesh))); - painter.add(Shape::Mesh(Arc::new(shadow_mesh))); - painter.add(Shape::line(left_line_strip, stroke)); - painter.add(Shape::line(right_line_strip, stroke)); - }; - - let zig_zag_first_and_last_edges = true; - - if let Some(segment) = time_ranges_ui.segments.first() { - let gap_edge = *segment.x.start() as f32; - - if zig_zag_first_and_last_edges { - // Left side of first segment - paint as a very wide gap that we only see the right side of - paint_time_gap(gap_edge - 100_000.0, gap_edge); - } else { - painter.rect_filled( - Rect::from_min_max(pos2(gap_edge - 100_000.0, top), pos2(gap_edge, bottom)), - 0.0, - fill_color, - ); - painter.vline(gap_edge, y_range, stroke); - } - } - - for (a, b) in time_ranges_ui.segments.iter().tuple_windows() { - paint_time_gap(*a.x.end() as f32, *b.x.start() as f32); - } - - if let Some(segment) = time_ranges_ui.segments.last() { - let gap_edge = *segment.x.end() as f32; - if zig_zag_first_and_last_edges { - // Right side of last segment - paint as a very wide gap that we only see the left side of - paint_time_gap(gap_edge, gap_edge + 100_000.0); - } else { - painter.rect_filled( - Rect::from_min_max(pos2(gap_edge, top), pos2(gap_edge + 100_000.0, bottom)), - 0.0, - fill_color, - ); - painter.vline(gap_edge, y_range, stroke); - } - } -} - -/// Returns a scroll delta -#[must_use] -fn interact_with_streams_rect( - time_ranges_ui: &TimeRangesUi, - time_ctrl: &mut TimeControl, - ui: &egui::Ui, - full_rect: &Rect, - streams_rect: &Rect, -) -> egui::Response { - let pointer_pos = ui.input(|i| i.pointer.hover_pos()); - - let mut delta_x = 0.0; - let mut zoom_factor = 1.0; - - // Check for zoom/pan inputs (via e.g. horizontal scrolling) on the entire - // time area rectangle, including the timeline rect. - let full_rect_hovered = pointer_pos.is_some_and(|pointer_pos| full_rect.contains(pointer_pos)); - if full_rect_hovered { - ui.input(|input| { - delta_x += input.smooth_scroll_delta.x; - zoom_factor *= input.zoom_delta_2d().x; - }); - } - - // We only check for drags in the streams rect, - // because drags in the timeline rect should move the time - // (or create loop sections). - let response = ui.interact( - *streams_rect, - ui.id().with("time_area_interact"), - egui::Sense::click_and_drag(), - ); - if response.dragged_by(PointerButton::Primary) { - delta_x += response.drag_delta().x; - ui.ctx().set_cursor_icon(CursorIcon::AllScroll); - } - if response.dragged_by(PointerButton::Secondary) { - zoom_factor *= (response.drag_delta().y * 0.01).exp(); - } - - if delta_x != 0.0 { - if let Some(new_view_range) = time_ranges_ui.pan(-delta_x) { - time_ctrl.set_time_view(new_view_range); - } - } - - if zoom_factor != 1.0 { - if let Some(pointer_pos) = pointer_pos { - if let Some(new_view_range) = time_ranges_ui.zoom_at(pointer_pos.x, zoom_factor) { - time_ctrl.set_time_view(new_view_range); - } - } - } - - if response.double_clicked() { - time_ctrl.reset_time_view(); - } - - response -} - -/// A vertical line that shows the current time. -fn time_marker_ui( - time_ranges_ui: &TimeRangesUi, - time_ctrl: &mut TimeControl, - ui: &egui::Ui, - time_area_response: Option<&egui::Response>, - time_area_painter: &egui::Painter, - timeline_rect: &Rect, -) { - // timeline_rect: top part with the second ticks and time marker - - let pointer_pos = ui.input(|i| i.pointer.hover_pos()); - let time_drag_id = ui.id().with("time_drag_id"); - let timeline_cursor_icon = CursorIcon::ResizeHorizontal; - let is_hovering_the_loop_selection = ui.output(|o| o.cursor_icon) != CursorIcon::Default; // A kind of hacky proxy - let is_anything_being_dragged = ui.ctx().dragged_id().is_some(); - let time_area_double_clicked = time_area_response.is_some_and(|resp| resp.double_clicked()); - let interact_radius = ui.style().interaction.resize_grab_radius_side; - - let mut is_hovering_time_cursor = false; - - // show current time as a line: - if let Some(time) = time_ctrl.time() { - if let Some(mut x) = time_ranges_ui.x_from_time_f32(time) { - if timeline_rect.x_range().contains(x) { - let line_rect = - Rect::from_x_y_ranges(x..=x, timeline_rect.top()..=ui.max_rect().bottom()) - .expand(interact_radius); - - let sense = if time_area_double_clicked { - egui::Sense::hover() - } else { - egui::Sense::drag() - }; - - let response = ui - .interact(line_rect, time_drag_id, sense) - .on_hover_and_drag_cursor(timeline_cursor_icon); - - is_hovering_time_cursor = response.hovered(); - - if response.dragged() { - if let Some(pointer_pos) = pointer_pos { - if let Some(time) = time_ranges_ui.time_from_x_f32(pointer_pos.x) { - let time = time_ranges_ui.clamp_time(time); - time_ctrl.set_time(time); - time_ctrl.pause(); - - x = pointer_pos.x; // avoid frame-delay - } - } - } - - ui.paint_time_cursor( - time_area_painter, - &response, - x, - Rangef::new(timeline_rect.top(), ui.max_rect().bottom()), - ); - } - } - } - - // "click here to view time here" - if let Some(pointer_pos) = pointer_pos { - let is_pointer_in_time_area_rect = - ui.ui_contains_pointer() && time_area_painter.clip_rect().contains(pointer_pos); - let is_pointer_in_timeline_rect = - ui.ui_contains_pointer() && timeline_rect.contains(pointer_pos); - - // Show preview? - if !is_hovering_time_cursor - && !time_area_double_clicked - && is_pointer_in_time_area_rect - && !is_anything_being_dragged - && !is_hovering_the_loop_selection - { - time_area_painter.vline( - pointer_pos.x, - timeline_rect.top()..=ui.max_rect().bottom(), - ui.visuals().widgets.noninteractive.fg_stroke, - ); - ui.ctx().set_cursor_icon(timeline_cursor_icon); // preview! - } - - // Click to move time here: - let time_area_response = ui.interact( - time_area_painter.clip_rect(), - ui.id().with("time_area_painter_id"), - egui::Sense::click(), - ); - - if !is_hovering_the_loop_selection { - let mut set_time_to_pointer = || { - if let Some(time) = time_ranges_ui.time_from_x_f32(pointer_pos.x) { - let time = time_ranges_ui.clamp_time(time); - time_ctrl.set_time(time); - time_ctrl.pause(); - } - }; - - // click on timeline = set time + start drag - // click on time area = set time - // double click on time area = reset time - if !is_anything_being_dragged - && is_pointer_in_timeline_rect - && ui.input(|i| i.pointer.primary_down()) - { - set_time_to_pointer(); - ui.ctx().set_dragged_id(time_drag_id); - } else if is_pointer_in_time_area_rect { - if time_area_response.double_clicked() { - time_ctrl.reset_time_view(); - } else if time_area_response.clicked() && !is_anything_being_dragged { - set_time_to_pointer(); - } - } - } - } } diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs index c498cbb5a9ee5..54acda96c2144 100644 --- a/crates/viewer/re_time_panel/src/streams_tree_data.rs +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -1,8 +1,8 @@ use std::ops::{ControlFlow, Range}; use itertools::Itertools as _; +use smallvec::SmallVec; -use crate::TimePanelSource; use re_chunk_store::ChunkStore; use re_data_ui::sorted_component_list_for_ui; use re_entity_db::{EntityTree, InstancePath}; @@ -10,7 +10,8 @@ use re_log_types::EntityPath; use re_types_core::ComponentName; use re_ui::filter_widget::FilterMatcher; use re_viewer_context::{CollapseScope, Item, ViewerContext, VisitorControlFlow}; -use smallvec::SmallVec; + +use crate::time_panel::TimePanelSource; #[derive(Debug)] pub struct StreamsTreeData { diff --git a/crates/viewer/re_time_panel/src/time_panel.rs b/crates/viewer/re_time_panel/src/time_panel.rs new file mode 100644 index 0000000000000..c5f8658187e83 --- /dev/null +++ b/crates/viewer/re_time_panel/src/time_panel.rs @@ -0,0 +1,1739 @@ +use std::sync::Arc; + +use egui::emath::Rangef; +use egui::{ + pos2, Color32, CursorIcon, NumExt, Painter, PointerButton, Rect, Response, Shape, Ui, Vec2, +}; + +use re_context_menu::{context_menu_ui_for_item_with_context, SelectionUpdateBehavior}; +use re_data_ui::item_ui::guess_instance_path_icon; +use re_data_ui::DataUi as _; +use re_entity_db::{EntityDb, InstancePath}; +use re_log_types::{ + ApplicationId, ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, TimeReal, TimeType, +}; +use re_types::blueprint::components::PanelState; +use re_types_core::ComponentName; +use re_ui::filter_widget::format_matching_text; +use re_ui::{filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _}; +use re_viewer_context::{ + CollapseScope, HoverHighlight, Item, ItemContext, RecordingConfig, TimeControl, TimeView, + UiLayout, ViewerContext, VisitorControlFlow, +}; +use re_viewport_blueprint::ViewportBlueprint; + +use crate::{ + recursive_chunks_per_timeline_subscriber::PathRecursiveChunksPerTimelineStoreSubscriber, + streams_tree_data::{components_for_entity, EntityData, StreamsTreeData}, + time_axis::TimelineAxis, + time_control_ui::TimeControlUi, + time_ranges_ui::TimeRangesUi, + {data_density_graph, paint_ticks, time_ranges_ui, time_selection_ui}, +}; + +#[derive(Debug, Clone)] +pub struct TimePanelItem { + pub entity_path: EntityPath, + pub component_name: Option, +} + +impl TimePanelItem { + pub fn entity_path(entity_path: EntityPath) -> Self { + Self { + entity_path, + component_name: None, + } + } + + pub fn component_path(component_path: ComponentPath) -> Self { + let ComponentPath { + entity_path, + component_name, + } = component_path; + Self { + entity_path, + component_name: Some(component_name), + } + } + + pub fn to_item(&self) -> Item { + let Self { + entity_path, + component_name, + } = self; + + if let Some(component_name) = component_name { + Item::ComponentPath(ComponentPath::new(entity_path.clone(), *component_name)) + } else { + Item::InstancePath(InstancePath::entity_all(entity_path.clone())) + } + } +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)] +pub enum TimePanelSource { + #[default] + Recording, + Blueprint, +} + +impl From for egui::Id { + fn from(source: TimePanelSource) -> Self { + match source { + TimePanelSource::Recording => "recording".into(), + TimePanelSource::Blueprint => "blueprint".into(), + } + } +} + +impl From for re_log_types::StoreKind { + fn from(source: TimePanelSource) -> Self { + match source { + TimePanelSource::Recording => Self::Recording, + TimePanelSource::Blueprint => Self::Blueprint, + } + } +} + +/// A panel that shows entity names to the left, time on the top. +/// +/// This includes the timeline controls and streams view. +#[derive(serde::Deserialize, serde::Serialize)] +#[serde(default)] +pub struct TimePanel { + data_density_graph_painter: data_density_graph::DataDensityGraphPainter, + + /// Width of the entity name columns previous frame. + prev_col_width: f32, + + /// The right side of the entity name column; updated during its painting. + #[serde(skip)] + next_col_right: f32, + + /// The time axis view, regenerated each frame. + #[serde(skip)] + time_ranges_ui: TimeRangesUi, + + /// Ui elements for controlling time. + time_control_ui: TimeControlUi, + + /// Which source is the time panel controlling? + source: TimePanelSource, + + /// Filtering of entity paths shown in the panel (when expanded). + #[serde(skip)] + filter_state: filter_widget::FilterState, + + /// The store id the filter widget relates to. + /// + /// Used to invalidate the filter state (aka deactivate it) when the user switches to a + /// recording with a different application id. + #[serde(skip)] + filter_state_app_id: Option, + + /// Range selection anchor item. + /// + /// This is the item we used as a starting point for range selection. It is set and remembered + /// everytime the user clicks on an item _without_ holding shift. + #[serde(skip)] + range_selection_anchor_item: Option, +} + +impl Default for TimePanel { + fn default() -> Self { + Self::ensure_registered_subscribers(); + + Self { + data_density_graph_painter: Default::default(), + prev_col_width: 400.0, + next_col_right: 0.0, + time_ranges_ui: Default::default(), + time_control_ui: TimeControlUi, + source: TimePanelSource::Recording, + filter_state: Default::default(), + filter_state_app_id: None, + range_selection_anchor_item: None, + } + } +} + +impl TimePanel { + /// Ensures that all required store subscribers are correctly set up. + /// + /// This is implicitly called by [`Self::default`], but may need to be explicitly called in, + /// e.g., testing context. + pub fn ensure_registered_subscribers() { + PathRecursiveChunksPerTimelineStoreSubscriber::ensure_registered(); + } + + pub fn new_blueprint_panel() -> Self { + Self { + source: TimePanelSource::Blueprint, + ..Default::default() + } + } + + /// Activates the search filter (for e.g. test purposes). + pub fn activate_filter(&mut self, query: &str) { + self.filter_state.activate(query); + } + + #[allow(clippy::too_many_arguments)] + pub fn show_panel( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + entity_db: &re_entity_db::EntityDb, + rec_cfg: &RecordingConfig, + ui: &mut egui::Ui, + state: PanelState, + mut panel_frame: egui::Frame, + ) { + if state.is_hidden() { + return; + } + + // Invalidate the filter widget if the store id has changed. + if self.filter_state_app_id.as_ref() != Some(&ctx.store_context.app_id) { + self.filter_state = Default::default(); + self.filter_state_app_id = Some(ctx.store_context.app_id.clone()); + } + + self.data_density_graph_painter.begin_frame(ui.ctx()); + + // Naturally, many parts of the time panel need the time control. + // Copy it once, read/edit, and then write back at the end if there was a change. + let time_ctrl_before = rec_cfg.time_ctrl.read().clone(); + let mut time_ctrl_after = time_ctrl_before.clone(); + + // this is the size of everything above the central panel (window title bar, top bar on web, + // etc.) + let screen_header_height = ui.cursor().top(); + + if state.is_expanded() { + // Since we use scroll bars we want to fill the whole vertical space downwards: + panel_frame.inner_margin.bottom = 0; + + // Similarly, let the data get close to the right edge: + panel_frame.inner_margin.right = 0; + } + + let window_height = ui.ctx().screen_rect().height(); + + let id: egui::Id = self.source.into(); + + let collapsed = egui::TopBottomPanel::bottom(id.with("time_panel_collapsed")) + .resizable(false) + .show_separator_line(false) + .frame(panel_frame) + .default_height(44.0); + + let min_height = 150.0; + let min_top_space = 150.0 + screen_header_height; + let expanded = egui::TopBottomPanel::bottom(id.with("time_panel_expanded")) + .resizable(true) + .show_separator_line(false) + .frame(panel_frame) + .min_height(min_height) + .max_height((window_height - min_top_space).at_least(min_height).round()) + .default_height((0.25 * window_height).clamp(min_height, 250.0).round()); + + egui::TopBottomPanel::show_animated_between_inside( + ui, + state.is_expanded(), + collapsed, + expanded, + |ui: &mut egui::Ui, expansion: f32| { + if expansion < 1.0 { + // Collapsed or animating + ui.horizontal(|ui| { + ui.spacing_mut().interact_size = + Vec2::splat(re_ui::DesignTokens::top_bar_height()); + ui.visuals_mut().button_frame = true; + self.collapsed_ui(ctx, entity_db, ui, &mut time_ctrl_after); + }); + } else { + // Expanded: + self.show_expanded_with_header( + ctx, + viewport_blueprint, + entity_db, + &mut time_ctrl_after, + ui, + ); + } + }, + ); + + // Apply time control if there were any changes. + // This means that if anyone else meanwhile changed the time control, these changes are lost now. + // At least though we don't overwrite them if we didn't change anything at all. + // Since changes on the time control via the time panel are rare, this should be fine. + if time_ctrl_before != time_ctrl_after { + *rec_cfg.time_ctrl.write() = time_ctrl_after; + } + } + + pub fn show_expanded_with_header( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + entity_db: &EntityDb, + time_ctrl_after: &mut TimeControl, + ui: &mut Ui, + ) { + ui.vertical(|ui| { + // Add back the margin we removed from the panel: + let mut top_row_frame = egui::Frame::default(); + let margin = DesignTokens::bottom_panel_margin(); + top_row_frame.inner_margin.right = margin.right; + top_row_frame.inner_margin.bottom = margin.bottom; + let top_row_rect = top_row_frame + .show(ui, |ui| { + ui.horizontal(|ui| { + ui.spacing_mut().interact_size = + Vec2::splat(re_ui::DesignTokens::top_bar_height()); + ui.visuals_mut().button_frame = true; + self.top_row_ui(ctx, entity_db, ui, time_ctrl_after); + }); + }) + .response + .rect; + + // Draw separator between top bar and the rest: + ui.painter().hline( + 0.0..=top_row_rect.right(), + top_row_rect.bottom(), + ui.visuals().widgets.noninteractive.bg_stroke, + ); + + ui.spacing_mut().scroll.bar_outer_margin = 4.0; // needed, because we have no panel margin on the right side. + + // Add extra margin on the left which was intentionally missing on the controls. + let mut streams_frame = egui::Frame::default(); + streams_frame.inner_margin.left = margin.left; + streams_frame.show(ui, |ui| { + self.expanded_ui(ctx, viewport_blueprint, entity_db, ui, time_ctrl_after); + }); + }); + } + + #[allow(clippy::unused_self)] + fn collapsed_ui( + &mut self, + ctx: &ViewerContext<'_>, + entity_db: &re_entity_db::EntityDb, + ui: &mut egui::Ui, + time_ctrl: &mut TimeControl, + ) { + ui.spacing_mut().item_spacing.x = 18.0; // from figma + + let time_range = entity_db.time_range_for(time_ctrl.timeline()); + let has_more_than_one_time_point = + time_range.is_some_and(|time_range| time_range.min() != time_range.max()); + + if ui.max_rect().width() < 600.0 && has_more_than_one_time_point { + // Responsive ui for narrow screens, e.g. mobile. Split the controls into two rows. + ui.vertical(|ui| { + if has_more_than_one_time_point { + ui.horizontal(|ui| { + let times_per_timeline = entity_db.times_per_timeline(); + self.time_control_ui + .play_pause_ui(time_ctrl, times_per_timeline, ui); + + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); + }); + } + ui.horizontal(|ui| { + self.time_control_ui.timeline_selector_ui( + time_ctrl, + entity_db.times_per_timeline(), + ui, + ); + collapsed_time_marker_and_time( + ui, + ctx, + &mut self.data_density_graph_painter, + entity_db, + time_ctrl, + ); + }); + }); + } else { + // One row: + let times_per_timeline = entity_db.times_per_timeline(); + + if has_more_than_one_time_point { + self.time_control_ui + .play_pause_ui(time_ctrl, times_per_timeline, ui); + } + + self.time_control_ui + .timeline_selector_ui(time_ctrl, times_per_timeline, ui); + + if has_more_than_one_time_point { + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); + } + + collapsed_time_marker_and_time( + ui, + ctx, + &mut self.data_density_graph_painter, + entity_db, + time_ctrl, + ); + } + } + + fn expanded_ui( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + entity_db: &re_entity_db::EntityDb, + ui: &mut egui::Ui, + time_ctrl: &mut TimeControl, + ) { + re_tracing::profile_function!(); + + // |timeline | + // ------------------------------------ + // tree |streams | + // | . . . . . . | + // | . . . . | + // ▲ + // └ tree_max_y (= time_x_left) + + // We use this to track what the rightmost coordinate for the tree section should be. We + // clamp it to a minimum of 150.0px for the filter widget to behave correctly even when the + // tree is fully collapsed (and thus narrow). + self.next_col_right = ui.min_rect().left() + 150.0; + + let time_x_left = + (ui.min_rect().left() + self.prev_col_width + ui.spacing().item_spacing.x) + .at_most(ui.max_rect().right() - 100.0) + .at_least(80.); // cover the empty recording case + + // Where the time will be shown. + let time_bg_x_range = Rangef::new(time_x_left, ui.max_rect().right()); + let time_fg_x_range = { + // Painting to the right of the scroll bar (if any) looks bad: + let right = ui.max_rect().right() - ui.spacing_mut().scroll.bar_outer_margin; + debug_assert!(time_x_left < right); + Rangef::new(time_x_left, right) + }; + + let side_margin = 26.0; // chosen so that the scroll bar looks approximately centered in the default gap + self.time_ranges_ui = initialize_time_ranges_ui( + entity_db, + time_ctrl, + Rangef::new( + time_fg_x_range.min + side_margin, + time_fg_x_range.max - side_margin, + ), + time_ctrl.time_view(), + ); + let full_y_range = Rangef::new(ui.min_rect().bottom(), ui.max_rect().bottom()); + + let timeline_rect = { + let top = ui.min_rect().bottom(); + + ui.add_space(-4.0); // hack to vertically center the text + + let size = egui::vec2(self.prev_col_width, 27.0); + ui.allocate_ui_with_layout(size, egui::Layout::top_down(egui::Align::LEFT), |ui| { + ui.set_min_size(size); + ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend); + ui.spacing_mut().item_spacing.y = 0.0; + + ui.full_span_scope(0.0..=time_x_left, |ui| { + self.filter_state.ui( + ui, + egui::RichText::new(if self.source == TimePanelSource::Blueprint { + "Blueprint Streams" + } else { + "Streams" + }) + .strong(), + ); + }); + }) + .response + .on_hover_text( + "A hierarchical view of the paths used during logging.\n\ + \n\ + On the right you can see when there was a log event for a stream.", + ); + + let bottom = ui.min_rect().bottom(); + Rect::from_x_y_ranges(time_fg_x_range, top..=bottom) + }; + + let streams_rect = Rect::from_x_y_ranges( + time_fg_x_range, + timeline_rect.bottom()..=ui.max_rect().bottom(), + ); + + // includes the timeline and streams areas. + let time_bg_area_rect = Rect::from_x_y_ranges(time_bg_x_range, full_y_range); + let time_fg_area_rect = Rect::from_x_y_ranges(time_fg_x_range, full_y_range); + let time_bg_area_painter = ui.painter().with_clip_rect(time_bg_area_rect); + let time_area_painter = ui.painter().with_clip_rect(time_fg_area_rect); + + if let Some(highlighted_range) = time_ctrl.highlighted_range { + paint_range_highlight( + highlighted_range, + &self.time_ranges_ui, + ui.painter(), + time_fg_area_rect, + ); + } + + ui.painter().hline( + 0.0..=ui.max_rect().right(), + timeline_rect.bottom(), + ui.visuals().widgets.noninteractive.bg_stroke, + ); + + paint_ticks::paint_time_ranges_and_ticks( + &self.time_ranges_ui, + ui, + &time_area_painter, + timeline_rect.top()..=timeline_rect.bottom(), + time_ctrl.time_type(), + ctx.app_options.time_zone, + ); + paint_time_ranges_gaps( + &self.time_ranges_ui, + ui, + &time_bg_area_painter, + full_y_range, + ); + time_selection_ui::loop_selection_ui( + time_ctrl, + &self.time_ranges_ui, + ui, + &time_bg_area_painter, + &timeline_rect, + ); + let time_area_response = interact_with_streams_rect( + &self.time_ranges_ui, + time_ctrl, + ui, + &time_bg_area_rect, + &streams_rect, + ); + + // Don't draw on top of the time ticks + let lower_time_area_painter = ui.painter().with_clip_rect(Rect::from_x_y_ranges( + time_fg_x_range, + ui.min_rect().bottom()..=ui.max_rect().bottom(), + )); + + // All the entity rows and their data density graphs + ui.full_span_scope(0.0..=time_x_left, |ui| { + list_item::list_item_scope(ui, "streams_tree", |ui| { + self.tree_ui( + ctx, + viewport_blueprint, + entity_db, + time_ctrl, + &time_area_response, + &lower_time_area_painter, + ui, + ); + }); + }); + + { + // Paint a shadow between the stream names on the left + // and the data on the right: + let shadow_width = 30.0; + + // In the design the shadow starts under the time markers. + //let shadow_y_start = + // timeline_rect.bottom() + ui.visuals().widgets.noninteractive.bg_stroke.width; + // This looks great but only if there are still time markers. + // When they move to the right (or have a cut) one expects the shadow to go all the way up. + // But that's quite complicated so let's have the shadow all the way + let shadow_y_start = full_y_range.min; + + let shadow_y_end = full_y_range.max; + let rect = egui::Rect::from_x_y_ranges( + time_x_left..=(time_x_left + shadow_width), + shadow_y_start..=shadow_y_end, + ); + ui.draw_shadow_line(rect, egui::Direction::LeftToRight); + } + + // Put time-marker on top and last, so that you can always drag it + time_marker_ui( + &self.time_ranges_ui, + time_ctrl, + ui, + Some(&time_area_response), + &time_area_painter, + &timeline_rect, + ); + + self.time_ranges_ui.snap_time_control(time_ctrl); + + // remember where to show the time for next frame: + self.prev_col_width = self.next_col_right - ui.min_rect().left(); + } + + // All the entity rows and their data density graphs: + #[expect(clippy::too_many_arguments)] + fn tree_ui( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + entity_db: &re_entity_db::EntityDb, + time_ctrl: &mut TimeControl, + time_area_response: &egui::Response, + time_area_painter: &egui::Painter, + ui: &mut egui::Ui, + ) { + re_tracing::profile_function!(); + + egui::ScrollArea::vertical() + .auto_shrink([false; 2]) + // We turn off `drag_to_scroll` so that the `ScrollArea` don't steal input from + // the earlier `interact_with_time_area`. + // We implement drag-to-scroll manually instead! + .drag_to_scroll(false) + .show(ui, |ui| { + ui.spacing_mut().item_spacing.y = 0.0; // no spacing needed for ListItems + + if time_area_response.dragged_by(PointerButton::Primary) { + ui.scroll_with_delta(Vec2::Y * time_area_response.drag_delta().y); + } + + let filter_matcher = self.filter_state.filter(); + + let streams_tree_data = + crate::streams_tree_data::StreamsTreeData::from_source_and_filter( + ctx, + self.source, + &filter_matcher, + ); + + for child in &streams_tree_data.children { + self.show_entity( + ctx, + viewport_blueprint, + &streams_tree_data, + entity_db, + time_ctrl, + time_area_response, + time_area_painter, + child, + ui, + ); + } + }); + } + + /// Display the list item for an entity. + #[expect(clippy::too_many_arguments)] + fn show_entity( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + time_ctrl: &mut TimeControl, + time_area_response: &egui::Response, + time_area_painter: &egui::Painter, + entity_data: &EntityData, + ui: &mut egui::Ui, + ) { + re_tracing::profile_function!(); + + let entity_path = &entity_data.entity_path; + let item = TimePanelItem::entity_path(entity_path.clone()); + let is_selected = ctx.selection().contains_item(&item.to_item()); + let is_item_hovered = ctx + .selection_state() + .highlight_for_ui_element(&item.to_item()) + == HoverHighlight::Hovered; + + let collapse_scope = self.collapse_scope(); + + // Expand if one of the children is focused + let focused_entity_path = ctx + .focused_item + .as_ref() + .and_then(|item| item.entity_path()); + + if focused_entity_path.is_some_and(|entity_path| entity_path.is_descendant_of(entity_path)) + { + collapse_scope + .entity(entity_path.clone()) + .set_open(ui.ctx(), true); + } + + // Globally unique id that is dependent on the "nature" of the tree (recording or blueprint, + // in a filter session or not) + let id = collapse_scope.entity(entity_path.clone()).into(); + + let list_item::ShowCollapsingResponse { + item_response: response, + body_response, + .. + } = ui + .list_item() + .render_offscreen(false) + .selected(is_selected) + .draggable(true) + .force_hovered(is_item_hovered) + .show_hierarchical_with_children( + ui, + id, + entity_data.default_open, + list_item::LabelContent::new(format_matching_text( + ctx.egui_ctx, + &entity_data.label, + entity_data.highlight_sections.iter().cloned(), + None, + )) + .with_icon(guess_instance_path_icon( + ctx, + &InstancePath::from(entity_path.clone()), + )) + .truncate(false), + |ui| { + self.show_entity_contents( + ctx, + viewport_blueprint, + streams_tree_data, + entity_db, + time_ctrl, + time_area_response, + time_area_painter, + entity_data, + ui, + ); + }, + ); + + let response = response.on_hover_ui(|ui| { + let include_subtree = true; + re_data_ui::item_ui::entity_hover_card_ui( + ui, + ctx, + &time_ctrl.current_query(), + entity_db, + entity_path, + include_subtree, + ); + }); + + if Some(entity_path) == focused_entity_path { + // Scroll only if the entity isn't already visible. This is important because that's what + // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be + // annoying to induce a scroll motion. + if !ui.clip_rect().contains_rect(response.rect) { + response.scroll_to_me(Some(egui::Align::Center)); + } + } + + self.handle_interactions_for_item( + ctx, + viewport_blueprint, + streams_tree_data, + entity_db, + item.to_item(), + &response, + true, + ); + + let is_closed = body_response.is_none(); + let response_rect = response.rect; + self.next_col_right = self.next_col_right.max(response_rect.right()); + + // + // Display the data density graph only if it is visible. + // + + // From the left of the label, all the way to the right-most of the time panel + let full_width_rect = Rect::from_x_y_ranges( + response_rect.left()..=ui.max_rect().right(), + response_rect.y_range(), + ); + + let is_visible = ui.is_rect_visible(full_width_rect); + if is_visible { + let tree_has_data_in_current_timeline = entity_db.subtree_has_data_on_timeline( + &entity_db.storage_engine(), + time_ctrl.timeline(), + entity_path, + ); + if tree_has_data_in_current_timeline { + let row_rect = Rect::from_x_y_ranges( + time_area_response.rect.x_range(), + response_rect.y_range(), + ); + + highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); + + // show the density graph only if that item is closed + if is_closed { + data_density_graph::data_density_graph_ui( + &mut self.data_density_graph_painter, + ctx, + time_ctrl, + entity_db, + time_area_painter, + ui, + &self.time_ranges_ui, + row_rect, + &item, + true, + ); + } + } + } + } + + /// Display the contents of an entity, i.e. its sub-entities and its components. + #[expect(clippy::too_many_arguments)] + fn show_entity_contents( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + time_ctrl: &mut TimeControl, + time_area_response: &egui::Response, + time_area_painter: &egui::Painter, + entity_data: &EntityData, + ui: &mut egui::Ui, + ) { + re_tracing::profile_function!(); + + for child in &entity_data.children { + self.show_entity( + ctx, + viewport_blueprint, + streams_tree_data, + entity_db, + time_ctrl, + time_area_response, + time_area_painter, + child, + ui, + ); + } + + let entity_path = &entity_data.entity_path; + let engine = entity_db.storage_engine(); + let store = engine.store(); + + for component_name in components_for_entity(store, entity_path) { + let is_static = store.entity_has_static_component(entity_path, &component_name); + + let component_path = ComponentPath::new(entity_path.clone(), component_name); + let short_component_name = component_path.component_name.short_name(); + let item = TimePanelItem::component_path(component_path.clone()); + let timeline = time_ctrl.timeline(); + + let response = ui + .list_item() + .render_offscreen(false) + .selected(ctx.selection().contains_item(&item.to_item())) + .force_hovered( + ctx.selection_state() + .highlight_for_ui_element(&item.to_item()) + == HoverHighlight::Hovered, + ) + .show_hierarchical( + ui, + list_item::LabelContent::new(short_component_name) + .with_icon(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT_TEMPORAL + }) + .truncate(false), + ); + + self.handle_interactions_for_item( + ctx, + viewport_blueprint, + streams_tree_data, + entity_db, + item.to_item(), + &response, + false, + ); + + let response_rect = response.rect; + + response.on_hover_ui(|ui| { + let num_static_messages = + store.num_static_events_for_component(entity_path, component_name); + let num_temporal_messages = store.num_temporal_events_for_component_on_timeline( + time_ctrl.timeline(), + entity_path, + component_name, + ); + let total_num_messages = num_static_messages + num_temporal_messages; + + if total_num_messages == 0 { + ui.label(ui.ctx().warning_text(format!( + "No event logged on timeline {:?}", + timeline.name() + ))); + } else { + list_item::list_item_scope(ui, "hover tooltip", |ui| { + let kind = if is_static { "Static" } else { "Temporal" }; + + let num_messages = if is_static { + num_static_messages + } else { + num_temporal_messages + }; + + let num_messages = if num_messages == 1 { + "once".to_owned() + } else { + format!("{} times", re_format::format_uint(num_messages)) + }; + + ui.list_item() + .interactive(false) + .render_offscreen(false) + .show_flat( + ui, + list_item::LabelContent::new(format!( + "{kind} component, logged {num_messages}" + )) + .truncate(false) + .with_icon(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT_TEMPORAL + }), + ); + + // Static components are not displayed at all on the timeline, so cannot be + // previewed there. So we display their content in this tooltip instead. + // Conversely, temporal components change over time, and so showing a specific instance here + // can be confusing. + if is_static { + let query = re_chunk_store::LatestAtQuery::new( + *time_ctrl.timeline(), + TimeInt::MAX, + ); + let ui_layout = UiLayout::Tooltip; + component_path.data_ui(ctx, ui, ui_layout, &query, entity_db); + } + }); + } + }); + + self.next_col_right = self.next_col_right.max(response_rect.right()); + + // From the left of the label, all the way to the right-most of the time panel + let full_width_rect = Rect::from_x_y_ranges( + response_rect.left()..=ui.max_rect().right(), + response_rect.y_range(), + ); + + let is_visible = ui.is_rect_visible(full_width_rect); + + if is_visible { + let component_has_data_in_current_timeline = store + .entity_has_component_on_timeline( + time_ctrl.timeline(), + entity_path, + &component_name, + ); + + if component_has_data_in_current_timeline { + // show the data in the time area: + let row_rect = Rect::from_x_y_ranges( + time_area_response.rect.x_range(), + response_rect.y_range(), + ); + + highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); + + 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, + db, + time_area_painter, + ui, + &self.time_ranges_ui, + row_rect, + &item, + true, + ); + } + } + } + } + + #[expect(clippy::too_many_arguments)] + fn handle_interactions_for_item( + &mut self, + ctx: &ViewerContext<'_>, + viewport_blueprint: &ViewportBlueprint, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + item: Item, + response: &egui::Response, + is_draggable: bool, + ) { + context_menu_ui_for_item_with_context( + ctx, + viewport_blueprint, + &item, + // expand/collapse context menu actions need this information + ItemContext::StreamsTree { + store_kind: self.source.into(), + filter_session_id: self.filter_state.session_id(), + }, + response, + SelectionUpdateBehavior::UseSelection, + ); + ctx.handle_select_hover_drag_interactions(response, item.clone(), is_draggable); + + self.handle_range_selection(ctx, streams_tree_data, entity_db, item, response); + } + + /// Handle setting/extending the selection based on shift-clicking. + fn handle_range_selection( + &mut self, + ctx: &ViewerContext<'_>, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + item: Item, + response: &Response, + ) { + // Early out if we're not being clicked. + if !response.clicked() { + return; + } + + let modifiers = ctx.egui_ctx.input(|i| i.modifiers); + + if modifiers.shift { + if let Some(anchor_item) = &self.range_selection_anchor_item { + let items_in_range = Self::items_in_range( + ctx, + streams_tree_data, + entity_db, + self.collapse_scope(), + anchor_item, + &item, + ); + + if items_in_range.is_empty() { + // This can happen if the last clicked item became invisible due to collapsing, or if + // the user switched to another recording. In either case, we invalidate it. + self.range_selection_anchor_item = None; + } else { + let items_iterator = items_in_range.into_iter().map(|item| { + ( + item, + Some(ItemContext::BlueprintTree { + filter_session_id: self.filter_state.session_id(), + }), + ) + }); + + if modifiers.command { + ctx.selection_state.extend_selection(items_iterator); + } else { + ctx.selection_state.set_selection(items_iterator); + } + } + } + } else { + self.range_selection_anchor_item = Some(item); + } + } + + /// Selects a range of items in the streams tree. + /// + /// This method selects all [`Item`]s displayed between the provided shift-clicked item and the + /// existing last-clicked item (if any). It takes into account the collapsed state, so only + /// actually visible items may be selected. + fn items_in_range( + ctx: &ViewerContext<'_>, + streams_tree_data: &StreamsTreeData, + entity_db: &re_entity_db::EntityDb, + collapse_scope: CollapseScope, + anchor_item: &Item, + shift_clicked_item: &Item, + ) -> Vec { + let mut items_in_range = vec![]; + let mut found_last_clicked_items = false; + let mut found_shift_clicked_items = false; + + streams_tree_data.visit(entity_db, |entity_data, component_name| { + let item = if let Some(component_name) = component_name { + Item::ComponentPath(ComponentPath::new( + entity_data.entity_path.clone(), + component_name, + )) + } else { + entity_data.item() + }; + + if &item == anchor_item { + found_last_clicked_items = true; + } + + if &item == shift_clicked_item { + found_shift_clicked_items = true; + } + + if found_last_clicked_items || found_shift_clicked_items { + items_in_range.push(item); + } + + if found_last_clicked_items && found_shift_clicked_items { + return VisitorControlFlow::Break(()); + } + + let is_expanded = entity_data + .is_open(ctx.egui_ctx, collapse_scope) + .unwrap_or(false); + + if is_expanded { + VisitorControlFlow::Continue + } else { + VisitorControlFlow::SkipBranch + } + }); + + if !found_last_clicked_items { + vec![] + } else { + items_in_range + } + } + + fn top_row_ui( + &self, + ctx: &ViewerContext<'_>, + entity_db: &re_entity_db::EntityDb, + ui: &mut egui::Ui, + time_ctrl: &mut TimeControl, + ) { + ui.spacing_mut().item_spacing.x = 18.0; // from figma + + if ui.max_rect().width() < 600.0 { + // Responsive ui for narrow screens, e.g. mobile. Split the controls into two rows. + ui.vertical(|ui| { + ui.horizontal(|ui| { + let times_per_timeline = entity_db.times_per_timeline(); + self.time_control_ui + .play_pause_ui(time_ctrl, times_per_timeline, ui); + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); + }); + ui.horizontal(|ui| { + self.time_control_ui.timeline_selector_ui( + time_ctrl, + entity_db.times_per_timeline(), + ui, + ); + + current_time_ui(ctx, ui, time_ctrl); + + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + help_button(ui); + }); + }); + }); + } else { + // One row: + let times_per_timeline = entity_db.times_per_timeline(); + + self.time_control_ui + .play_pause_ui(time_ctrl, times_per_timeline, ui); + self.time_control_ui + .timeline_selector_ui(time_ctrl, times_per_timeline, ui); + self.time_control_ui.playback_speed_ui(time_ctrl, ui); + self.time_control_ui.fps_ui(time_ctrl, ui); + current_time_ui(ctx, ui, time_ctrl); + + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + help_button(ui); + }); + } + } + + fn collapse_scope(&self) -> CollapseScope { + match (self.source, self.filter_state.session_id()) { + (TimePanelSource::Recording, None) => CollapseScope::StreamsTree, + + (TimePanelSource::Blueprint, None) => CollapseScope::BlueprintStreamsTree, + + (TimePanelSource::Recording, Some(session_id)) => { + CollapseScope::StreamsTreeFiltered { session_id } + } + + (TimePanelSource::Blueprint, Some(session_id)) => { + CollapseScope::BlueprintStreamsTreeFiltered { session_id } + } + } + } +} + +/// Draw the hovered/selected highlight background for a timeline row. +fn highlight_timeline_row( + ui: &Ui, + ctx: &ViewerContext<'_>, + painter: &Painter, + item: &Item, + row_rect: &Rect, +) { + let item_hovered = + ctx.selection_state().highlight_for_ui_element(item) == HoverHighlight::Hovered; + let item_selected = ctx.selection().contains_item(item); + let bg_color = if item_selected { + Some(ui.visuals().selection.bg_fill.gamma_multiply(0.4)) + } else if item_hovered { + Some( + ui.visuals() + .widgets + .hovered + .weak_bg_fill + .gamma_multiply(0.3), + ) + } else { + None + }; + if let Some(bg_color) = bg_color { + painter.rect_filled(*row_rect, egui::Rounding::ZERO, bg_color); + } +} + +fn collapsed_time_marker_and_time( + ui: &mut egui::Ui, + ctx: &ViewerContext<'_>, + data_density_graph_painter: &mut data_density_graph::DataDensityGraphPainter, + entity_db: &re_entity_db::EntityDb, + time_ctrl: &mut TimeControl, +) { + let timeline = time_ctrl.timeline(); + + let Some(time_range) = entity_db.time_range_for(timeline) else { + // We have no data on this timeline + return; + }; + + if time_range.min() == time_range.max() { + // Only one time point - showing a slider that can't be moved is just annoying + } else { + let space_needed_for_current_time = match timeline.typ() { + re_chunk_store::TimeType::Time => 220.0, + re_chunk_store::TimeType::Sequence => 100.0, + }; + + let mut time_range_rect = ui.available_rect_before_wrap(); + time_range_rect.max.x -= space_needed_for_current_time; + + if time_range_rect.width() > 50.0 { + ui.allocate_rect(time_range_rect, egui::Sense::hover()); + + let time_ranges_ui = + initialize_time_ranges_ui(entity_db, time_ctrl, time_range_rect.x_range(), None); + time_ranges_ui.snap_time_control(time_ctrl); + + let painter = ui.painter_at(time_range_rect.expand(4.0)); + + if let Some(highlighted_range) = time_ctrl.highlighted_range { + paint_range_highlight( + highlighted_range, + &time_ranges_ui, + &painter, + time_range_rect, + ); + } + + painter.hline( + time_range_rect.x_range(), + time_range_rect.center().y, + ui.visuals().widgets.noninteractive.fg_stroke, + ); + + data_density_graph::data_density_graph_ui( + data_density_graph_painter, + ctx, + time_ctrl, + entity_db, + ui.painter(), + ui, + &time_ranges_ui, + time_range_rect.shrink2(egui::vec2(0.0, 10.0)), + &TimePanelItem::entity_path(EntityPath::root()), + false, + ); + + time_marker_ui( + &time_ranges_ui, + time_ctrl, + ui, + None, + &painter, + &time_range_rect, + ); + } + } + + current_time_ui(ctx, ui, time_ctrl); +} + +fn paint_range_highlight( + highlighted_range: ResolvedTimeRange, + time_ranges_ui: &TimeRangesUi, + painter: &egui::Painter, + rect: Rect, +) { + let x_from = time_ranges_ui.x_from_time_f32(highlighted_range.min().into()); + let x_to = time_ranges_ui.x_from_time_f32(highlighted_range.max().into()); + + if let (Some(x_from), Some(x_to)) = (x_from, x_to) { + let visible_history_area_rect = + Rect::from_x_y_ranges(x_from..=x_to, rect.y_range()).intersect(rect); + + painter.rect( + visible_history_area_rect, + 0.0, + egui::Color32::WHITE.gamma_multiply(0.1), + egui::Stroke::NONE, + ); + } +} + +fn help_button(ui: &mut egui::Ui) { + // TODO(andreas): Nicer help text like on views. + ui.help_hover_button().on_hover_text( + "\ + In the top row you can drag to move the time, or shift-drag to select a loop region.\n\ + \n\ + Drag main area to pan.\n\ + Zoom: Ctrl/cmd + scroll, or drag up/down with secondary mouse button.\n\ + Double-click to reset view.\n\ + \n\ + Press the space bar to play/pause.", + ); +} + +fn current_time_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, time_ctrl: &mut TimeControl) { + if let Some(time_int) = time_ctrl.time_int() { + let time_type = time_ctrl.time_type(); + match time_type { + re_log_types::TimeType::Time => { + // TODO(#7653): parse time stamps + ui.monospace(time_type.format(time_int, ctx.app_options.time_zone)); + } + re_log_types::TimeType::Sequence => { + // NOTE: egui uses `f64` for all numbers internally, so we get precision problems if the integer gets too big. + if time_int.as_f64() as i64 == time_int.as_i64() { + let mut int = time_int.as_i64(); + let drag_value = egui::DragValue::new(&mut int) + .custom_formatter(|x, _range| { + TimeType::format_sequence(TimeInt::new_temporal(x as i64)) + }) + .custom_parser(|s| TimeType::parse_sequence(s).map(TimeInt::as_f64)); + let response = ui.add(drag_value); + if response.changed() { + time_ctrl.set_time(TimeInt::new_temporal(int)); + } + } else { + // Avoid the precision problems by just displaying the number without the ability to change it (here). + ui.monospace(time_type.format(time_int, ctx.app_options.time_zone)); + } + } + } + } +} + +// ---------------------------------------------------------------------------- + +fn initialize_time_ranges_ui( + entity_db: &re_entity_db::EntityDb, + time_ctrl: &TimeControl, + time_x_range: Rangef, + mut time_view: Option, +) -> TimeRangesUi { + re_tracing::profile_function!(); + + let mut time_range = Vec::new(); + + if let Some(times) = entity_db.time_histogram(time_ctrl.timeline()) { + // NOTE: `times` can be empty if a GC wiped everything. + if !times.is_empty() { + let timeline_axis = TimelineAxis::new(time_ctrl.time_type(), times); + time_view = time_view.or_else(|| Some(view_everything(&time_x_range, &timeline_axis))); + time_range.extend(timeline_axis.ranges); + } + } + + TimeRangesUi::new( + time_x_range, + time_view.unwrap_or(TimeView { + min: TimeReal::from(0), + time_spanned: 1.0, + }), + &time_range, + ) +} + +/// Find a nice view of everything. +fn view_everything(x_range: &Rangef, timeline_axis: &TimelineAxis) -> TimeView { + let gap_width = time_ranges_ui::gap_width(x_range, &timeline_axis.ranges) as f32; + let num_gaps = timeline_axis.ranges.len().saturating_sub(1); + let width = x_range.span(); + let width_sans_gaps = width - num_gaps as f32 * gap_width; + + let factor = if width_sans_gaps > 0.0 { + width / width_sans_gaps + } else { + 1.0 // too narrow to fit everything anyway + }; + + let min = timeline_axis.min(); + let time_spanned = timeline_axis.sum_time_lengths() as f64 * factor as f64; + + TimeView { + min: min.into(), + time_spanned, + } +} + +/// Visually separate the different time segments +fn paint_time_ranges_gaps( + time_ranges_ui: &TimeRangesUi, + ui: &egui::Ui, + painter: &egui::Painter, + y_range: Rangef, +) { + re_tracing::profile_function!(); + + // For each gap we are painting this: + // + // zig width + // | + // <-> + // \ / ^ + // \ / | zig height + // \ / v + // / \ + // / \ + // / \ + // \ / + // \ / + // \ / + // / \ + // / \ + // / \ + // + // <---------> + // gap width + // + // Filled with a dark color, plus a stroke and a small drop shadow to the left. + + use itertools::Itertools as _; + + let Rangef { + min: top, + max: bottom, + } = y_range; + + let fill_color = ui.visuals().widgets.noninteractive.bg_fill; + let stroke = ui.visuals().widgets.noninteractive.bg_stroke; + + let paint_time_gap = |gap_left: f32, gap_right: f32| { + let gap_width = gap_right - gap_left; + let zig_width = 4.0_f32.at_most(gap_width / 3.0).at_least(1.0); + let zig_height = zig_width; + let shadow_width = 12.0; + + let mut y = top; + let mut row = 0; // 0 = start wide, 1 = start narrow + + let mut mesh = egui::Mesh::default(); + let mut shadow_mesh = egui::Mesh::default(); + let mut left_line_strip = vec![]; + let mut right_line_strip = vec![]; + + while y - zig_height <= bottom { + let (left, right) = if row % 2 == 0 { + // full width + (gap_left, gap_right) + } else { + // contracted + (gap_left + zig_width, gap_right - zig_width) + }; + + let left_pos = pos2(left, y); + let right_pos = pos2(right, y); + + if !mesh.is_empty() { + let next_left_vidx = mesh.vertices.len() as u32; + let next_right_vidx = next_left_vidx + 1; + let prev_left_vidx = next_left_vidx - 2; + let prev_right_vidx = next_right_vidx - 2; + + mesh.add_triangle(prev_left_vidx, next_left_vidx, prev_right_vidx); + mesh.add_triangle(next_left_vidx, prev_right_vidx, next_right_vidx); + } + + mesh.colored_vertex(left_pos, fill_color); + mesh.colored_vertex(right_pos, fill_color); + + shadow_mesh.colored_vertex(pos2(right - shadow_width, y), Color32::TRANSPARENT); + shadow_mesh + .colored_vertex(right_pos, re_ui::design_tokens().shadow_gradient_dark_start); + + left_line_strip.push(left_pos); + right_line_strip.push(right_pos); + + y += zig_height; + row += 1; + } + + // Regular & shadow mesh have the same topology! + shadow_mesh.indices.clone_from(&mesh.indices); + + painter.add(Shape::Mesh(Arc::new(mesh))); + painter.add(Shape::Mesh(Arc::new(shadow_mesh))); + painter.add(Shape::line(left_line_strip, stroke)); + painter.add(Shape::line(right_line_strip, stroke)); + }; + + let zig_zag_first_and_last_edges = true; + + if let Some(segment) = time_ranges_ui.segments.first() { + let gap_edge = *segment.x.start() as f32; + + if zig_zag_first_and_last_edges { + // Left side of first segment - paint as a very wide gap that we only see the right side of + paint_time_gap(gap_edge - 100_000.0, gap_edge); + } else { + painter.rect_filled( + Rect::from_min_max(pos2(gap_edge - 100_000.0, top), pos2(gap_edge, bottom)), + 0.0, + fill_color, + ); + painter.vline(gap_edge, y_range, stroke); + } + } + + for (a, b) in time_ranges_ui.segments.iter().tuple_windows() { + paint_time_gap(*a.x.end() as f32, *b.x.start() as f32); + } + + if let Some(segment) = time_ranges_ui.segments.last() { + let gap_edge = *segment.x.end() as f32; + if zig_zag_first_and_last_edges { + // Right side of last segment - paint as a very wide gap that we only see the left side of + paint_time_gap(gap_edge, gap_edge + 100_000.0); + } else { + painter.rect_filled( + Rect::from_min_max(pos2(gap_edge, top), pos2(gap_edge + 100_000.0, bottom)), + 0.0, + fill_color, + ); + painter.vline(gap_edge, y_range, stroke); + } + } +} + +/// Returns a scroll delta +#[must_use] +fn interact_with_streams_rect( + time_ranges_ui: &TimeRangesUi, + time_ctrl: &mut TimeControl, + ui: &egui::Ui, + full_rect: &Rect, + streams_rect: &Rect, +) -> egui::Response { + let pointer_pos = ui.input(|i| i.pointer.hover_pos()); + + let mut delta_x = 0.0; + let mut zoom_factor = 1.0; + + // Check for zoom/pan inputs (via e.g. horizontal scrolling) on the entire + // time area rectangle, including the timeline rect. + let full_rect_hovered = pointer_pos.is_some_and(|pointer_pos| full_rect.contains(pointer_pos)); + if full_rect_hovered { + ui.input(|input| { + delta_x += input.smooth_scroll_delta.x; + zoom_factor *= input.zoom_delta_2d().x; + }); + } + + // We only check for drags in the streams rect, + // because drags in the timeline rect should move the time + // (or create loop sections). + let response = ui.interact( + *streams_rect, + ui.id().with("time_area_interact"), + egui::Sense::click_and_drag(), + ); + if response.dragged_by(PointerButton::Primary) { + delta_x += response.drag_delta().x; + ui.ctx().set_cursor_icon(CursorIcon::AllScroll); + } + if response.dragged_by(PointerButton::Secondary) { + zoom_factor *= (response.drag_delta().y * 0.01).exp(); + } + + if delta_x != 0.0 { + if let Some(new_view_range) = time_ranges_ui.pan(-delta_x) { + time_ctrl.set_time_view(new_view_range); + } + } + + if zoom_factor != 1.0 { + if let Some(pointer_pos) = pointer_pos { + if let Some(new_view_range) = time_ranges_ui.zoom_at(pointer_pos.x, zoom_factor) { + time_ctrl.set_time_view(new_view_range); + } + } + } + + if response.double_clicked() { + time_ctrl.reset_time_view(); + } + + response +} + +/// A vertical line that shows the current time. +fn time_marker_ui( + time_ranges_ui: &TimeRangesUi, + time_ctrl: &mut TimeControl, + ui: &egui::Ui, + time_area_response: Option<&egui::Response>, + time_area_painter: &egui::Painter, + timeline_rect: &Rect, +) { + // timeline_rect: top part with the second ticks and time marker + + let pointer_pos = ui.input(|i| i.pointer.hover_pos()); + let time_drag_id = ui.id().with("time_drag_id"); + let timeline_cursor_icon = CursorIcon::ResizeHorizontal; + let is_hovering_the_loop_selection = ui.output(|o| o.cursor_icon) != CursorIcon::Default; // A kind of hacky proxy + let is_anything_being_dragged = ui.ctx().dragged_id().is_some(); + let time_area_double_clicked = time_area_response.is_some_and(|resp| resp.double_clicked()); + let interact_radius = ui.style().interaction.resize_grab_radius_side; + + let mut is_hovering_time_cursor = false; + + // show current time as a line: + if let Some(time) = time_ctrl.time() { + if let Some(mut x) = time_ranges_ui.x_from_time_f32(time) { + if timeline_rect.x_range().contains(x) { + let line_rect = + Rect::from_x_y_ranges(x..=x, timeline_rect.top()..=ui.max_rect().bottom()) + .expand(interact_radius); + + let sense = if time_area_double_clicked { + egui::Sense::hover() + } else { + egui::Sense::drag() + }; + + let response = ui + .interact(line_rect, time_drag_id, sense) + .on_hover_and_drag_cursor(timeline_cursor_icon); + + is_hovering_time_cursor = response.hovered(); + + if response.dragged() { + if let Some(pointer_pos) = pointer_pos { + if let Some(time) = time_ranges_ui.time_from_x_f32(pointer_pos.x) { + let time = time_ranges_ui.clamp_time(time); + time_ctrl.set_time(time); + time_ctrl.pause(); + + x = pointer_pos.x; // avoid frame-delay + } + } + } + + ui.paint_time_cursor( + time_area_painter, + &response, + x, + Rangef::new(timeline_rect.top(), ui.max_rect().bottom()), + ); + } + } + } + + // "click here to view time here" + if let Some(pointer_pos) = pointer_pos { + let is_pointer_in_time_area_rect = + ui.ui_contains_pointer() && time_area_painter.clip_rect().contains(pointer_pos); + let is_pointer_in_timeline_rect = + ui.ui_contains_pointer() && timeline_rect.contains(pointer_pos); + + // Show preview? + if !is_hovering_time_cursor + && !time_area_double_clicked + && is_pointer_in_time_area_rect + && !is_anything_being_dragged + && !is_hovering_the_loop_selection + { + time_area_painter.vline( + pointer_pos.x, + timeline_rect.top()..=ui.max_rect().bottom(), + ui.visuals().widgets.noninteractive.fg_stroke, + ); + ui.ctx().set_cursor_icon(timeline_cursor_icon); // preview! + } + + // Click to move time here: + let time_area_response = ui.interact( + time_area_painter.clip_rect(), + ui.id().with("time_area_painter_id"), + egui::Sense::click(), + ); + + if !is_hovering_the_loop_selection { + let mut set_time_to_pointer = || { + if let Some(time) = time_ranges_ui.time_from_x_f32(pointer_pos.x) { + let time = time_ranges_ui.clamp_time(time); + time_ctrl.set_time(time); + time_ctrl.pause(); + } + }; + + // click on timeline = set time + start drag + // click on time area = set time + // double click on time area = reset time + if !is_anything_being_dragged + && is_pointer_in_timeline_rect + && ui.input(|i| i.pointer.primary_down()) + { + set_time_to_pointer(); + ui.ctx().set_dragged_id(time_drag_id); + } else if is_pointer_in_time_area_rect { + if time_area_response.double_clicked() { + time_ctrl.reset_time_view(); + } else if time_area_response.clicked() && !is_anything_being_dragged { + set_time_to_pointer(); + } + } + } + } +}