From 13f1ea1a64c6d3eeb8158d796a27bd9e5f65a452 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:01:33 +0100 Subject: [PATCH 1/4] Move and document `DataResultNodeOrPath` (#8762) --- .../viewer/re_blueprint_tree/src/blueprint_tree.rs | 6 ++++-- .../src/data_result_node_or_path.rs | 12 ++++++++---- crates/viewer/re_blueprint_tree/src/lib.rs | 1 + crates/viewer/re_viewer_context/src/lib.rs | 2 -- 4 files changed, 13 insertions(+), 8 deletions(-) rename crates/viewer/{re_viewer_context => re_blueprint_tree}/src/data_result_node_or_path.rs (61%) diff --git a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs index 341191ba6145c..483219af4282d 100644 --- a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs +++ b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs @@ -12,13 +12,15 @@ use re_ui::{ }; use re_viewer_context::{ contents_name_style, icon_for_container_kind, CollapseScope, ContainerId, Contents, - DataQueryResult, DataResultNode, DataResultNodeOrPath, DragAndDropFeedback, DragAndDropPayload, - HoverHighlight, Item, ItemContext, SystemCommandSender, ViewId, ViewerContext, + DataQueryResult, DataResultNode, DragAndDropFeedback, DragAndDropPayload, HoverHighlight, Item, + ItemContext, SystemCommandSender, ViewId, ViewerContext, }; use re_viewport_blueprint::{ ui::show_add_view_or_container_modal, ViewBlueprint, ViewportBlueprint, }; +use crate::data_result_node_or_path::DataResultNodeOrPath; + /// Holds the state of the blueprint tree UI. #[derive(Default)] pub struct BlueprintTree { diff --git a/crates/viewer/re_viewer_context/src/data_result_node_or_path.rs b/crates/viewer/re_blueprint_tree/src/data_result_node_or_path.rs similarity index 61% rename from crates/viewer/re_viewer_context/src/data_result_node_or_path.rs rename to crates/viewer/re_blueprint_tree/src/data_result_node_or_path.rs index 6f9d4945d65a2..79bc7156eb19c 100644 --- a/crates/viewer/re_viewer_context/src/data_result_node_or_path.rs +++ b/crates/viewer/re_blueprint_tree/src/data_result_node_or_path.rs @@ -1,8 +1,12 @@ -use re_chunk::EntityPath; +use re_log_types::EntityPath; +use re_viewer_context::{DataResultNode, DataResultTree}; -use crate::{DataResultNode, DataResultTree}; - -// TODO(wumpf): document this +/// Helper for presenting [`DataResultNode`]s within a larger entity-based tree. +/// +/// The blueprint tree presents data results within possibly larger tree structures. For example, +/// all "in-tree" data results are presented within the subtree defined by the view origin. Yet +/// part of this subtree may not be a [`DataResultNode`] by itself. This enum can represent any node +/// of any subtree, regardless of whether it is a [`DataResultNode`] or note. pub enum DataResultNodeOrPath<'a> { Path(&'a EntityPath), DataResultNode(&'a DataResultNode), diff --git a/crates/viewer/re_blueprint_tree/src/lib.rs b/crates/viewer/re_blueprint_tree/src/lib.rs index 8433494644478..bc1f8000b3879 100644 --- a/crates/viewer/re_blueprint_tree/src/lib.rs +++ b/crates/viewer/re_blueprint_tree/src/lib.rs @@ -1,5 +1,6 @@ //! This crate implements the UI for the blueprint tree in the left panel. mod blueprint_tree; +mod data_result_node_or_path; pub use blueprint_tree::BlueprintTree; diff --git a/crates/viewer/re_viewer_context/src/lib.rs b/crates/viewer/re_viewer_context/src/lib.rs index faaa5d6983d20..6bae1e671263c 100644 --- a/crates/viewer/re_viewer_context/src/lib.rs +++ b/crates/viewer/re_viewer_context/src/lib.rs @@ -12,7 +12,6 @@ mod command_sender; mod component_fallbacks; mod component_ui_registry; mod contents; -mod data_result_node_or_path; mod drag_and_drop; mod file_dialog; mod image_info; @@ -54,7 +53,6 @@ pub use self::{ }, component_ui_registry::{ComponentUiRegistry, ComponentUiTypes}, contents::{blueprint_id_to_tile_id, Contents, ContentsName}, - data_result_node_or_path::DataResultNodeOrPath, drag_and_drop::{DragAndDropFeedback, DragAndDropManager, DragAndDropPayload}, file_dialog::santitize_file_name, image_info::{ColormapWithRange, ImageInfo}, From e6e3b676c5e76633588d09d451820be3d7725019 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 21 Jan 2025 19:02:35 +0100 Subject: [PATCH 2/4] Tagged columnar updates: Rust (#8764) I ended up with something slightly different than the original design, because it turned out to really not feel that great in practice. In particular, it required duplicating _a lot_ of generated code for little (no?) added value. In short: `.columns` becomes a vanilla method rather than a static method. ```rust // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. let times = TimeColumn::new_seconds("time", 10..15); #[rustfmt::skip] let 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], ]; // At each timestep, all points in the cloud share the same but changing color and radius. let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF]; let radii = [0.05, 0.01, 0.2, 0.1, 0.3]; // Partition our data as expected across the 5 timesteps. let position = rerun::Points3D::update_fields() .with_positions(positions) .columns([2, 4, 4, 3, 4])?; let color_and_radius = rerun::Points3D::update_fields() .with_colors(colors) .with_radii(radii) .columns([1, 1, 1, 1, 1])?; rec.send_columns_v2("points", [times], position.chain(color_and_radius))?; ``` * Fixes #8753 * Fixes #7167 --- .../re_types_builder/src/codegen/rust/api.rs | 41 +++++++- .../store/re_types/src/archetypes/arrows2d.rs | 49 ++++++++++ .../store/re_types/src/archetypes/arrows3d.rs | 46 +++++++++ .../re_types/src/archetypes/bar_chart.rs | 31 +++++++ .../re_types/src/archetypes/capsules3d.rs | 52 +++++++++++ .../re_types/src/archetypes/depth_image.rs | 46 +++++++++ .../re_types/src/archetypes/ellipsoids3d.rs | 55 +++++++++++ .../re_types/src/archetypes/encoded_image.rs | 37 ++++++++ .../src/archetypes/geo_line_strings.rs | 34 +++++++ .../re_types/src/archetypes/geo_points.rs | 37 ++++++++ .../re_types/src/archetypes/graph_edges.rs | 31 +++++++ .../re_types/src/archetypes/graph_nodes.rs | 43 +++++++++ .../src/archetypes/instance_poses3d.rs | 40 ++++++++ .../re_types/src/archetypes/line_strips2d.rs | 46 +++++++++ .../re_types/src/archetypes/line_strips3d.rs | 43 +++++++++ .../store/re_types/src/archetypes/points2d.rs | 49 ++++++++++ .../store/re_types/src/archetypes/points3d.rs | 93 +++++++++++++++++++ .../store/re_types/src/archetypes/scalar.rs | 27 ++++++ .../src/archetypes/segmentation_image.rs | 37 ++++++++ .../re_types/src/archetypes/series_line.rs | 37 ++++++++ .../re_types/src/archetypes/series_point.rs | 37 ++++++++ .../re_types/src/archetypes/text_document.rs | 31 +++++++ .../store/re_types/src/archetypes/text_log.rs | 34 +++++++ .../re_types/src/archetypes/transform3d.rs | 46 +++++++++ .../src/archetypes/video_frame_reference.rs | 31 +++++++ .../src/blueprint/archetypes/background.rs | 31 +++++++ .../archetypes/container_blueprint.rs | 49 ++++++++++ .../blueprint/archetypes/dataframe_query.rs | 40 ++++++++ .../src/blueprint/archetypes/force_center.rs | 31 +++++++ .../archetypes/force_collision_radius.rs | 34 +++++++ .../src/blueprint/archetypes/force_link.rs | 34 +++++++ .../blueprint/archetypes/force_many_body.rs | 31 +++++++ .../blueprint/archetypes/force_position.rs | 34 +++++++ .../src/blueprint/archetypes/line_grid3d.rs | 40 ++++++++ .../blueprint/archetypes/map_background.rs | 27 ++++++ .../src/blueprint/archetypes/map_zoom.rs | 27 ++++++ .../blueprint/archetypes/near_clip_plane.rs | 27 ++++++ .../blueprint/archetypes/panel_blueprint.rs | 27 ++++++ .../src/blueprint/archetypes/plot_legend.rs | 31 +++++++ .../src/blueprint/archetypes/scalar_axis.rs | 31 +++++++ .../archetypes/tensor_scalar_mapping.rs | 34 +++++++ .../archetypes/tensor_slice_selection.rs | 37 ++++++++ .../blueprint/archetypes/tensor_view_fit.rs | 27 ++++++ .../blueprint/archetypes/view_blueprint.rs | 37 ++++++++ .../src/blueprint/archetypes/view_contents.rs | 27 ++++++ .../archetypes/viewport_blueprint.rs | 42 +++++++++ .../archetypes/visible_time_ranges.rs | 27 ++++++ .../blueprint/archetypes/visual_bounds2d.rs | 27 ++++++ .../re_types_core/src/archetypes/clear.rs | 26 ++++++ crates/store/re_types_core/src/lib.rs | 34 ++++++- .../store/re_types_core/src/loggable_batch.rs | 77 +++++++++++++++ crates/top/re_sdk/src/lib.rs | 2 +- crates/top/re_sdk/src/recording_stream.rs | 37 +++++++- crates/utils/re_arrow_util/src/arrow_util.rs | 20 +++- docs/snippets/INDEX.md | 7 +- .../all/archetypes/points3d_send_columns.cpp | 10 +- .../all/archetypes/points3d_send_columns.py | 23 +++-- .../all/archetypes/points3d_send_columns.rs | 36 +++++++ docs/snippets/snippets.toml | 7 +- lychee.toml | 1 + rerun_cpp/src/rerun/archetypes/points3d.hpp | 10 +- rerun_py/rerun_sdk/rerun/_send_columns.py | 2 +- .../rerun_sdk/rerun/archetypes/points3d.py | 23 +++-- 63 files changed, 2085 insertions(+), 35 deletions(-) create mode 100644 docs/snippets/all/archetypes/points3d_send_columns.rs 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 38a0eed4881e6..c9758940e17a0 100644 --- a/crates/build/re_types_builder/src/codegen/rust/api.rs +++ b/crates/build/re_types_builder/src/codegen/rust/api.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use anyhow::Context as _; use camino::{Utf8Path, Utf8PathBuf}; -use itertools::Itertools as _; +use itertools::Itertools; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -1922,10 +1922,47 @@ fn quote_builder_from_obj(reporter: &Reporter, objects: &Objects, obj: &Object) } }); + let columnar_methods = obj.is_eager_rust_archetype().then(|| { + let columns_doc = unindent::unindent("\ + Partitions the component data into multiple sub-batches. + + Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + instead, via [`SerializedComponentBatch::partitioned`]. + + 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. + + [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + "); + let columns_doc = quote_doc_lines(&columns_doc.lines().map(|l| l.to_owned()).collect_vec()); + + let fields = required.iter().chain(optional.iter()).map(|field| { + let field_name = format_ident!("{}", field.name); + quote!(self.#field_name.map(|#field_name| #field_name.partitioned(_lengths.clone())).transpose()?) + }); + + quote! { + #columns_doc + #[inline] + pub fn columns( + self, + _lengths: I, // prefixed so it doesn't conflict with fields of the same name + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ #(#fields),* ]; + let indicator_column = ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + } + }); + let with_methods = if obj.is_eager_rust_archetype() { quote! { #partial_update_methods - + #columnar_methods #(#eager_with_methods)* } } else { diff --git a/crates/store/re_types/src/archetypes/arrows2d.rs b/crates/store/re_types/src/archetypes/arrows2d.rs index e34a17d00a8bc..c0a6de4d98b8e 100644 --- a/crates/store/re_types/src/archetypes/arrows2d.rs +++ b/crates/store/re_types/src/archetypes/arrows2d.rs @@ -401,6 +401,55 @@ impl Arrows2D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.vectors + .map(|vectors| vectors.partitioned(_lengths.clone())) + .transpose()?, + self.origins + .map(|origins| origins.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.draw_order + .map(|draw_order| draw_order.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// All the vectors for each arrow in the batch. #[inline] pub fn with_vectors( diff --git a/crates/store/re_types/src/archetypes/arrows3d.rs b/crates/store/re_types/src/archetypes/arrows3d.rs index 5ba80d6c4c50e..ef4c852ed2eaf 100644 --- a/crates/store/re_types/src/archetypes/arrows3d.rs +++ b/crates/store/re_types/src/archetypes/arrows3d.rs @@ -385,6 +385,52 @@ impl Arrows3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.vectors + .map(|vectors| vectors.partitioned(_lengths.clone())) + .transpose()?, + self.origins + .map(|origins| origins.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// All the vectors for each arrow in the batch. #[inline] pub fn with_vectors( diff --git a/crates/store/re_types/src/archetypes/bar_chart.rs b/crates/store/re_types/src/archetypes/bar_chart.rs index 5e8cf8a7da88b..92ecbf1b0b6da 100644 --- a/crates/store/re_types/src/archetypes/bar_chart.rs +++ b/crates/store/re_types/src/archetypes/bar_chart.rs @@ -218,6 +218,37 @@ impl BarChart { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.values + .map(|values| values.partitioned(_lengths.clone())) + .transpose()?, + self.color + .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()) + } + /// The values. Should always be a 1-dimensional tensor (i.e. a vector). #[inline] pub fn with_values(mut self, values: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/capsules3d.rs b/crates/store/re_types/src/archetypes/capsules3d.rs index aa569e5080566..09356f45af53b 100644 --- a/crates/store/re_types/src/archetypes/capsules3d.rs +++ b/crates/store/re_types/src/archetypes/capsules3d.rs @@ -460,6 +460,58 @@ impl Capsules3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.lengths + .map(|lengths| lengths.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.translations + .map(|translations| translations.partitioned(_lengths.clone())) + .transpose()?, + self.rotation_axis_angles + .map(|rotation_axis_angles| rotation_axis_angles.partitioned(_lengths.clone())) + .transpose()?, + self.quaternions + .map(|quaternions| quaternions.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// Lengths of the capsules, defined as the distance between the centers of the endcaps. #[inline] pub fn with_lengths( diff --git a/crates/store/re_types/src/archetypes/depth_image.rs b/crates/store/re_types/src/archetypes/depth_image.rs index 3293d6babd1d2..fb5092552cfba 100644 --- a/crates/store/re_types/src/archetypes/depth_image.rs +++ b/crates/store/re_types/src/archetypes/depth_image.rs @@ -407,6 +407,52 @@ impl DepthImage { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.buffer + .map(|buffer| buffer.partitioned(_lengths.clone())) + .transpose()?, + self.format + .map(|format| format.partitioned(_lengths.clone())) + .transpose()?, + self.meter + .map(|meter| meter.partitioned(_lengths.clone())) + .transpose()?, + self.colormap + .map(|colormap| colormap.partitioned(_lengths.clone())) + .transpose()?, + self.depth_range + .map(|depth_range| depth_range.partitioned(_lengths.clone())) + .transpose()?, + self.point_fill_ratio + .map(|point_fill_ratio| point_fill_ratio.partitioned(_lengths.clone())) + .transpose()?, + self.draw_order + .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()) + } + /// The raw depth image data. #[inline] pub fn with_buffer(mut self, buffer: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/ellipsoids3d.rs b/crates/store/re_types/src/archetypes/ellipsoids3d.rs index 4bd00fda37be3..932dd30887094 100644 --- a/crates/store/re_types/src/archetypes/ellipsoids3d.rs +++ b/crates/store/re_types/src/archetypes/ellipsoids3d.rs @@ -494,6 +494,61 @@ impl Ellipsoids3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.half_sizes + .map(|half_sizes| half_sizes.partitioned(_lengths.clone())) + .transpose()?, + self.centers + .map(|centers| centers.partitioned(_lengths.clone())) + .transpose()?, + self.rotation_axis_angles + .map(|rotation_axis_angles| rotation_axis_angles.partitioned(_lengths.clone())) + .transpose()?, + self.quaternions + .map(|quaternions| quaternions.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.line_radii + .map(|line_radii| line_radii.partitioned(_lengths.clone())) + .transpose()?, + self.fill_mode + .map(|fill_mode| fill_mode.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// For each ellipsoid, half of its size on its three axes. /// /// If all components are equal, then it is a sphere with that radius. diff --git a/crates/store/re_types/src/archetypes/encoded_image.rs b/crates/store/re_types/src/archetypes/encoded_image.rs index 8c06b552f1ceb..83edf8c0f6cd9 100644 --- a/crates/store/re_types/src/archetypes/encoded_image.rs +++ b/crates/store/re_types/src/archetypes/encoded_image.rs @@ -288,6 +288,43 @@ impl EncodedImage { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.blob + .map(|blob| blob.partitioned(_lengths.clone())) + .transpose()?, + self.media_type + .map(|media_type| media_type.partitioned(_lengths.clone())) + .transpose()?, + self.opacity + .map(|opacity| opacity.partitioned(_lengths.clone())) + .transpose()?, + self.draw_order + .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()) + } + /// The encoded content of some image file, e.g. a PNG or JPEG. #[inline] pub fn with_blob(mut self, blob: impl Into) -> Self { 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 a7159b1232cad..3591a27cab7f6 100644 --- a/crates/store/re_types/src/archetypes/geo_line_strings.rs +++ b/crates/store/re_types/src/archetypes/geo_line_strings.rs @@ -266,6 +266,40 @@ impl GeoLineStrings { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.line_strings + .map(|line_strings| line_strings.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .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()) + } + /// The line strings, expressed in [EPSG:4326](https://epsg.io/4326) coordinates (North/East-positive degrees). #[inline] pub fn with_line_strings( diff --git a/crates/store/re_types/src/archetypes/geo_points.rs b/crates/store/re_types/src/archetypes/geo_points.rs index 9f6a0f5857493..bc5430f031793 100644 --- a/crates/store/re_types/src/archetypes/geo_points.rs +++ b/crates/store/re_types/src/archetypes/geo_points.rs @@ -285,6 +285,43 @@ impl GeoPoints { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.positions + .map(|positions| positions.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// The [EPSG:4326](https://epsg.io/4326) coordinates for the points (North/East-positive degrees). #[inline] pub fn with_positions( diff --git a/crates/store/re_types/src/archetypes/graph_edges.rs b/crates/store/re_types/src/archetypes/graph_edges.rs index 7ebf59ec2f30f..2451c5b352313 100644 --- a/crates/store/re_types/src/archetypes/graph_edges.rs +++ b/crates/store/re_types/src/archetypes/graph_edges.rs @@ -232,6 +232,37 @@ impl GraphEdges { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.edges + .map(|edges| edges.partitioned(_lengths.clone())) + .transpose()?, + self.graph_type + .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()) + } + /// A list of node tuples. #[inline] pub fn with_edges( diff --git a/crates/store/re_types/src/archetypes/graph_nodes.rs b/crates/store/re_types/src/archetypes/graph_nodes.rs index 59a9b48ed87e6..e9c8bb5ffa891 100644 --- a/crates/store/re_types/src/archetypes/graph_nodes.rs +++ b/crates/store/re_types/src/archetypes/graph_nodes.rs @@ -334,6 +334,49 @@ impl GraphNodes { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.node_ids + .map(|node_ids| node_ids.partitioned(_lengths.clone())) + .transpose()?, + self.positions + .map(|positions| positions.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .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()) + } + /// A list of node IDs. #[inline] pub fn with_node_ids( diff --git a/crates/store/re_types/src/archetypes/instance_poses3d.rs b/crates/store/re_types/src/archetypes/instance_poses3d.rs index a019a9c1cc1b5..5ea105281d35b 100644 --- a/crates/store/re_types/src/archetypes/instance_poses3d.rs +++ b/crates/store/re_types/src/archetypes/instance_poses3d.rs @@ -354,6 +354,46 @@ impl InstancePoses3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.translations + .map(|translations| translations.partitioned(_lengths.clone())) + .transpose()?, + self.rotation_axis_angles + .map(|rotation_axis_angles| rotation_axis_angles.partitioned(_lengths.clone())) + .transpose()?, + self.quaternions + .map(|quaternions| quaternions.partitioned(_lengths.clone())) + .transpose()?, + self.scales + .map(|scales| scales.partitioned(_lengths.clone())) + .transpose()?, + self.mat3x3 + .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()) + } + /// Translation vectors. #[inline] pub fn with_translations( diff --git a/crates/store/re_types/src/archetypes/line_strips2d.rs b/crates/store/re_types/src/archetypes/line_strips2d.rs index daef1b89ef077..e5d927d7eba2b 100644 --- a/crates/store/re_types/src/archetypes/line_strips2d.rs +++ b/crates/store/re_types/src/archetypes/line_strips2d.rs @@ -408,6 +408,52 @@ impl LineStrips2D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.strips + .map(|strips| strips.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.draw_order + .map(|draw_order| draw_order.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// All the actual 2D line strips that make up the batch. #[inline] pub fn with_strips( diff --git a/crates/store/re_types/src/archetypes/line_strips3d.rs b/crates/store/re_types/src/archetypes/line_strips3d.rs index 308ae9c0fe831..1d76a8db4fec4 100644 --- a/crates/store/re_types/src/archetypes/line_strips3d.rs +++ b/crates/store/re_types/src/archetypes/line_strips3d.rs @@ -392,6 +392,49 @@ impl LineStrips3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.strips + .map(|strips| strips.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .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()) + } + /// All the actual 3D line strips that make up the batch. #[inline] pub fn with_strips( diff --git a/crates/store/re_types/src/archetypes/points2d.rs b/crates/store/re_types/src/archetypes/points2d.rs index 54a4cf25b289c..a4372905432a0 100644 --- a/crates/store/re_types/src/archetypes/points2d.rs +++ b/crates/store/re_types/src/archetypes/points2d.rs @@ -455,6 +455,55 @@ impl Points2D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.positions + .map(|positions| positions.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.draw_order + .map(|draw_order| draw_order.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .map(|class_ids| class_ids.partitioned(_lengths.clone())) + .transpose()?, + self.keypoint_ids + .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()) + } + /// All the 2D positions at which the point cloud shows points. #[inline] pub fn with_positions( diff --git a/crates/store/re_types/src/archetypes/points3d.rs b/crates/store/re_types/src/archetypes/points3d.rs index c540dcdc24a6e..44443bf60cb2d 100644 --- a/crates/store/re_types/src/archetypes/points3d.rs +++ b/crates/store/re_types/src/archetypes/points3d.rs @@ -94,6 +94,53 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// /// +/// +/// ### Send several point clouds with varying point count over time in a single call +/// ```ignore +/// use rerun::TimeColumn; +/// +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_points3d_send_columns").spawn()?; +/// +/// // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. +/// let times = TimeColumn::new_seconds("time", 10..15); +/// +/// #[rustfmt::skip] +/// let 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], +/// ]; +/// +/// // At each timestep, all points in the cloud share the same but changing color and radius. +/// let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF]; +/// let radii = [0.05, 0.01, 0.2, 0.1, 0.3]; +/// +/// // Partition our data as expected across the 5 timesteps. +/// let position = rerun::Points3D::update_fields() +/// .with_positions(positions) +/// .columns([2, 4, 4, 3, 4])?; +/// let color_and_radius = rerun::Points3D::update_fields() +/// .with_colors(colors) +/// .with_radii(radii) +/// .columns([1, 1, 1, 1, 1])?; +/// +/// rec.send_columns_v2("points", [times], position.chain(color_and_radius))?; +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
#[derive(Clone, Debug, PartialEq, Default)] pub struct Points3D { /// All the 3D positions at which the point cloud shows points. @@ -424,6 +471,52 @@ impl Points3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.positions + .map(|positions| positions.partitioned(_lengths.clone())) + .transpose()?, + self.radii + .map(|radii| radii.partitioned(_lengths.clone())) + .transpose()?, + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.labels + .map(|labels| labels.partitioned(_lengths.clone())) + .transpose()?, + self.show_labels + .map(|show_labels| show_labels.partitioned(_lengths.clone())) + .transpose()?, + self.class_ids + .map(|class_ids| class_ids.partitioned(_lengths.clone())) + .transpose()?, + self.keypoint_ids + .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()) + } + /// All the 3D positions at which the point cloud shows points. #[inline] pub fn with_positions( diff --git a/crates/store/re_types/src/archetypes/scalar.rs b/crates/store/re_types/src/archetypes/scalar.rs index 9653c4d40a907..460aed4c3f54b 100644 --- a/crates/store/re_types/src/archetypes/scalar.rs +++ b/crates/store/re_types/src/archetypes/scalar.rs @@ -194,6 +194,33 @@ impl Scalar { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .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()) + } + /// The scalar value to log. #[inline] pub fn with_scalar(mut self, scalar: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/segmentation_image.rs b/crates/store/re_types/src/archetypes/segmentation_image.rs index d447dccf0084d..eac4e9012fc08 100644 --- a/crates/store/re_types/src/archetypes/segmentation_image.rs +++ b/crates/store/re_types/src/archetypes/segmentation_image.rs @@ -306,6 +306,43 @@ impl SegmentationImage { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.buffer + .map(|buffer| buffer.partitioned(_lengths.clone())) + .transpose()?, + self.format + .map(|format| format.partitioned(_lengths.clone())) + .transpose()?, + self.opacity + .map(|opacity| opacity.partitioned(_lengths.clone())) + .transpose()?, + self.draw_order + .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()) + } + /// The raw image data. #[inline] pub fn with_buffer(mut self, buffer: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/series_line.rs b/crates/store/re_types/src/archetypes/series_line.rs index 539b65bc09a23..0c1957658a4aa 100644 --- a/crates/store/re_types/src/archetypes/series_line.rs +++ b/crates/store/re_types/src/archetypes/series_line.rs @@ -307,6 +307,43 @@ impl SeriesLine { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.color + .map(|color| color.partitioned(_lengths.clone())) + .transpose()?, + self.width + .map(|width| width.partitioned(_lengths.clone())) + .transpose()?, + self.name + .map(|name| name.partitioned(_lengths.clone())) + .transpose()?, + self.aggregation_policy + .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()) + } + /// Color for the corresponding series. #[inline] pub fn with_color(mut self, color: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/series_point.rs b/crates/store/re_types/src/archetypes/series_point.rs index bc839b5c5c28d..2c3ba5f3383c2 100644 --- a/crates/store/re_types/src/archetypes/series_point.rs +++ b/crates/store/re_types/src/archetypes/series_point.rs @@ -305,6 +305,43 @@ impl SeriesPoint { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.color + .map(|color| color.partitioned(_lengths.clone())) + .transpose()?, + self.marker + .map(|marker| marker.partitioned(_lengths.clone())) + .transpose()?, + self.name + .map(|name| name.partitioned(_lengths.clone())) + .transpose()?, + self.marker_size + .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()) + } + /// Color for the corresponding series. #[inline] pub fn with_color(mut self, color: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/text_document.rs b/crates/store/re_types/src/archetypes/text_document.rs index e06b1347e6e53..99e786ef73c3f 100644 --- a/crates/store/re_types/src/archetypes/text_document.rs +++ b/crates/store/re_types/src/archetypes/text_document.rs @@ -267,6 +267,37 @@ impl TextDocument { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.text + .map(|text| text.partitioned(_lengths.clone())) + .transpose()?, + self.media_type + .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()) + } + /// Contents of the text document. #[inline] pub fn with_text(mut self, text: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/text_log.rs b/crates/store/re_types/src/archetypes/text_log.rs index 1504cad37f84f..43c3ca4ceee0d 100644 --- a/crates/store/re_types/src/archetypes/text_log.rs +++ b/crates/store/re_types/src/archetypes/text_log.rs @@ -255,6 +255,40 @@ impl TextLog { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.text + .map(|text| text.partitioned(_lengths.clone())) + .transpose()?, + self.level + .map(|level| level.partitioned(_lengths.clone())) + .transpose()?, + self.color + .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()) + } + /// The body of the message. #[inline] pub fn with_text(mut self, text: impl Into) -> Self { diff --git a/crates/store/re_types/src/archetypes/transform3d.rs b/crates/store/re_types/src/archetypes/transform3d.rs index 95633745cb1dd..b638c4eb25565 100644 --- a/crates/store/re_types/src/archetypes/transform3d.rs +++ b/crates/store/re_types/src/archetypes/transform3d.rs @@ -468,6 +468,52 @@ impl Transform3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.translation + .map(|translation| translation.partitioned(_lengths.clone())) + .transpose()?, + self.rotation_axis_angle + .map(|rotation_axis_angle| rotation_axis_angle.partitioned(_lengths.clone())) + .transpose()?, + self.quaternion + .map(|quaternion| quaternion.partitioned(_lengths.clone())) + .transpose()?, + self.scale + .map(|scale| scale.partitioned(_lengths.clone())) + .transpose()?, + self.mat3x3 + .map(|mat3x3| mat3x3.partitioned(_lengths.clone())) + .transpose()?, + self.relation + .map(|relation| relation.partitioned(_lengths.clone())) + .transpose()?, + self.axis_length + .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()) + } + /// Translation vector. #[inline] pub fn with_translation( 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 c84541a5f45c9..9416ef048b8ef 100644 --- a/crates/store/re_types/src/archetypes/video_frame_reference.rs +++ b/crates/store/re_types/src/archetypes/video_frame_reference.rs @@ -317,6 +317,37 @@ impl VideoFrameReference { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.timestamp + .map(|timestamp| timestamp.partitioned(_lengths.clone())) + .transpose()?, + self.video_reference + .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()) + } + /// References the closest video frame to this timestamp. /// /// Note that this uses the closest video frame instead of the latest at this timestamp diff --git a/crates/store/re_types/src/blueprint/archetypes/background.rs b/crates/store/re_types/src/blueprint/archetypes/background.rs index edb3d0f3287d7..f6481cc28cbe3 100644 --- a/crates/store/re_types/src/blueprint/archetypes/background.rs +++ b/crates/store/re_types/src/blueprint/archetypes/background.rs @@ -191,6 +191,37 @@ impl Background { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.kind + .map(|kind| kind.partitioned(_lengths.clone())) + .transpose()?, + self.color + .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()) + } + /// The type of the background. #[inline] pub fn with_kind( 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 81eb205dd0917..d8f47a39545f6 100644 --- a/crates/store/re_types/src/blueprint/archetypes/container_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/container_blueprint.rs @@ -584,6 +584,55 @@ impl ContainerBlueprint { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.container_kind + .map(|container_kind| container_kind.partitioned(_lengths.clone())) + .transpose()?, + self.display_name + .map(|display_name| display_name.partitioned(_lengths.clone())) + .transpose()?, + self.contents + .map(|contents| contents.partitioned(_lengths.clone())) + .transpose()?, + self.col_shares + .map(|col_shares| col_shares.partitioned(_lengths.clone())) + .transpose()?, + self.row_shares + .map(|row_shares| row_shares.partitioned(_lengths.clone())) + .transpose()?, + self.active_tab + .map(|active_tab| active_tab.partitioned(_lengths.clone())) + .transpose()?, + self.visible + .map(|visible| visible.partitioned(_lengths.clone())) + .transpose()?, + self.grid_columns + .map(|grid_columns| grid_columns.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The class of the view. #[inline] pub fn with_container_kind( 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..509412b3406ac 100644 --- a/crates/store/re_types/src/blueprint/archetypes/dataframe_query.rs +++ b/crates/store/re_types/src/blueprint/archetypes/dataframe_query.rs @@ -284,6 +284,46 @@ impl DataframeQuery { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.timeline + .map(|timeline| timeline.partitioned(_lengths.clone())) + .transpose()?, + self.filter_by_range + .map(|filter_by_range| filter_by_range.partitioned(_lengths.clone())) + .transpose()?, + self.filter_is_not_null + .map(|filter_is_not_null| filter_is_not_null.partitioned(_lengths.clone())) + .transpose()?, + self.apply_latest_at + .map(|apply_latest_at| apply_latest_at.partitioned(_lengths.clone())) + .transpose()?, + self.select + .map(|select| select.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The timeline for this query. /// /// If unset, the timeline currently active on the time panel is used. 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..e1aedf6c852a8 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_center.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_center.rs @@ -198,6 +198,37 @@ impl ForceCenter { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.enabled + .map(|enabled| enabled.partitioned(_lengths.clone())) + .transpose()?, + self.strength + .map(|strength| strength.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Whether the center force is enabled. /// /// The center force tries to move the center of mass of the graph towards the origin. 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..2de0b3aad177f 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 @@ -231,6 +231,40 @@ impl ForceCollisionRadius { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.enabled + .map(|enabled| enabled.partitioned(_lengths.clone())) + .transpose()?, + self.strength + .map(|strength| strength.partitioned(_lengths.clone())) + .transpose()?, + self.iterations + .map(|iterations| iterations.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Whether the collision force is enabled. /// /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. 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..845a06340b9c0 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_link.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_link.rs @@ -230,6 +230,40 @@ impl ForceLink { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.enabled + .map(|enabled| enabled.partitioned(_lengths.clone())) + .transpose()?, + self.distance + .map(|distance| distance.partitioned(_lengths.clone())) + .transpose()?, + self.iterations + .map(|iterations| iterations.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Whether the link force is enabled. /// /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. 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..7f117ebb8d424 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 @@ -203,6 +203,37 @@ impl ForceManyBody { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.enabled + .map(|enabled| enabled.partitioned(_lengths.clone())) + .transpose()?, + self.strength + .map(|strength| strength.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Whether the many body force is enabled. /// /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the 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..5a883d29d8494 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_position.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_position.rs @@ -226,6 +226,40 @@ impl ForcePosition { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.enabled + .map(|enabled| enabled.partitioned(_lengths.clone())) + .transpose()?, + self.strength + .map(|strength| strength.partitioned(_lengths.clone())) + .transpose()?, + self.position + .map(|position| position.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Whether the position force is enabled. /// /// The position force pulls nodes towards a specific position, similar to gravity. 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..7f2a4d3e5d757 100644 --- a/crates/store/re_types/src/blueprint/archetypes/line_grid3d.rs +++ b/crates/store/re_types/src/blueprint/archetypes/line_grid3d.rs @@ -288,6 +288,46 @@ impl LineGrid3D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.visible + .map(|visible| visible.partitioned(_lengths.clone())) + .transpose()?, + self.spacing + .map(|spacing| spacing.partitioned(_lengths.clone())) + .transpose()?, + self.plane + .map(|plane| plane.partitioned(_lengths.clone())) + .transpose()?, + self.stroke_width + .map(|stroke_width| stroke_width.partitioned(_lengths.clone())) + .transpose()?, + self.color + .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()) + } + /// Whether the grid is visible. /// /// Defaults to true. 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..68d03e8d94847 100644 --- a/crates/store/re_types/src/blueprint/archetypes/map_background.rs +++ b/crates/store/re_types/src/blueprint/archetypes/map_background.rs @@ -167,6 +167,33 @@ impl MapBackground { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .provider + .map(|provider| provider.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Map provider and style to use. /// /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. 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..94b9bbda840bd 100644 --- a/crates/store/re_types/src/blueprint/archetypes/map_zoom.rs +++ b/crates/store/re_types/src/blueprint/archetypes/map_zoom.rs @@ -162,6 +162,33 @@ impl MapZoom { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .zoom + .map(|zoom| zoom.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Zoom level for the map. /// /// Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). 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..0f12c4437ad24 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 @@ -172,6 +172,33 @@ impl NearClipPlane { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .near_clip_plane + .map(|near_clip_plane| near_clip_plane.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Controls the distance to the near clip plane in 3D scene units. /// /// Content closer than this distance will not be visible. 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..c078ee28d667f 100644 --- a/crates/store/re_types/src/blueprint/archetypes/panel_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/panel_blueprint.rs @@ -163,6 +163,33 @@ impl PanelBlueprint { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .state + .map(|state| state.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Current state of the panels. #[inline] pub fn with_state( 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..4772b7ce26c80 100644 --- a/crates/store/re_types/src/blueprint/archetypes/plot_legend.rs +++ b/crates/store/re_types/src/blueprint/archetypes/plot_legend.rs @@ -200,6 +200,37 @@ impl PlotLegend { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.corner + .map(|corner| corner.partitioned(_lengths.clone())) + .transpose()?, + self.visible + .map(|visible| visible.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// To what corner the legend is aligned. /// /// Defaults to the right bottom corner. 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..30522b8871d22 100644 --- a/crates/store/re_types/src/blueprint/archetypes/scalar_axis.rs +++ b/crates/store/re_types/src/blueprint/archetypes/scalar_axis.rs @@ -200,6 +200,37 @@ impl ScalarAxis { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.range + .map(|range| range.partitioned(_lengths.clone())) + .transpose()?, + self.zoom_lock + .map(|zoom_lock| zoom_lock.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The range of the axis. /// /// If unset, the range well be automatically determined based on the queried data. 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..cbfbc8f9287db 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 @@ -235,6 +235,40 @@ impl TensorScalarMapping { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.mag_filter + .map(|mag_filter| mag_filter.partitioned(_lengths.clone())) + .transpose()?, + self.colormap + .map(|colormap| colormap.partitioned(_lengths.clone())) + .transpose()?, + self.gamma + .map(|gamma| gamma.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Filter used when zooming in on the tensor. /// /// Note that the filter is applied to the scalar values *before* they are mapped to color. 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..5d4763ee4dd32 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 @@ -260,6 +260,43 @@ impl TensorSliceSelection { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.width + .map(|width| width.partitioned(_lengths.clone())) + .transpose()?, + self.height + .map(|height| height.partitioned(_lengths.clone())) + .transpose()?, + self.indices + .map(|indices| indices.partitioned(_lengths.clone())) + .transpose()?, + self.slider + .map(|slider| slider.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// Which dimension to map to width. /// /// If not specified, the height will be determined automatically based on the name and index of the dimension. 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..8f961904176bd 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 @@ -163,6 +163,33 @@ impl TensorViewFit { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .scaling + .map(|scaling| scaling.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// How the image is scaled to fit the view. #[inline] pub fn with_scaling( 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..066f0f33c5e30 100644 --- a/crates/store/re_types/src/blueprint/archetypes/view_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/view_blueprint.rs @@ -265,6 +265,43 @@ impl ViewBlueprint { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.class_identifier + .map(|class_identifier| class_identifier.partitioned(_lengths.clone())) + .transpose()?, + self.display_name + .map(|display_name| display_name.partitioned(_lengths.clone())) + .transpose()?, + self.space_origin + .map(|space_origin| space_origin.partitioned(_lengths.clone())) + .transpose()?, + self.visible + .map(|visible| visible.partitioned(_lengths.clone())) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The class of the view. #[inline] pub fn with_class_identifier( 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..ae66091884dfc 100644 --- a/crates/store/re_types/src/blueprint/archetypes/view_contents.rs +++ b/crates/store/re_types/src/blueprint/archetypes/view_contents.rs @@ -206,6 +206,33 @@ impl ViewContents { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .query + .map(|query| query.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The `QueryExpression` that populates the contents for the view. /// /// They determine which entities are part of the view. 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..bffb6ed842c6d 100644 --- a/crates/store/re_types/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/store/re_types/src/blueprint/archetypes/viewport_blueprint.rs @@ -299,6 +299,48 @@ impl ViewportBlueprint { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.root_container + .map(|root_container| root_container.partitioned(_lengths.clone())) + .transpose()?, + self.maximized + .map(|maximized| maximized.partitioned(_lengths.clone())) + .transpose()?, + self.auto_layout + .map(|auto_layout| auto_layout.partitioned(_lengths.clone())) + .transpose()?, + self.auto_views + .map(|auto_views| auto_views.partitioned(_lengths.clone())) + .transpose()?, + self.past_viewer_recommendations + .map(|past_viewer_recommendations| { + past_viewer_recommendations.partitioned(_lengths.clone()) + }) + .transpose()?, + ]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The layout of the views #[inline] pub fn with_root_container( 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..58874101f3726 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 @@ -177,6 +177,33 @@ impl VisibleTimeRanges { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .ranges + .map(|ranges| ranges.partitioned(_lengths.clone())) + .transpose()?]; + let indicator_column = + ::re_types_core::indicator_column::(_lengths.into_iter().count())?; + Ok(columns.into_iter().chain([indicator_column]).flatten()) + } + /// The time ranges to show for each timeline unless specified otherwise on a per-entity basis. /// /// If a timeline is specified more than once, the first entry will be used. 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..4ce35a58d2421 100644 --- a/crates/store/re_types/src/blueprint/archetypes/visual_bounds2d.rs +++ b/crates/store/re_types/src/blueprint/archetypes/visual_bounds2d.rs @@ -173,6 +173,33 @@ impl VisualBounds2D { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .range + .map(|range| 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()) + } + /// Controls the visible range of a 2D view. /// /// Use this to control pan & zoom of the view. diff --git a/crates/store/re_types_core/src/archetypes/clear.rs b/crates/store/re_types_core/src/archetypes/clear.rs index 2c0223e8506a8..423a199486ef1 100644 --- a/crates/store/re_types_core/src/archetypes/clear.rs +++ b/crates/store/re_types_core/src/archetypes/clear.rs @@ -220,6 +220,32 @@ impl Clear { } } + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// 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. + /// + /// [`SerializedComponentColumn`]: [crate::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .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()) + } + #[inline] pub fn with_is_recursive( mut self, diff --git a/crates/store/re_types_core/src/lib.rs b/crates/store/re_types_core/src/lib.rs index bd3943bff017a..ee11f28a44d3f 100644 --- a/crates/store/re_types_core/src/lib.rs +++ b/crates/store/re_types_core/src/lib.rs @@ -52,7 +52,7 @@ pub use self::{ }, loggable_batch::{ ComponentBatch, ComponentBatchCow, ComponentBatchCowWithDescriptor, LoggableBatch, - SerializedComponentBatch, + SerializedComponentBatch, SerializedComponentColumn, }, result::{ DeserializationError, DeserializationResult, ResultExt, SerializationError, @@ -187,3 +187,35 @@ pub fn try_serialize_field( } } } + +/// Internal serialization helper for code-generated archetypes. +/// +/// This generates a correctly sized [`SerializedComponentColumn`] for a given indicator, where the +/// specified `num_rows` value represents the number of rows in the column. +#[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) + }) + .transpose() +} diff --git a/crates/store/re_types_core/src/loggable_batch.rs b/crates/store/re_types_core/src/loggable_batch.rs index 326e860128e9f..f483c97f0dd6e 100644 --- a/crates/store/re_types_core/src/loggable_batch.rs +++ b/crates/store/re_types_core/src/loggable_batch.rs @@ -149,6 +149,8 @@ fn assert_component_batch_object_safe() { let _: &dyn LoggableBatch; } +// --- + /// The serialized contents of a [`ComponentBatch`] with associated [`ComponentDescriptor`]. /// /// This is what gets logged into Rerun: @@ -229,6 +231,81 @@ impl SerializedComponentBatch { } } +/// A column's worth of component data. +/// +/// If a [`SerializedComponentBatch`] represents one row's worth of data +#[derive(Debug, Clone)] +pub struct SerializedComponentColumn { + pub list_array: arrow::array::ListArray, + + // TODO(cmc): Maybe Cow<> this one if it grows bigger. Or intern descriptors altogether, most likely. + pub descriptor: ComponentDescriptor, +} + +impl SerializedComponentColumn { + /// Repartitions the component data into multiple sub-batches, ignoring the previous partitioning. + /// + /// The specified `lengths` must sum to the total length of the component batch. + pub fn repartitioned( + self, + lengths: impl IntoIterator, + ) -> SerializationResult { + let Self { + list_array, + descriptor, + } = self; + + let list_array = re_arrow_util::arrow_util::repartition_list_array(list_array, lengths)?; + + Ok(Self { + list_array, + descriptor, + }) + } +} + +impl From for SerializedComponentColumn { + #[inline] + fn from(batch: SerializedComponentBatch) -> Self { + use arrow::{ + array::{Array, ListArray}, + buffer::OffsetBuffer, + datatypes::Field, + }; + + let list_array = { + let nullable = true; + let field = Field::new_list_field(batch.array.data_type().clone(), nullable); + let offsets = OffsetBuffer::from_lengths(std::iter::once(batch.array.len())); + let nulls = None; + ListArray::new(field.into(), offsets, batch.array, nulls) + }; + + Self { + list_array, + descriptor: batch.descriptor, + } + } +} + +impl SerializedComponentBatch { + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`] data into a [`SerializedComponentColumn`]. + /// + /// 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. + #[inline] + pub fn partitioned( + self, + lengths: impl IntoIterator, + ) -> SerializationResult { + let column: SerializedComponentColumn = self.into(); + column.repartitioned(lengths) + } +} + // --- // TODO(cmc): This is far from ideal and feels very hackish, but for now the priority is getting diff --git a/crates/top/re_sdk/src/lib.rs b/crates/top/re_sdk/src/lib.rs index 5756313ef465b..42b49e20c4cd0 100644 --- a/crates/top/re_sdk/src/lib.rs +++ b/crates/top/re_sdk/src/lib.rs @@ -95,7 +95,7 @@ pub use re_types_core::{ ComponentBatchCowWithDescriptor, ComponentDescriptor, ComponentName, DatatypeName, DeserializationError, DeserializationResult, GenericIndicatorComponent, Loggable, LoggableBatch, NamedIndicatorComponent, SerializationError, SerializationResult, - SerializedComponentBatch, + 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 d3880df771ed7..fef81b467d02f 100644 --- a/crates/top/re_sdk/src/recording_stream.rs +++ b/crates/top/re_sdk/src/recording_stream.rs @@ -18,7 +18,7 @@ use re_log_types::{ StoreId, StoreInfo, StoreKind, StoreSource, Time, TimeInt, TimePoint, TimeType, Timeline, TimelineName, }; -use re_types_core::{AsComponents, SerializationError}; +use re_types_core::{AsComponents, SerializationError, SerializedComponentColumn}; #[cfg(feature = "web_viewer")] use re_web_viewer_server::WebViewerServerPort; @@ -1030,6 +1030,41 @@ impl RecordingStream { 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 + /// in a columnar form. The lengths of all of the [`TimeColumn`] and the component columns + /// 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. + pub fn send_columns_v2( + &self, + ent_path: impl Into, + indexes: impl IntoIterator, + columns: impl IntoIterator, + ) -> RecordingStreamResult<()> { + let id = ChunkId::new(); + + let indexes = indexes + .into_iter() + .map(|timeline| (*timeline.timeline(), timeline)) + .collect::>(); + + let components: ChunkComponents = columns + .into_iter() + .map(|column| (column.descriptor, column.list_array)) + .collect(); + + let chunk = Chunk::from_auto_row_ids(id, ent_path.into(), indexes, components)?; + + self.send_chunk(chunk); + + Ok(()) + } + /// Log data to Rerun. /// /// It can be used to log anything diff --git a/crates/utils/re_arrow_util/src/arrow_util.rs b/crates/utils/re_arrow_util/src/arrow_util.rs index 3de1a54c1f565..b69fb1e052d52 100644 --- a/crates/utils/re_arrow_util/src/arrow_util.rs +++ b/crates/utils/re_arrow_util/src/arrow_util.rs @@ -32,7 +32,7 @@ pub fn into_arrow_ref(array: impl Array + 'static) -> ArrayRef { std::sync::Arc::new(array) } -/// Returns an iterator with the lengths of the offsets +/// Returns an iterator with the lengths of the offsets. pub fn offsets_lengths( offsets: &arrow::buffer::OffsetBuffer, ) -> impl Iterator + '_ { @@ -48,6 +48,24 @@ pub fn offsets_lengths( }) } +/// Repartitions a [`ListArray`] according to the specified `lengths`, ignoring previous partitioning. +/// +/// The specified `lengths` must sum to the total length underlying values (i.e. the child array). +/// +/// The validity of the values is ignored. +#[inline] +pub fn repartition_list_array( + list_array: ListArray, + lengths: impl IntoIterator, +) -> arrow::error::Result { + let (field, _offsets, values, _nulls) = list_array.into_parts(); + + let offsets = OffsetBuffer::from_lengths(lengths); + let nulls = None; + + ListArray::try_new(field, offsets, values, nulls) +} + /// Returns true if the given `list_array` is semantically empty. /// /// Semantic emptiness is defined as either one of these: diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index c34be42a0af04..65af664f70b8b 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -128,7 +128,7 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`Points2D`](https://rerun.io/docs/reference/types/archetypes/points2d)** | `views/spatial2d` | Use a blueprint to customize a Spatial2DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial2d.py) | | | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `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) | | **[`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.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) | @@ -203,7 +203,7 @@ _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.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) | | | @@ -226,7 +226,7 @@ _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.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) | @@ -237,6 +237,7 @@ _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.cpp b/docs/snippets/all/archetypes/points3d_send_columns.cpp index a803540717443..72b57ac72132f 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.cpp +++ b/docs/snippets/all/archetypes/points3d_send_columns.cpp @@ -7,10 +7,10 @@ using namespace std::chrono_literals; int main() { - const auto rec = rerun::RecordingStream("rerun_example_send_columns_arrays"); + const auto rec = rerun::RecordingStream("rerun_example_points3d_send_columns"); rec.spawn().exit_on_failure(); - // Prepare a point cloud that evolves over time 5 timesteps, changing the number of points in the process. + // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. std::vector> positions = { // clang-format off {1.0, 0.0, 1.0}, {0.5, 0.5, 2.0}, @@ -23,6 +23,7 @@ int main() { // At each time stamp, all points in the cloud share the same but changing color. std::vector colors = {0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF}; + std::vector radii = {0.05f, 0.01f, 0.2f, 0.1f, 0.3f}; // Log at seconds 10-14 auto times = rerun::Collection{10s, 11s, 12s, 13s, 14s}; @@ -37,7 +38,11 @@ int main() { 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, @@ -45,6 +50,7 @@ int main() { indicator_batch.value_or_throw(), position_batch.value_or_throw(), color_batch.value_or_throw(), + radius_batch.value_or_throw(), } ); } diff --git a/docs/snippets/all/archetypes/points3d_send_columns.py b/docs/snippets/all/archetypes/points3d_send_columns.py index f697a6c5b53f2..2117c22c2e2df 100644 --- a/docs/snippets/all/archetypes/points3d_send_columns.py +++ b/docs/snippets/all/archetypes/points3d_send_columns.py @@ -5,28 +5,33 @@ import numpy as np import rerun as rr -rr.init("rerun_example_send_columns_arrays", spawn=True) +rr.init("rerun_example_points3d_send_columns", spawn=True) -# Prepare a point cloud that evolves over time 5 timesteps, changing the number of points in the process. +# 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]], + [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 positions_arr = np.concatenate(positions) -# At each time stamp, all points in the cloud share the same but changing color. +# 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( "points", times=[rr.TimeSecondsColumn("time", times)], components=[ rr.Points3D.indicator(), - rr.components.Position3DBatch(positions_arr).partition([len(row) for row in positions]), + rr.components.Position3DBatch(positions_arr).partition([2, 4, 4, 3, 4]), rr.components.ColorBatch(colors), + rr.components.RadiusBatch(radii), ], ) diff --git a/docs/snippets/all/archetypes/points3d_send_columns.rs b/docs/snippets/all/archetypes/points3d_send_columns.rs new file mode 100644 index 0000000000000..110ec6a871d5b --- /dev/null +++ b/docs/snippets/all/archetypes/points3d_send_columns.rs @@ -0,0 +1,36 @@ +//! Use the `send_columns` API to send several point clouds over time in a single call. + +use rerun::TimeColumn; + +fn main() -> Result<(), Box> { + let rec = rerun::RecordingStreamBuilder::new("rerun_example_points3d_send_columns").spawn()?; + + // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. + let times = TimeColumn::new_seconds("time", 10..15); + + #[rustfmt::skip] + let 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], + ]; + + // At each timestep, all points in the cloud share the same but changing color and radius. + let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF]; + let radii = [0.05, 0.01, 0.2, 0.1, 0.3]; + + // Partition our data as expected across the 5 timesteps. + let position = rerun::Points3D::update_fields() + .with_positions(positions) + .columns([2, 4, 4, 3, 4])?; + let color_and_radius = rerun::Points3D::update_fields() + .with_colors(colors) + .with_radii(radii) + .columns([1, 1, 1, 1, 1])?; + + rec.send_columns_v2("points", [times], position.chain(color_and_radius))?; + + Ok(()) +} diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 7898423ce0e72..4ed1ed51e0618 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -91,9 +91,6 @@ "cpp", # Missing examples "rust", # Missing examples ] -"archetypes/points3d_send_columns" = [ - "rust", # Doesn't support partitioned component batches yet. -] "howto/any_batch_value_send_columns" = [ "cpp", # Not implemented "rust", # Not implemented @@ -234,6 +231,10 @@ quick_start = [ # These examples don't have exactly the same implementation. "archetypes/points3d_partial_updates" = [ # TODO(cmc): revert once C++ has tagged partial updates "cpp", ] +"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 "cpp", "py", diff --git a/lychee.toml b/lychee.toml index 26cd9309d0175..6c64616abe8b6 100644 --- a/lychee.toml +++ b/lychee.toml @@ -160,6 +160,7 @@ exclude = [ 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp', '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_send_columns.rs', 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.cpp', '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', diff --git a/rerun_cpp/src/rerun/archetypes/points3d.hpp b/rerun_cpp/src/rerun/archetypes/points3d.hpp index 392cfa16229a7..69be252a65bb9 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.hpp @@ -111,10 +111,10 @@ namespace rerun::archetypes { /// using namespace std::chrono_literals; /// /// int main() { - /// const auto rec = rerun::RecordingStream("rerun_example_send_columns_arrays"); + /// const auto rec = rerun::RecordingStream("rerun_example_points3d_send_columns"); /// rec.spawn().exit_on_failure(); /// - /// // Prepare a point cloud that evolves over time 5 timesteps, changing the number of points in the process. + /// // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. /// std::vector> positions = { /// // clang-format off /// {1.0, 0.0, 1.0}, {0.5, 0.5, 2.0}, @@ -127,6 +127,7 @@ namespace rerun::archetypes { /// /// // At each time stamp, all points in the cloud share the same but changing color. /// std::vector colors = {0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF}; + /// std::vector radii = {0.05f, 0.01f, 0.2f, 0.1f, 0.3f}; /// /// // Log at seconds 10-14 /// auto times = rerun::Collection{10s, 11s, 12s, 13s, 14s}; @@ -141,7 +142,11 @@ namespace rerun::archetypes { /// 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, @@ -149,6 +154,7 @@ namespace rerun::archetypes { /// indicator_batch.value_or_throw(), /// position_batch.value_or_throw(), /// color_batch.value_or_throw(), + /// radius_batch.value_or_throw(), /// } /// ); /// } diff --git a/rerun_py/rerun_sdk/rerun/_send_columns.py b/rerun_py/rerun_sdk/rerun/_send_columns.py index 683d442f60537..1639a8ded6334 100644 --- a/rerun_py/rerun_sdk/rerun/_send_columns.py +++ b/rerun_py/rerun_sdk/rerun/_send_columns.py @@ -210,7 +210,7 @@ def send_columns( expected_length = len(time_column) elif len(time_column) != expected_length: raise ValueError( - f"All times and components in a batch must have the same length. Expected length: {expected_length} but got: {len(time_column)} for timeline: {timeline_name}" + 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 diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index 59e04a50f8c36..da0ba3e6ae8b2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -95,29 +95,34 @@ class Points3D(Points3DExt, Archetype): import numpy as np import rerun as rr - rr.init("rerun_example_send_columns_arrays", spawn=True) + rr.init("rerun_example_points3d_send_columns", spawn=True) - # Prepare a point cloud that evolves over time 5 timesteps, changing the number of points in the process. + # 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]], + [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 positions_arr = np.concatenate(positions) - # At each time stamp, all points in the cloud share the same but changing color. + # 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( "points", times=[rr.TimeSecondsColumn("time", times)], components=[ rr.Points3D.indicator(), - rr.components.Position3DBatch(positions_arr).partition([len(row) for row in positions]), + rr.components.Position3DBatch(positions_arr).partition([2, 4, 4, 3, 4]), rr.components.ColorBatch(colors), + rr.components.RadiusBatch(radii), ], ) ``` From e7318f39650015c520224d9dfc63d3aaf80cf26d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 21 Jan 2025 20:14:07 +0100 Subject: [PATCH 3/4] Introduce eager serialization & update/clear APIs in the C++ SDK (#8727) --- .../re_types_builder/src/codegen/cpp/mod.rs | 305 +++++++++++++----- crates/build/re_types_builder/src/lib.rs | 1 + .../re_types/definitions/attributes/cpp.fbs | 6 + .../re_types/definitions/attributes/rust.fbs | 1 + .../rerun/archetypes/annotation_context.fbs | 1 + .../definitions/rerun/archetypes/arrows2d.fbs | 1 + .../definitions/rerun/archetypes/arrows3d.fbs | 1 + .../definitions/rerun/archetypes/points3d.fbs | 3 +- .../rerun/archetypes/transform3d.fbs | 1 + .../rerun/blueprint/archetypes/background.fbs | 5 +- .../archetypes/container_blueprint.fbs | 1 + .../blueprint/archetypes/dataframe_query.fbs | 1 + .../blueprint/archetypes/force_center.fbs | 1 + .../archetypes/force_collision_radius.fbs | 1 + .../rerun/blueprint/archetypes/force_link.fbs | 1 + .../blueprint/archetypes/force_many_body.fbs | 1 + .../blueprint/archetypes/force_position.fbs | 1 + .../blueprint/archetypes/line_grid3d.fbs | 1 + .../blueprint/archetypes/map_background.fbs | 1 + .../rerun/blueprint/archetypes/map_zoom.fbs | 1 + .../blueprint/archetypes/near_clip_plane.fbs | 1 + .../blueprint/archetypes/panel_blueprint.fbs | 1 + .../blueprint/archetypes/plot_legend.fbs | 1 + .../blueprint/archetypes/scalar_axis.fbs | 1 + .../archetypes/tensor_scalar_mapping.fbs | 1 + .../archetypes/tensor_slice_selection.fbs | 1 + .../blueprint/archetypes/tensor_view_fit.fbs | 1 + .../blueprint/archetypes/view_blueprint.fbs | 1 + .../blueprint/archetypes/view_contents.fbs | 1 + .../archetypes/viewport_blueprint.fbs | 1 + .../archetypes/visible_time_ranges.fbs | 1 + .../blueprint/archetypes/visual_bounds2d.fbs | 1 + .../archetypes/points3d_partial_updates.cpp | 18 +- .../transform3d_partial_updates.cpp | 17 +- docs/snippets/snippets.toml | 16 +- .../rerun/archetypes/annotation_context.cpp | 23 +- .../rerun/archetypes/annotation_context.hpp | 33 +- rerun_cpp/src/rerun/archetypes/arrows2d.cpp | 104 ++---- rerun_cpp/src/rerun/archetypes/arrows2d.hpp | 109 +++++-- .../src/rerun/archetypes/arrows2d_ext.cpp | 4 +- rerun_cpp/src/rerun/archetypes/arrows3d.cpp | 90 ++---- rerun_cpp/src/rerun/archetypes/arrows3d.hpp | 97 ++++-- .../src/rerun/archetypes/arrows3d_ext.cpp | 4 +- rerun_cpp/src/rerun/archetypes/asset3d.hpp | 5 + .../src/rerun/archetypes/asset_video.hpp | 5 + rerun_cpp/src/rerun/archetypes/bar_chart.hpp | 5 + rerun_cpp/src/rerun/archetypes/boxes2d.hpp | 5 + rerun_cpp/src/rerun/archetypes/boxes3d.hpp | 5 + rerun_cpp/src/rerun/archetypes/capsules3d.hpp | 5 + rerun_cpp/src/rerun/archetypes/clear.hpp | 5 + .../src/rerun/archetypes/depth_image.hpp | 5 + .../src/rerun/archetypes/ellipsoids3d.hpp | 5 + .../src/rerun/archetypes/encoded_image.hpp | 5 + .../src/rerun/archetypes/geo_line_strings.hpp | 5 + rerun_cpp/src/rerun/archetypes/geo_points.hpp | 5 + .../src/rerun/archetypes/graph_edges.hpp | 5 + .../src/rerun/archetypes/graph_nodes.hpp | 5 + rerun_cpp/src/rerun/archetypes/image.hpp | 5 + .../src/rerun/archetypes/instance_poses3d.hpp | 5 + .../src/rerun/archetypes/line_strips2d.hpp | 5 + .../src/rerun/archetypes/line_strips3d.hpp | 5 + rerun_cpp/src/rerun/archetypes/mesh3d.hpp | 5 + rerun_cpp/src/rerun/archetypes/pinhole.hpp | 5 + rerun_cpp/src/rerun/archetypes/points2d.hpp | 5 + rerun_cpp/src/rerun/archetypes/points3d.cpp | 92 ++---- rerun_cpp/src/rerun/archetypes/points3d.hpp | 99 ++++-- rerun_cpp/src/rerun/archetypes/scalar.hpp | 5 + .../rerun/archetypes/segmentation_image.hpp | 5 + .../src/rerun/archetypes/series_line.hpp | 5 + .../src/rerun/archetypes/series_point.hpp | 5 + rerun_cpp/src/rerun/archetypes/tensor.hpp | 5 + .../src/rerun/archetypes/text_document.hpp | 5 + rerun_cpp/src/rerun/archetypes/text_log.hpp | 5 + .../src/rerun/archetypes/transform3d.cpp | 119 +++---- .../src/rerun/archetypes/transform3d.hpp | 200 ++++++++---- .../src/rerun/archetypes/transform3d_ext.cpp | 90 ++++-- .../archetypes/video_frame_reference.hpp | 5 + .../src/rerun/archetypes/view_coordinates.hpp | 5 + .../rerun/blueprint/archetypes/background.cpp | 36 +-- .../rerun/blueprint/archetypes/background.hpp | 41 ++- .../archetypes/container_blueprint.cpp | 125 +++---- .../archetypes/container_blueprint.hpp | 124 +++++-- .../blueprint/archetypes/dataframe_query.cpp | 83 ++--- .../blueprint/archetypes/dataframe_query.hpp | 78 ++++- .../blueprint/archetypes/force_center.cpp | 35 +- .../blueprint/archetypes/force_center.hpp | 37 ++- .../archetypes/force_collision_radius.cpp | 50 ++- .../archetypes/force_collision_radius.hpp | 52 ++- .../rerun/blueprint/archetypes/force_link.cpp | 50 ++- .../rerun/blueprint/archetypes/force_link.hpp | 50 ++- .../blueprint/archetypes/force_many_body.cpp | 35 +- .../blueprint/archetypes/force_many_body.hpp | 38 ++- .../blueprint/archetypes/force_position.cpp | 49 ++- .../blueprint/archetypes/force_position.hpp | 50 ++- .../blueprint/archetypes/line_grid3d.cpp | 75 ++--- .../blueprint/archetypes/line_grid3d.hpp | 68 +++- .../blueprint/archetypes/map_background.cpp | 23 +- .../blueprint/archetypes/map_background.hpp | 36 ++- .../rerun/blueprint/archetypes/map_zoom.cpp | 23 +- .../rerun/blueprint/archetypes/map_zoom.hpp | 36 ++- .../blueprint/archetypes/near_clip_plane.cpp | 25 +- .../blueprint/archetypes/near_clip_plane.hpp | 41 ++- .../blueprint/archetypes/panel_blueprint.cpp | 21 +- .../blueprint/archetypes/panel_blueprint.hpp | 25 +- .../blueprint/archetypes/plot_legend.cpp | 35 +- .../blueprint/archetypes/plot_legend.hpp | 36 ++- .../blueprint/archetypes/scalar_axis.cpp | 36 +-- .../blueprint/archetypes/scalar_axis.hpp | 38 ++- .../archetypes/tensor_scalar_mapping.cpp | 48 +-- .../archetypes/tensor_scalar_mapping.hpp | 52 ++- .../archetypes/tensor_slice_selection.cpp | 66 ++-- .../archetypes/tensor_slice_selection.hpp | 61 +++- .../blueprint/archetypes/tensor_view_fit.cpp | 21 +- .../blueprint/archetypes/tensor_view_fit.hpp | 25 +- .../blueprint/archetypes/view_blueprint.cpp | 66 ++-- .../blueprint/archetypes/view_blueprint.hpp | 74 ++++- .../blueprint/archetypes/view_contents.cpp | 23 +- .../blueprint/archetypes/view_contents.hpp | 37 ++- .../archetypes/viewport_blueprint.cpp | 81 ++--- .../archetypes/viewport_blueprint.hpp | 84 ++++- .../archetypes/visible_time_ranges.cpp | 23 +- .../archetypes/visible_time_ranges.hpp | 38 ++- .../blueprint/archetypes/visual_bounds2d.cpp | 23 +- .../blueprint/archetypes/visual_bounds2d.hpp | 35 +- rerun_cpp/src/rerun/component_batch.hpp | 16 +- .../src/rerun/components/transform_mat3x3.hpp | 5 + .../rerun/components/transform_mat3x3_ext.cpp | 9 + rerun_cpp/src/rerun/error.hpp | 10 +- rerun_cpp/src/rerun/result.hpp | 22 +- .../tests/archetypes/annotation_context.cpp | 6 +- rerun_cpp/tests/archetypes/archetype_test.hpp | 2 +- rerun_cpp/tests/archetypes/arrows3d.cpp | 36 ++- rerun_cpp/tests/archetypes/points3d.cpp | 45 ++- rerun_cpp/tests/archetypes/transform3d.cpp | 146 +++++++-- .../generated/archetypes/affix_fuzzer1.hpp | 5 + .../generated/archetypes/affix_fuzzer2.hpp | 5 + .../generated/archetypes/affix_fuzzer3.hpp | 5 + .../generated/archetypes/affix_fuzzer4.hpp | 5 + scripts/ci/check_large_files.py | 1 + 139 files changed, 2711 insertions(+), 1427 deletions(-) create mode 100644 rerun_cpp/src/rerun/components/transform_mat3x3_ext.cpp 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 d363c49b6d578..17f814f2c0d69 100644 --- a/crates/build/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/build/re_types_builder/src/codegen/cpp/mod.rs @@ -16,7 +16,7 @@ use crate::{ format_path, objects::ObjectClass, ArrowRegistry, Docs, ElementType, GeneratedFiles, Object, ObjectField, ObjectKind, Objects, - Reporter, Type, ATTR_CPP_NO_FIELD_CTORS, ATTR_CPP_RENAME_FIELD, + Reporter, Type, ATTR_CPP_ARCHETYPE_EAGER, ATTR_CPP_NO_FIELD_CTORS, ATTR_CPP_RENAME_FIELD, ATTR_RERUN_LOG_MISSING_AS_EMPTY, }; @@ -451,8 +451,11 @@ impl QuotedObject { hpp_type_extensions: &TokenStream, ) -> Self { let type_ident = obj.ident(); + let archetype_name = &obj.fqname; let quoted_docs = quote_obj_docs(reporter, objects, obj); + let eager_serialization = obj.is_attr_set(ATTR_CPP_ARCHETYPE_EAGER); + let mut cpp_includes = Includes::new(obj.fqname.clone(), obj.scope()); cpp_includes.insert_rerun("collection_adapter_builtins.hpp"); hpp_includes.insert_system("utility"); // std::move @@ -463,19 +466,30 @@ impl QuotedObject { .iter() .map(|obj_field| { let docstring = quote_field_docs(reporter, objects, obj_field); - let field_name = field_name_identifier(obj_field); - let field_type = quote_archetype_field_type(&mut hpp_includes, obj_field); - let field_type = if obj_field.is_nullable { + let field_name = field_name_ident(obj_field); + + if eager_serialization { hpp_includes.insert_system("optional"); - quote! { std::optional<#field_type> } + quote! { + #NEWLINE_TOKEN + #docstring + std::optional #field_name + } } else { - field_type - }; + let field_type = + quote_archetype_unserialized_type(&mut hpp_includes, obj_field); + let field_type = if obj_field.is_nullable { + hpp_includes.insert_system("optional"); + quote! { std::optional<#field_type> } + } else { + field_type + }; - quote! { + quote! { #NEWLINE_TOKEN #docstring #field_type #field_name + } } }) .collect_vec(); @@ -493,13 +507,19 @@ impl QuotedObject { let (parameters, assignments): (Vec<_>, Vec<_>) = required_component_fields .iter() .map(|obj_field| { - let field_type = quote_archetype_field_type(&mut hpp_includes, obj_field); - let field_ident = field_name_identifier(obj_field); + let field_type = + quote_archetype_unserialized_type(&mut hpp_includes, obj_field); + let field_ident = field_name_ident(obj_field); // C++ compilers give warnings for re-using the same name as the member variable. let parameter_ident = format_ident!("_{}", obj_field.name); ( quote! { #field_type #parameter_ident }, - quote! { #field_ident(std::move(#parameter_ident)) }, + if eager_serialization { + let descriptor = archetype_component_descriptor_constant_ident(obj_field); + quote! { #field_ident(ComponentBatch::from_loggable(std::move(#parameter_ident), #descriptor).value_or_throw()) } + } else { + quote! { #field_ident(std::move(#parameter_ident)) } + }, ) }) .unzip(); @@ -514,35 +534,140 @@ impl QuotedObject { }); } - // Builder methods for all optional components. - for obj_field in obj.fields.iter().filter(|field| field.is_nullable) { - let field_ident = field_name_identifier(obj_field); - // C++ compilers give warnings for re-using the same name as the member variable. - let parameter_ident = format_ident!("_{}", obj_field.name); - let method_ident = format_ident!("with_{}", obj_field.name); - let field_type = quote_archetype_field_type(&mut hpp_includes, obj_field); - - hpp_includes.insert_rerun("compiler_utils.hpp"); - let gcc_ignore_comment = - quote_comment("See: https://github.com/rerun-io/rerun/issues/4027"); + let descriptor_constants = if eager_serialization { + obj.fields + .iter() + .map(|obj_field| { + let field_name = field_name(obj_field); + let comment = quote_doc_comment(&format!("`ComponentDescriptor` for the `{field_name}` field.")); + let constant_name = archetype_component_descriptor_constant_ident(obj_field); + let field_type = obj_field.typ.fqname(); + let field_type = quote_fqname_as_type_path( + &mut hpp_includes, + field_type.expect("Component field must have a non trivial type"), + ); + quote! { + #NEWLINE_TOKEN + #comment + static constexpr auto #constant_name = ComponentDescriptor( + ArchetypeName, #field_name, Loggable<#field_type>::Descriptor.component_name + ); + } + }) + .collect_vec() + } else { + Vec::new() + }; + if eager_serialization { + // update_fields method - this is equivalent to the default constructor. methods.push(Method { - docs: obj_field.docs.clone().into(), + docs: format!("Update only some specific fields of a `{type_ident}`.").into(), declaration: MethodDeclaration { - is_static: false, + is_static: true, return_type: quote!(#type_ident), - name_and_parameters: quote! { - #method_ident(#field_type #parameter_ident) && - }, + name_and_parameters: quote! { update_fields() }, }, definition_body: quote! { - #field_ident = std::move(#parameter_ident); - #NEWLINE_TOKEN - #gcc_ignore_comment - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + return #type_ident(); }, inline: true, }); + + // clear_fields method. + methods.push(Method { + docs: format!("Clear all the fields of a `{type_ident}`.").into(), + declaration: MethodDeclaration { + is_static: true, + return_type: quote!(#type_ident), + name_and_parameters: quote! { clear_fields() }, + }, + definition_body: { + let field_assignments = obj.fields.iter().map(|obj_field| { + let field_ident = field_name_ident(obj_field); + let field_type = obj_field.typ.fqname(); + let field_type = quote_fqname_as_type_path( + &mut hpp_includes, + field_type.expect("Component field must have a non trivial type"), + ); + let descriptor = archetype_component_descriptor_constant_ident(obj_field); + quote! { + archetype.#field_ident = ComponentBatch::empty<#field_type>(#descriptor).value_or_throw(); + } + }); + + quote! { + auto archetype = #type_ident(); + #(#field_assignments)* + return archetype; + } + }, + inline: false, + }); + + // Builder methods for all components. + for obj_field in &obj.fields { + let field_ident = field_name_ident(obj_field); + // C++ compilers give warnings for re-using the same name as the member variable. + let parameter_ident = format_ident!("_{}", obj_field.name); + let method_ident = format_ident!("with_{}", obj_field.name); + let field_type = quote_archetype_unserialized_type(&mut hpp_includes, obj_field); + let descriptor = archetype_component_descriptor_constant_ident(obj_field); + + // TODO(andreas): Haven't tested this again since introducing eager serialization. + hpp_includes.insert_rerun("compiler_utils.hpp"); + let gcc_ignore_comment = + quote_comment("See: https://github.com/rerun-io/rerun/issues/4027"); + + methods.push(Method { + docs: obj_field.docs.clone().into(), + declaration: MethodDeclaration { + is_static: false, + return_type: quote!(#type_ident), + name_and_parameters: quote! { + #method_ident(const #field_type& #parameter_ident) && + }, + }, + definition_body: quote! { + #field_ident = ComponentBatch::from_loggable(#parameter_ident, #descriptor).value_or_throw(); + #NEWLINE_TOKEN + #gcc_ignore_comment + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + }, + inline: true, + }); + } + } else { + // Builder methods for all optional components. + for obj_field in obj.fields.iter().filter(|field| field.is_nullable) { + let field_ident = field_name_ident(obj_field); + // C++ compilers give warnings for re-using the same name as the member variable. + let parameter_ident = format_ident!("_{}", obj_field.name); + let method_ident = format_ident!("with_{}", obj_field.name); + let field_type = quote_archetype_unserialized_type(&mut hpp_includes, obj_field); + + hpp_includes.insert_rerun("compiler_utils.hpp"); + let gcc_ignore_comment = + quote_comment("See: https://github.com/rerun-io/rerun/issues/4027"); + + methods.push(Method { + docs: obj_field.docs.clone().into(), + declaration: MethodDeclaration { + is_static: false, + return_type: quote!(#type_ident), + name_and_parameters: quote! { + #method_ident(#field_type #parameter_ident) && + }, + }, + definition_body: quote! { + #field_ident = std::move(#parameter_ident); + #NEWLINE_TOKEN + #gcc_ignore_comment + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + }, + inline: true, + }); + } } let quoted_namespace = if let Some(scope) = obj.scope() { @@ -567,6 +692,8 @@ impl QuotedObject { format!("{}Indicator", obj.fqname).replace("archetypes", "components"); let doc_hide_comment = quote_hide_from_docs(); let deprecation_notice = quote_deprecation_notice(obj); + let name_doc_string = + quote_doc_comment("The name of the archetype as used in `ComponentDescriptor`s."); // Note that GCC doesn't like using deprecated fields even if the archetype itself is deprecated. // In that case we're just being generous with the ignore warnings, making it finegrained is hard and not really worth it anyways. @@ -583,6 +710,12 @@ impl QuotedObject { obj.deprecation_notice().is_some() || has_any_deprecated_fields, ); + // 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 + // * we really want to make sure that the object is movable, therefore creating a move ctor + // -> this means that there's no implicit move assignment. + // Therefore, we have to define all five move/copy constructors/assignments. let hpp = quote! { #hpp_includes @@ -600,11 +733,22 @@ impl QuotedObject { #indicator_comment using IndicatorComponent = rerun::components::IndicatorComponent; + #NEWLINE_TOKEN + #name_doc_string + static constexpr const char ArchetypeName[] = #archetype_name; + + #NEWLINE_TOKEN + #(#descriptor_constants)* + #hpp_type_extensions public: #type_ident() = default; #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; + #NEWLINE_TOKEN #NEWLINE_TOKEN #(#methods_hpp)* @@ -687,7 +831,7 @@ impl QuotedObject { objects, &mut hpp_includes, obj_field, - &field_name_identifier(obj_field), + &field_name_ident(obj_field), ); quote! { #NEWLINE_TOKEN @@ -845,7 +989,7 @@ impl QuotedObject { } }) .chain(obj.fields.iter().map(|obj_field| { - let ident = field_name_identifier(obj_field); + let ident = field_name_ident(obj_field); quote! { #ident, } @@ -923,7 +1067,7 @@ impl QuotedObject { for obj_field in &obj.fields { let snake_case_name = obj_field.snake_case_name(); let field_name = format_ident!("{}", snake_case_name); - let tag_name = field_name_identifier(obj_field); + let tag_name = field_name_ident(obj_field); let method = if obj_field.typ == Type::Unit { let method_name = format_ident!("is_{}", snake_case_name); @@ -977,7 +1121,7 @@ impl QuotedObject { } }) .chain(obj.fields.iter().map(|obj_field| { - let tag_ident = field_name_identifier(obj_field); + let tag_ident = field_name_ident(obj_field); let field_ident = format_ident!("{}", obj_field.snake_case_name()); if obj_field.typ.has_default_destructor(objects) { @@ -1018,7 +1162,7 @@ impl QuotedObject { let mut placement_new_arms = Vec::new(); let mut trivial_memcpy_cases = Vec::new(); for obj_field in &obj.fields { - let tag_ident = field_name_identifier(obj_field); + let tag_ident = field_name_ident(obj_field); let case = quote!(case detail::#tag_typename::#tag_ident:); // Inferring from trivial destructability that we don't need to call the copy constructor is a little bit wonky, @@ -1257,7 +1401,7 @@ impl QuotedObject { .map(|obj_field| { let enum_value = obj_field.enum_value.unwrap(); let docstring = quote_field_docs(reporter, objects, obj_field); - let field_name = field_name_identifier(obj_field); + let field_name = field_name_ident(obj_field); // We assign the arrow type index to the enum fields to make encoding simpler and faster: let arrow_type_index = Literal::usize_unsuffixed(enum_value as _); @@ -1306,14 +1450,18 @@ impl QuotedObject { } } -fn field_name_identifier(obj_field: &ObjectField) -> Ident { +fn field_name(obj_field: &ObjectField) -> String { if let Some(name) = obj_field.try_get_attr::(ATTR_CPP_RENAME_FIELD) { - format_ident!("{}", name) + name } else { - format_ident!("{}", obj_field.name) + obj_field.name.clone() } } +fn field_name_ident(obj_field: &ObjectField) -> Ident { + format_ident!("{}", field_name(obj_field)) +} + fn single_field_constructor_methods( obj: &Object, hpp_includes: &mut Includes, @@ -1355,7 +1503,7 @@ fn add_copy_assignment_and_constructor( objects: &Objects, ) -> Vec { let mut methods = Vec::new(); - let field_ident = field_name_identifier(target_field); + let field_ident = field_name_ident(target_field); let param_ident = format_ident!("{}_", obj_field.name); // We keep parameter passing for assignment & ctors simple by _always_ passing by value. @@ -1607,39 +1755,45 @@ fn archetype_serialize(type_ident: &Ident, obj: &Object, hpp_includes: &mut Incl }; let archetype_name = &obj.fqname; + let eager_serialization = obj.is_attr_set(ATTR_CPP_ARCHETYPE_EAGER); let num_fields = quote_integer(obj.fields.len() + 1); // Plus one for the indicator. let push_batches = obj.fields.iter().map(|field| { - let field_name = field_name_identifier(field); - let field_fqname = &field.typ.fqname(); - let field_accessor = quote!(archetype.#field_name); - - let push_back = quote! { - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - }; + let archetype_field_name = field_name(field); + let field_name_ident = field_name_ident(field); - let archetype_field_name = field.snake_case_name(); - - // TODO(andreas): Introducing MonoCollection will remove the need for distinguishing these two cases. - if field.is_nullable && !obj.attrs.has(ATTR_RERUN_LOG_MISSING_AS_EMPTY) { + if eager_serialization { quote! { - if (#field_accessor.has_value()) { - auto result = ComponentBatch::from_loggable( - #field_accessor.value(), - ComponentDescriptor(#archetype_name, #archetype_field_name, #field_fqname) - ); - #push_back + if (archetype.#field_name_ident.has_value()) { + cells.push_back(archetype.#field_name_ident.value()); } } } else { - quote! { - { - auto result = ComponentBatch::from_loggable( - #field_accessor, - ComponentDescriptor(#archetype_name, #archetype_field_name, #field_fqname) - ); - #push_back + let field_fqname = &field.typ.fqname(); + let push_back = quote! { + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + }; + + if field.is_nullable && !obj.attrs.has(ATTR_RERUN_LOG_MISSING_AS_EMPTY) { + quote! { + if (archetype.#field_name_ident.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.#field_name_ident.value(), + ComponentDescriptor(#archetype_name, #archetype_field_name, #field_fqname) + ); + #push_back + } + } + } else { + quote! { + { + auto result = ComponentBatch::from_loggable( + archetype.#field_name_ident, + ComponentDescriptor(#archetype_name, #archetype_field_name, #field_fqname) + ); + #push_back + } } } } @@ -1901,7 +2055,7 @@ fn quote_append_field_to_builder( includes: &mut Includes, objects: &Objects, ) -> TokenStream { - let field_name = field_name_identifier(field); + let field_name = field_name_ident(field); if let Some(elem_type) = field.typ.plural_inner() { let value_builder = format_ident!("value_builder"); @@ -2205,16 +2359,16 @@ fn are_types_disjoint(fields: &[ObjectField]) -> bool { type_set.len() == fields.len() } -fn quote_archetype_field_type(hpp_includes: &mut Includes, obj_field: &ObjectField) -> TokenStream { +fn quote_archetype_unserialized_type( + hpp_includes: &mut Includes, + obj_field: &ObjectField, +) -> TokenStream { match &obj_field.typ { Type::Vector { elem_type } => { hpp_includes.insert_rerun("collection.hpp"); let elem_type = quote_element_type(hpp_includes, elem_type); quote! { Collection<#elem_type> } } - // TODO(andreas): This should emit `MonoCollection` which will be a constrained version of `Collection`. - // (Simply adapting `MonoCollection` breaks some existing code, so this not entirely trivial to do. - // Designing constraints for `MonoCollection` is harder still) Type::Object(fqname) => quote_fqname_as_type_path(hpp_includes, fqname), _ => panic!("Only vectors and objects are allowed in archetypes."), } @@ -2330,10 +2484,7 @@ fn quote_element_type(includes: &mut Includes, typ: &ElementType) -> TokenStream fn quote_fqname_as_type_path(includes: &mut Includes, fqname: &str) -> TokenStream { includes.insert_rerun_type(fqname); - let fqname = fqname - .replace(".testing", "") - .replace('.', "::") - .replace("crate", "rerun"); + let fqname = fqname.replace(".testing", "").replace('.', "::"); let expr: syn::TypePath = syn::parse_str(&fqname).unwrap(); quote!(#expr) @@ -2658,3 +2809,7 @@ fn quote_deprecation_ignore_start_and_end( (quote!(), quote!()) } } + +fn archetype_component_descriptor_constant_ident(obj_field: &ObjectField) -> Ident { + format_ident!("Descriptor_{}", obj_field.name) +} diff --git a/crates/build/re_types_builder/src/lib.rs b/crates/build/re_types_builder/src/lib.rs index 487963a74e43d..f80010185563a 100644 --- a/crates/build/re_types_builder/src/lib.rs +++ b/crates/build/re_types_builder/src/lib.rs @@ -194,6 +194,7 @@ pub const ATTR_RERUN_EXPERIMENTAL: &str = "attr.rerun.experimental"; pub const ATTR_PYTHON_ALIASES: &str = "attr.python.aliases"; pub const ATTR_PYTHON_ARRAY_ALIASES: &str = "attr.python.array_aliases"; +pub const ATTR_CPP_ARCHETYPE_EAGER: &str = "attr.cpp.archetype_eager"; pub const ATTR_CPP_NO_FIELD_CTORS: &str = "attr.cpp.no_field_ctors"; pub const ATTR_CPP_RENAME_FIELD: &str = "attr.cpp.rename_field"; diff --git a/crates/store/re_types/definitions/attributes/cpp.fbs b/crates/store/re_types/definitions/attributes/cpp.fbs index 1ebfa0821c817..fdc0a149bb2b9 100644 --- a/crates/store/re_types/definitions/attributes/cpp.fbs +++ b/crates/store/re_types/definitions/attributes/cpp.fbs @@ -6,3 +6,9 @@ attribute "attr.cpp.no_field_ctors"; /// Changes the name of a field in the generated C++ code. /// This can be used to avoid name clashes with C++ keywords or methods. attribute "attr.cpp.rename_field"; + +/// The generated C++ object should be eagerly serialized, i.e. only comprised of Arrow arrays. +/// +/// Applies only to archetypes. No-op otherwise. +// TODO(#7245): This should be always enabled. +attribute "attr.cpp.archetype_eager"; diff --git a/crates/store/re_types/definitions/attributes/rust.fbs b/crates/store/re_types/definitions/attributes/rust.fbs index 87d5904f3e816..c26f621822f88 100644 --- a/crates/store/re_types/definitions/attributes/rust.fbs +++ b/crates/store/re_types/definitions/attributes/rust.fbs @@ -53,4 +53,5 @@ attribute "attr.rust.archetype_native"; /// The generated Rust object should be eagerly serialized, i.e. only comprised of Arrow arrays. /// /// Applies only to archetypes. No-op otherwise. +// TODO(#7245): This should be always enabled. attribute "attr.rust.archetype_eager"; diff --git a/crates/store/re_types/definitions/rerun/archetypes/annotation_context.fbs b/crates/store/re_types/definitions/rerun/archetypes/annotation_context.fbs index bd7442723f313..14ef25c3108bd 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/annotation_context.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/annotation_context.fbs @@ -16,6 +16,7 @@ namespace rerun.archetypes; /// \example archetypes/annotation_context_connections !api title="Connections" image="https://static.rerun.io/annotation_context_connections/4a8422bc154699c5334f574ff01b55c5cd1748e3/1200w.png" table AnnotationContext ( // TODO(#7245): "attr.rust.archetype_eager", + "attr.cpp.archetype_eager", "attr.rust.derive": "Eq, PartialEq", "attr.docs.view_types": "Spatial2DView, Spatial3DView" ) { diff --git a/crates/store/re_types/definitions/rerun/archetypes/arrows2d.fbs b/crates/store/re_types/definitions/rerun/archetypes/arrows2d.fbs index 56854ae5b6a43..10a12c5140134 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/arrows2d.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/arrows2d.fbs @@ -8,6 +8,7 @@ namespace rerun.archetypes; /// \example archetypes/arrows2d_simple title="Simple batch of 2D arrows" image="https://static.rerun.io/arrow2d_simple/59f044ccc03f7bc66ee802288f75706618b29a6e/1200w.png" table Arrows2D ( "attr.rust.archetype_eager", + "attr.cpp.archetype_eager", "attr.rust.derive": "PartialEq", "attr.rust.new_pub_crate", "attr.cpp.no_field_ctors", diff --git a/crates/store/re_types/definitions/rerun/archetypes/arrows3d.fbs b/crates/store/re_types/definitions/rerun/archetypes/arrows3d.fbs index b07c94130e93f..89c4439b4eff1 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/arrows3d.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/arrows3d.fbs @@ -7,6 +7,7 @@ namespace rerun.archetypes; /// \example archetypes/arrows3d_simple title="Simple batch of 3D arrows" image="https://static.rerun.io/arrow3d_simple/55e2f794a520bbf7527d7b828b0264732146c5d0/1200w.png" table Arrows3D ( "attr.rust.archetype_eager", + "attr.cpp.archetype_eager", "attr.rust.derive": "PartialEq", "attr.rust.new_pub_crate", "attr.cpp.no_field_ctors", diff --git a/crates/store/re_types/definitions/rerun/archetypes/points3d.fbs b/crates/store/re_types/definitions/rerun/archetypes/points3d.fbs index 2bc5b5eb7a306..adff5311aa233 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/points3d.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/points3d.fbs @@ -9,7 +9,8 @@ namespace rerun.archetypes; /// \example archetypes/points3d_ui_radius title="Log points with radii given in UI points" image="https://static.rerun.io/point3d_ui_radius/e051a65b4317438bcaea8d0eee016ac9460b5336/1200w.png" /// \example archetypes/points3d_send_columns title="Send several point clouds with varying point count over time in a single call" image="https://static.rerun.io/points3d_send_columns/633b524a2ee439b0e3afc3f894f4927ce938a3ec/1200w.png" missing="rs" table Points3D ( - "attr.rust.archetype_eager": "", + "attr.rust.archetype_eager", + "attr.cpp.archetype_eager", "attr.rust.derive": "PartialEq", "attr.docs.category": "Spatial 3D", "attr.docs.view_types": "Spatial3DView, Spatial2DView: if logged above active projection" diff --git a/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs b/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs index 5aae1ce97c144..1fb9ca1deca11 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs @@ -18,6 +18,7 @@ namespace rerun.archetypes; /// \example archetypes/transform3d_hierarchy title="Transform hierarchy" image="https://static.rerun.io/transform_hierarchy/cb7be7a5a31fcb2efc02ba38e434849248f87554/1200w.png" table Transform3D ( "attr.rust.archetype_eager", + "attr.cpp.archetype_eager", "attr.docs.category": "Spatial 3D", "attr.docs.view_types": "Spatial3DView, Spatial2DView: if logged above active projection", "attr.rerun.log_missing_as_empty", // See https://github.com/rerun-io/rerun/issues/6909 diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/background.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/background.fbs index 5464e214ee4a7..1f875fa76eed3 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/background.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/background.fbs @@ -3,9 +3,10 @@ namespace rerun.blueprint.archetypes; /// Configuration for the background of a view. table Background ( + "attr.cpp.archetype_eager", + "attr.rust.archetype_eager", "attr.python.aliases": "datatypes.Rgba32Like, blueprint_components.BackgroundKindLike", - "attr.rerun.scope": "blueprint", - "attr.rust.archetype_eager" + "attr.rerun.scope": "blueprint" ) { // --- Required --- diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/container_blueprint.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/container_blueprint.fbs index 07232ba0b150c..de553139fdf4c 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/container_blueprint.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/container_blueprint.fbs @@ -5,6 +5,7 @@ namespace rerun.blueprint.archetypes; /// The description of a container. table ContainerBlueprint ( "attr.rerun.scope": "blueprint", + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rust.archetype_native" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/dataframe_query.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/dataframe_query.fbs index 03cd66ec9a492..a29d808f4d59c 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/dataframe_query.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/dataframe_query.fbs @@ -3,6 +3,7 @@ namespace rerun.blueprint.archetypes; /// The query for the dataframe view. table DataframeQuery ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs index a84cb467afa48..8cc391aae33f1 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Tries to move the center of mass of the graph to the origin. struct ForceCenter ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs index e234cd05b08a8..2f92134848c34 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Resolves collisions between the bounding circles, according to the radius of the nodes. struct ForceCollisionRadius ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs index addd9d3a26323..5386fe1af738e 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Aims to achieve a target distance between two nodes that are connected by an edge. struct ForceLink ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs index 3507c736c588e..17900436a6abf 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs @@ -4,6 +4,7 @@ namespace rerun.blueprint.archetypes; /// /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. struct ForceManyBody ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs index 2456ba44e5a7b..f0ab6fee08a21 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Similar to gravity, this force pulls nodes towards a specific position. struct ForcePosition ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/line_grid3d.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/line_grid3d.fbs index e974d87430b7d..2293aef8567f2 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/line_grid3d.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/line_grid3d.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Configuration for the 3D line grid. table LineGrid3D ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs index 0a2b93e965b82..56db05d7611e4 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs @@ -3,6 +3,7 @@ namespace rerun.blueprint.archetypes; /// Configuration for the background map of the map view. table MapBackground ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.python.aliases": "blueprint_components.MapProviderLike" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs index 40cba26edf839..21346016759e7 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs @@ -4,6 +4,7 @@ namespace rerun.blueprint.archetypes; /// Configuration of the map view zoom level. //TODO(ab): Turn this archetype into `MapArea` and include a `center: LatLon` componnent or similar table MapZoom ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.python.aliases": "datatypes.Float64Like" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs index 5e77fc9006d5a..2e9e08ca21a38 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Controls the distance to the near clip plane in 3D scene units. table NearClipPlane ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs index fe6ba781aebbc..c7fcffa60aefa 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs @@ -4,6 +4,7 @@ namespace rerun.blueprint.archetypes; /// Shared state for the 3 collapsible panels. table PanelBlueprint ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs index 30c60b3c07eeb..b01e9c6b8171f 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs @@ -5,6 +5,7 @@ namespace rerun.blueprint.archetypes; /// Configuration for the legend of a plot. table PlotLegend ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default", diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/scalar_axis.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/scalar_axis.fbs index d7a3657ed9c44..bf2ea9a3db94d 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/scalar_axis.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/scalar_axis.fbs @@ -5,6 +5,7 @@ namespace rerun.blueprint.archetypes; /// Configuration for the scalar axis of a plot. table ScalarAxis ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_scalar_mapping.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_scalar_mapping.fbs index 0195e2b9bc2c2..62d42b4a057dc 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_scalar_mapping.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_scalar_mapping.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Configures how tensor scalars are mapped to color. table TensorScalarMapping ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_slice_selection.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_slice_selection.fbs index 8619811df8465..4ed60996a74bb 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_slice_selection.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_slice_selection.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Specifies a 2D slice of a tensor. table TensorSliceSelection ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_view_fit.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_view_fit.fbs index ca2591d487a6a..f5d655f64ccac 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_view_fit.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/tensor_view_fit.fbs @@ -2,6 +2,7 @@ namespace rerun.blueprint.archetypes; /// Configures how a selected tensor slice is shown on screen. table TensorViewFit ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default", diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_blueprint.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_blueprint.fbs index 6eba591e3fc69..d77c38fa5b451 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_blueprint.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_blueprint.fbs @@ -4,6 +4,7 @@ namespace rerun.blueprint.archetypes; /// The description of a single view. table ViewBlueprint ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_contents.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_contents.fbs index 091bb68798b05..e95ea9b55d79f 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_contents.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/view_contents.fbs @@ -41,6 +41,7 @@ namespace rerun.blueprint.archetypes; /// The last rule matching `/world` is `- /world`, so it is excluded. /// The last rule matching `/world/house` is `+ /world/**`, so it is included. table ViewContents ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs index e8a1f97539067..ef9aada2f489d 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs @@ -4,6 +4,7 @@ namespace rerun.blueprint.archetypes; /// The top-level description of the viewport. table ViewportBlueprint ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/visible_time_ranges.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/visible_time_ranges.fbs index 3706c4b5d9fe4..fd0954c54c585 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/visible_time_ranges.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/visible_time_ranges.fbs @@ -12,6 +12,7 @@ namespace rerun.blueprint.archetypes; /// - For time series views, the default is to show the entire timeline. /// - For any other view, the default is to apply latest-at semantics. table VisibleTimeRanges ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default", diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/visual_bounds2d.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/visual_bounds2d.fbs index b9ba3e9e5d7bc..92ecd1650e87e 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/visual_bounds2d.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/visual_bounds2d.fbs @@ -8,6 +8,7 @@ namespace rerun.blueprint.archetypes; /// If no visual bounds are set, it will be determined automatically, /// based on the bounding-box of the data or other camera information present in the view. table VisualBounds2D ( + "attr.cpp.archetype_eager", "attr.rust.archetype_eager", "attr.rerun.scope": "blueprint" ) { diff --git a/docs/snippets/all/archetypes/points3d_partial_updates.cpp b/docs/snippets/all/archetypes/points3d_partial_updates.cpp index 7171ddb33e636..5f9879c5672da 100644 --- a/docs/snippets/all/archetypes/points3d_partial_updates.cpp +++ b/docs/snippets/all/archetypes/points3d_partial_updates.cpp @@ -37,26 +37,12 @@ int main() { } rec.set_time_sequence("frame", i); - rec.log("points", rerun::Points3D::IndicatorComponent(), colors, radii); - // TODO(cmc): implement new APIs and use them! - // rec.log("points", rerun::Points3D::update_fields().with_radii(radii).with_colors(colors)); + rec.log("points", rerun::Points3D::update_fields().with_radii(radii).with_colors(colors)); } 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() - ); - // TODO(cmc): implement new APIs and use them! - // rec.log("points", rerun::Points3D::clear_fields().with_radii(radii).with_colors(colors)); + rec.log("points", rerun::Points3D::clear_fields().with_positions(positions).with_radii(radii)); } diff --git a/docs/snippets/all/archetypes/transform3d_partial_updates.cpp b/docs/snippets/all/archetypes/transform3d_partial_updates.cpp index 384723c1cb3cb..44f2492b9e9f0 100644 --- a/docs/snippets/all/archetypes/transform3d_partial_updates.cpp +++ b/docs/snippets/all/archetypes/transform3d_partial_updates.cpp @@ -4,7 +4,7 @@ float truncated_radians(int deg) { auto degf = static_cast(deg); - const auto pi = 3.14159265358979323846; + const auto pi = 3.14159265358979323846f; return static_cast(static_cast(degf * pi / 180.0f * 1000.0f)) / 1000.0f; } @@ -22,36 +22,35 @@ int main() { // Update only the rotation of the box. for (int deg = 0; deg <= 45; deg++) { auto rad = truncated_radians(deg * 4); - // TODO(#8583): update_fields rec.log( "box", - rerun::Transform3D().with_rotation_axis_angle( + rerun::Transform3D::update_fields().with_rotation_axis_angle( rerun::RotationAxisAngle({0.0f, 1.0f, 0.0f}, rerun::Angle::radians(rad)) ) ); } // Update only the position of the box. - for (int t = 0; t <= 45; t++) { + for (int t = 0; t <= 50; t++) { rec.log( "box", - rerun::Transform3D().with_translation({0.0f, 0.0f, static_cast(t) / 10.0f}) + rerun::Transform3D::update_fields().with_translation( + {0.0f, 0.0f, static_cast(t) / 10.0f} + ) ); } // Update only the rotation of the box. for (int deg = 0; deg <= 45; deg++) { auto rad = truncated_radians((deg + 45) * 4); - // TODO(#8583): update_fields rec.log( "box", - rerun::Transform3D().with_rotation_axis_angle( + rerun::Transform3D::update_fields().with_rotation_axis_angle( rerun::RotationAxisAngle({0.0f, 1.0f, 0.0f}, rerun::Angle::radians(rad)) ) ); } // Clear all of the box's attributes, and reset its axis length. - // TODO(#8583): clear_fields - rec.log("box", rerun::Transform3D().with_axis_length(15.0)); + rec.log("box", rerun::Transform3D::clear_fields().with_axis_length(15.0)); } diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 4ed1ed51e0618..7658e9f8cef10 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -6,23 +6,16 @@ # These archetypes will ignore the associated snippets in the snippet index. [snippets_ref.archetypes.opt_out] -"DataframeQuery" = [ - "reference/dataframe_save_blueprint" -] +"DataframeQuery" = ["reference/dataframe_save_blueprint"] # These components will ignore the associated snippets in the snippet index. [snippets_ref.components.opt_out] -"ShowLabels" = [ - "tutorials/data_out", -] +"ShowLabels" = ["tutorials/data_out"] # These arbitrary feature names will be indexed exactly as written down. # Add anything you can think about! [snippets_ref.features] -"Dataframes" = [ - "reference/dataframe_query", - "reference/dataframe_view_query", -] +"Dataframes" = ["reference/dataframe_query", "reference/dataframe_view_query"] "`AnyValue`" = [ "tutorials/any_values", "tutorials/extra_values", @@ -271,9 +264,6 @@ quick_start = [ # These examples don't have exactly the same implementation. "archetypes/transform3d_hierarchy" = [ # Uses a lot of trigonometry which is surprisingly easy to get the same on Rust & C++, but not on Python/Numpy "py", ] -"archetypes/transform3d_partial_updates" = [ - "cpp", # TODO(#8583): remove once C++ partial updates APIs have shipped -] "archetypes/instance_poses3d_combined" = [ # TODO(#3235): Slight floating point differences in point grid. "cpp", "py", diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.cpp b/rerun_cpp/src/rerun/archetypes/annotation_context.cpp index 79b5004d00b84..2eedd044bdcae 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.cpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.cpp @@ -5,7 +5,15 @@ #include "../collection_adapter_builtins.hpp" -namespace rerun::archetypes {} +namespace rerun::archetypes { + AnnotationContext AnnotationContext::clear_fields() { + auto archetype = AnnotationContext(); + archetype.context = + ComponentBatch::empty(Descriptor_context) + .value_or_throw(); + return archetype; + } +} // namespace rerun::archetypes namespace rerun { @@ -16,17 +24,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.context, - ComponentDescriptor( - "rerun.archetypes.AnnotationContext", - "context", - "rerun.components.AnnotationContext" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.context.has_value()) { + cells.push_back(archetype.context.value()); } { auto indicator = AnnotationContext::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp index 48b9334b25d90..7918f8ea11b02 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp @@ -4,12 +4,14 @@ #pragma once #include "../collection.hpp" +#include "../compiler_utils.hpp" #include "../component_batch.hpp" #include "../components/annotation_context.hpp" #include "../indicator_component.hpp" #include "../result.hpp" #include +#include #include #include @@ -64,7 +66,7 @@ namespace rerun::archetypes { /// ``` struct AnnotationContext { /// List of class descriptions, mapping class indices to class names, colors etc. - rerun::components::AnnotationContext context; + std::optional context; public: static constexpr const char IndicatorComponentName[] = @@ -72,13 +74,40 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.AnnotationContext"; + + /// `ComponentDescriptor` for the `context` field. + static constexpr auto Descriptor_context = ComponentDescriptor( + ArchetypeName, "context", + Loggable::Descriptor.component_name + ); public: AnnotationContext() = default; AnnotationContext(AnnotationContext&& other) = default; + AnnotationContext(const AnnotationContext& other) = default; + AnnotationContext& operator=(const AnnotationContext& other) = default; + AnnotationContext& operator=(AnnotationContext&& other) = default; explicit AnnotationContext(rerun::components::AnnotationContext _context) - : context(std::move(_context)) {} + : context(ComponentBatch::from_loggable(std::move(_context), Descriptor_context) + .value_or_throw()) {} + + /// Update only some specific fields of a `AnnotationContext`. + static AnnotationContext update_fields() { + return AnnotationContext(); + } + + /// Clear all the fields of a `AnnotationContext`. + static AnnotationContext clear_fields(); + + /// List of class descriptions, mapping class indices to class names, colors etc. + AnnotationContext with_context(const rerun::components::AnnotationContext& _context) && { + context = ComponentBatch::from_loggable(_context, Descriptor_context).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.cpp b/rerun_cpp/src/rerun/archetypes/arrows2d.cpp index ee120118aabd6..bc6242122d37d 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.cpp @@ -5,7 +5,31 @@ #include "../collection_adapter_builtins.hpp" -namespace rerun::archetypes {} +namespace rerun::archetypes { + Arrows2D Arrows2D::clear_fields() { + auto archetype = Arrows2D(); + archetype.vectors = + ComponentBatch::empty(Descriptor_vectors).value_or_throw(); + archetype.origins = ComponentBatch::empty(Descriptor_origins) + .value_or_throw(); + archetype.radii = + ComponentBatch::empty(Descriptor_radii).value_or_throw(); + archetype.colors = + ComponentBatch::empty(Descriptor_colors).value_or_throw(); + archetype.labels = + ComponentBatch::empty(Descriptor_labels).value_or_throw(); + archetype.show_labels = + ComponentBatch::empty(Descriptor_show_labels) + .value_or_throw(); + archetype.draw_order = + ComponentBatch::empty(Descriptor_draw_order) + .value_or_throw(); + archetype.class_ids = + ComponentBatch::empty(Descriptor_class_ids) + .value_or_throw(); + return archetype; + } +} // namespace rerun::archetypes namespace rerun { @@ -16,89 +40,29 @@ namespace rerun { std::vector cells; cells.reserve(9); - { - auto result = ComponentBatch::from_loggable( - archetype.vectors, - ComponentDescriptor( - "rerun.archetypes.Arrows2D", - "vectors", - "rerun.components.Vector2D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.vectors.has_value()) { + cells.push_back(archetype.vectors.value()); } if (archetype.origins.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.origins.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows2D", - "origins", - "rerun.components.Position2D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.origins.value()); } if (archetype.radii.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.radii.value(), - ComponentDescriptor("rerun.archetypes.Arrows2D", "radii", "rerun.components.Radius") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.radii.value()); } if (archetype.colors.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.colors.value(), - ComponentDescriptor("rerun.archetypes.Arrows2D", "colors", "rerun.components.Color") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.colors.value()); } if (archetype.labels.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.labels.value(), - ComponentDescriptor("rerun.archetypes.Arrows2D", "labels", "rerun.components.Text") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.labels.value()); } if (archetype.show_labels.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.show_labels.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows2D", - "show_labels", - "rerun.components.ShowLabels" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.show_labels.value()); } if (archetype.draw_order.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.draw_order.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows2D", - "draw_order", - "rerun.components.DrawOrder" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.draw_order.value()); } if (archetype.class_ids.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.class_ids.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows2D", - "class_ids", - "rerun.components.ClassId" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.class_ids.value()); } { auto indicator = Arrows2D::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp index 63ae5c8a4ac4d..edef0d924bc45 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp @@ -49,53 +49,91 @@ namespace rerun::archetypes { /// ``` struct Arrows2D { /// All the vectors for each arrow in the batch. - Collection vectors; + std::optional vectors; /// 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. - std::optional> origins; + std::optional origins; /// 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`. - std::optional> radii; + std::optional radii; /// Optional colors for the points. - std::optional> colors; + std::optional colors; /// 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. - std::optional> labels; + std::optional labels; /// Optional choice of whether the text labels should be shown by default. - std::optional show_labels; + std::optional show_labels; /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. - std::optional draw_order; + std::optional draw_order; /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. - std::optional> class_ids; + std::optional class_ids; public: static constexpr const char IndicatorComponentName[] = "rerun.components.Arrows2DIndicator"; /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Arrows2D"; + + /// `ComponentDescriptor` for the `vectors` field. + static constexpr auto Descriptor_vectors = ComponentDescriptor( + ArchetypeName, "vectors", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `origins` field. + static constexpr auto Descriptor_origins = ComponentDescriptor( + ArchetypeName, "origins", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `radii` field. + static constexpr auto Descriptor_radii = ComponentDescriptor( + ArchetypeName, "radii", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `colors` field. + static constexpr auto Descriptor_colors = ComponentDescriptor( + ArchetypeName, "colors", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `labels` field. + static constexpr auto Descriptor_labels = ComponentDescriptor( + ArchetypeName, "labels", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `show_labels` field. + static constexpr auto Descriptor_show_labels = ComponentDescriptor( + ArchetypeName, "show_labels", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `draw_order` field. + static constexpr auto Descriptor_draw_order = ComponentDescriptor( + ArchetypeName, "draw_order", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `class_ids` field. + static constexpr auto Descriptor_class_ids = ComponentDescriptor( + ArchetypeName, "class_ids", + Loggable::Descriptor.component_name + ); public: // START of extensions from arrows2d_ext.cpp: /// Creates new 2D arrows pointing in the given directions, with a base at the origin (0, 0). static Arrows2D from_vectors(Collection vectors_) { - Arrows2D arrows; - arrows.vectors = std::move(vectors_); - return arrows; + return Arrows2D().with_vectors(vectors_); } // END of extensions from arrows2d_ext.cpp, start of generated code: @@ -103,12 +141,30 @@ namespace rerun::archetypes { public: Arrows2D() = default; Arrows2D(Arrows2D&& other) = default; + Arrows2D(const Arrows2D& other) = default; + Arrows2D& operator=(const Arrows2D& other) = default; + Arrows2D& operator=(Arrows2D&& other) = default; + + /// Update only some specific fields of a `Arrows2D`. + static Arrows2D update_fields() { + return Arrows2D(); + } + + /// Clear all the fields of a `Arrows2D`. + static Arrows2D clear_fields(); + + /// All the vectors for each arrow in the batch. + Arrows2D with_vectors(const Collection& _vectors) && { + vectors = ComponentBatch::from_loggable(_vectors, Descriptor_vectors).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// 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. - Arrows2D with_origins(Collection _origins) && { - origins = std::move(_origins); + Arrows2D with_origins(const Collection& _origins) && { + origins = ComponentBatch::from_loggable(_origins, Descriptor_origins).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -117,15 +173,15 @@ namespace rerun::archetypes { /// /// 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`. - Arrows2D with_radii(Collection _radii) && { - radii = std::move(_radii); + Arrows2D with_radii(const Collection& _radii) && { + radii = ComponentBatch::from_loggable(_radii, Descriptor_radii).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Optional colors for the points. - Arrows2D with_colors(Collection _colors) && { - colors = std::move(_colors); + Arrows2D with_colors(const Collection& _colors) && { + colors = ComponentBatch::from_loggable(_colors, Descriptor_colors).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -134,15 +190,16 @@ namespace rerun::archetypes { /// /// 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. - Arrows2D with_labels(Collection _labels) && { - labels = std::move(_labels); + Arrows2D with_labels(const Collection& _labels) && { + labels = ComponentBatch::from_loggable(_labels, Descriptor_labels).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Optional choice of whether the text labels should be shown by default. - Arrows2D with_show_labels(rerun::components::ShowLabels _show_labels) && { - show_labels = std::move(_show_labels); + Arrows2D with_show_labels(const rerun::components::ShowLabels& _show_labels) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -150,8 +207,9 @@ namespace rerun::archetypes { /// An optional floating point value that specifies the 2D drawing order. /// /// Objects with higher values are drawn on top of those with lower values. - Arrows2D with_draw_order(rerun::components::DrawOrder _draw_order) && { - draw_order = std::move(_draw_order); + Arrows2D with_draw_order(const rerun::components::DrawOrder& _draw_order) && { + draw_order = + ComponentBatch::from_loggable(_draw_order, Descriptor_draw_order).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -159,8 +217,9 @@ namespace rerun::archetypes { /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. - Arrows2D with_class_ids(Collection _class_ids) && { - class_ids = std::move(_class_ids); + Arrows2D with_class_ids(const Collection& _class_ids) && { + class_ids = + ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d_ext.cpp b/rerun_cpp/src/rerun/archetypes/arrows2d_ext.cpp index 9677fd7ece95a..6f9c97def1f79 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d_ext.cpp @@ -10,9 +10,7 @@ namespace rerun { /// Creates new 2D arrows pointing in the given directions, with a base at the origin (0, 0). static Arrows2D from_vectors(Collection vectors_) { - Arrows2D arrows; - arrows.vectors = std::move(vectors_); - return arrows; + return Arrows2D().with_vectors(vectors_); } // diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.cpp b/rerun_cpp/src/rerun/archetypes/arrows3d.cpp index 613974c52858d..dbf8999cef1d1 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.cpp @@ -5,7 +5,28 @@ #include "../collection_adapter_builtins.hpp" -namespace rerun::archetypes {} +namespace rerun::archetypes { + Arrows3D Arrows3D::clear_fields() { + auto archetype = Arrows3D(); + archetype.vectors = + ComponentBatch::empty(Descriptor_vectors).value_or_throw(); + archetype.origins = ComponentBatch::empty(Descriptor_origins) + .value_or_throw(); + archetype.radii = + ComponentBatch::empty(Descriptor_radii).value_or_throw(); + archetype.colors = + ComponentBatch::empty(Descriptor_colors).value_or_throw(); + archetype.labels = + ComponentBatch::empty(Descriptor_labels).value_or_throw(); + archetype.show_labels = + ComponentBatch::empty(Descriptor_show_labels) + .value_or_throw(); + archetype.class_ids = + ComponentBatch::empty(Descriptor_class_ids) + .value_or_throw(); + return archetype; + } +} // namespace rerun::archetypes namespace rerun { @@ -16,77 +37,26 @@ namespace rerun { std::vector cells; cells.reserve(8); - { - auto result = ComponentBatch::from_loggable( - archetype.vectors, - ComponentDescriptor( - "rerun.archetypes.Arrows3D", - "vectors", - "rerun.components.Vector3D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.vectors.has_value()) { + cells.push_back(archetype.vectors.value()); } if (archetype.origins.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.origins.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows3D", - "origins", - "rerun.components.Position3D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.origins.value()); } if (archetype.radii.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.radii.value(), - ComponentDescriptor("rerun.archetypes.Arrows3D", "radii", "rerun.components.Radius") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.radii.value()); } if (archetype.colors.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.colors.value(), - ComponentDescriptor("rerun.archetypes.Arrows3D", "colors", "rerun.components.Color") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.colors.value()); } if (archetype.labels.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.labels.value(), - ComponentDescriptor("rerun.archetypes.Arrows3D", "labels", "rerun.components.Text") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.labels.value()); } if (archetype.show_labels.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.show_labels.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows3D", - "show_labels", - "rerun.components.ShowLabels" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.show_labels.value()); } if (archetype.class_ids.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.class_ids.value(), - ComponentDescriptor( - "rerun.archetypes.Arrows3D", - "class_ids", - "rerun.components.ClassId" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.class_ids.value()); } { auto indicator = Arrows3D::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp index 9229b82336260..ee3cb51172d21 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp @@ -64,49 +64,82 @@ namespace rerun::archetypes { /// ``` struct Arrows3D { /// All the vectors for each arrow in the batch. - Collection vectors; + std::optional vectors; /// 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. - std::optional> origins; + std::optional origins; /// 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`. - std::optional> radii; + std::optional radii; /// Optional colors for the points. - std::optional> colors; + std::optional colors; /// 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. - std::optional> labels; + std::optional labels; /// Optional choice of whether the text labels should be shown by default. - std::optional show_labels; + std::optional show_labels; /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. - std::optional> class_ids; + std::optional class_ids; public: static constexpr const char IndicatorComponentName[] = "rerun.components.Arrows3DIndicator"; /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Arrows3D"; + + /// `ComponentDescriptor` for the `vectors` field. + static constexpr auto Descriptor_vectors = ComponentDescriptor( + ArchetypeName, "vectors", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `origins` field. + static constexpr auto Descriptor_origins = ComponentDescriptor( + ArchetypeName, "origins", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `radii` field. + static constexpr auto Descriptor_radii = ComponentDescriptor( + ArchetypeName, "radii", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `colors` field. + static constexpr auto Descriptor_colors = ComponentDescriptor( + ArchetypeName, "colors", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `labels` field. + static constexpr auto Descriptor_labels = ComponentDescriptor( + ArchetypeName, "labels", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `show_labels` field. + static constexpr auto Descriptor_show_labels = ComponentDescriptor( + ArchetypeName, "show_labels", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `class_ids` field. + static constexpr auto Descriptor_class_ids = ComponentDescriptor( + ArchetypeName, "class_ids", + Loggable::Descriptor.component_name + ); public: // START of extensions from arrows3d_ext.cpp: /// Creates new 3D arrows pointing in the given directions, with a base at the origin (0, 0, /// 0). static Arrows3D from_vectors(Collection vectors_) { - Arrows3D arrows; - arrows.vectors = std::move(vectors_); - return arrows; + return Arrows3D().with_vectors(vectors_); } // END of extensions from arrows3d_ext.cpp, start of generated code: @@ -114,12 +147,30 @@ namespace rerun::archetypes { public: Arrows3D() = default; Arrows3D(Arrows3D&& other) = default; + Arrows3D(const Arrows3D& other) = default; + Arrows3D& operator=(const Arrows3D& other) = default; + Arrows3D& operator=(Arrows3D&& other) = default; + + /// Update only some specific fields of a `Arrows3D`. + static Arrows3D update_fields() { + return Arrows3D(); + } + + /// Clear all the fields of a `Arrows3D`. + static Arrows3D clear_fields(); + + /// All the vectors for each arrow in the batch. + Arrows3D with_vectors(const Collection& _vectors) && { + vectors = ComponentBatch::from_loggable(_vectors, Descriptor_vectors).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// 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. - Arrows3D with_origins(Collection _origins) && { - origins = std::move(_origins); + Arrows3D with_origins(const Collection& _origins) && { + origins = ComponentBatch::from_loggable(_origins, Descriptor_origins).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -128,15 +179,15 @@ namespace rerun::archetypes { /// /// 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`. - Arrows3D with_radii(Collection _radii) && { - radii = std::move(_radii); + Arrows3D with_radii(const Collection& _radii) && { + radii = ComponentBatch::from_loggable(_radii, Descriptor_radii).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Optional colors for the points. - Arrows3D with_colors(Collection _colors) && { - colors = std::move(_colors); + Arrows3D with_colors(const Collection& _colors) && { + colors = ComponentBatch::from_loggable(_colors, Descriptor_colors).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -145,15 +196,16 @@ namespace rerun::archetypes { /// /// 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. - Arrows3D with_labels(Collection _labels) && { - labels = std::move(_labels); + Arrows3D with_labels(const Collection& _labels) && { + labels = ComponentBatch::from_loggable(_labels, Descriptor_labels).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Optional choice of whether the text labels should be shown by default. - Arrows3D with_show_labels(rerun::components::ShowLabels _show_labels) && { - show_labels = std::move(_show_labels); + Arrows3D with_show_labels(const rerun::components::ShowLabels& _show_labels) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -161,8 +213,9 @@ namespace rerun::archetypes { /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. - Arrows3D with_class_ids(Collection _class_ids) && { - class_ids = std::move(_class_ids); + Arrows3D with_class_ids(const Collection& _class_ids) && { + class_ids = + ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d_ext.cpp b/rerun_cpp/src/rerun/archetypes/arrows3d_ext.cpp index 9a8e03c407b50..62659b744a23f 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d_ext.cpp @@ -11,9 +11,7 @@ namespace rerun { /// Creates new 3D arrows pointing in the given directions, with a base at the origin (0, 0, /// 0). static Arrows3D from_vectors(Collection vectors_) { - Arrows3D arrows; - arrows.vectors = std::move(vectors_); - return arrows; + return Arrows3D().with_vectors(vectors_); } // diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.hpp b/rerun_cpp/src/rerun/archetypes/asset3d.hpp index 05ee83b58192f..ee6d8369d5616 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.hpp @@ -78,6 +78,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Asset3D"; public: // START of extensions from asset3d_ext.cpp: /// Creates a new `Asset3D` from the file contents at `path`. @@ -107,6 +109,9 @@ namespace rerun::archetypes { public: Asset3D() = default; Asset3D(Asset3D&& other) = default; + Asset3D(const Asset3D& other) = default; + Asset3D& operator=(const Asset3D& other) = default; + Asset3D& operator=(Asset3D&& other) = default; explicit Asset3D(rerun::components::Blob _blob) : blob(std::move(_blob)) {} diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.hpp b/rerun_cpp/src/rerun/archetypes/asset_video.hpp index 261dbc09aac08..cc812d7d38995 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.hpp @@ -134,6 +134,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.AssetVideo"; public: // START of extensions from asset_video_ext.cpp: /// Creates a new `AssetVideo` from the file contents at `path`. @@ -168,6 +170,9 @@ namespace rerun::archetypes { public: AssetVideo() = default; AssetVideo(AssetVideo&& other) = default; + AssetVideo(const AssetVideo& other) = default; + AssetVideo& operator=(const AssetVideo& other) = default; + AssetVideo& operator=(AssetVideo&& other) = default; explicit AssetVideo(rerun::components::Blob _blob) : blob(std::move(_blob)) {} diff --git a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp index 31acb39e3c725..4266c0ae83951 100644 --- a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp +++ b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp @@ -48,6 +48,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.BarChart"; public: // START of extensions from bar_chart_ext.cpp: BarChart(rerun::datatypes::TensorBuffer buffer) { @@ -165,6 +167,9 @@ namespace rerun::archetypes { public: BarChart() = default; BarChart(BarChart&& other) = default; + BarChart(const BarChart& other) = default; + BarChart& operator=(const BarChart& other) = default; + BarChart& operator=(BarChart&& other) = default; explicit BarChart(rerun::components::TensorData _values) : values(std::move(_values)) {} diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp index 34dd7a37f1627..aeed404a2ea8c 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp @@ -79,6 +79,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Boxes2D"; public: // START of extensions from boxes2d_ext.cpp: /// Creates new `Boxes2D` with `half_sizes` centered around the local origin. @@ -132,6 +134,9 @@ namespace rerun::archetypes { public: Boxes2D() = default; Boxes2D(Boxes2D&& other) = default; + Boxes2D(const Boxes2D& other) = default; + Boxes2D& operator=(const Boxes2D& other) = default; + Boxes2D& operator=(Boxes2D&& other) = default; /// Optional center positions of the boxes. Boxes2D with_centers(Collection _centers) && { diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp index 18ba6d1bea736..4801504150d9c 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp @@ -115,6 +115,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Boxes3D"; public: // START of extensions from boxes3d_ext.cpp: /// Creates new `Boxes3D` with `half_sizes` centered around the local origin. @@ -172,6 +174,9 @@ namespace rerun::archetypes { public: Boxes3D() = default; Boxes3D(Boxes3D&& other) = default; + Boxes3D(const Boxes3D& other) = default; + Boxes3D& operator=(const Boxes3D& other) = default; + Boxes3D& operator=(Boxes3D&& other) = default; /// Optional center positions of the boxes. /// diff --git a/rerun_cpp/src/rerun/archetypes/capsules3d.hpp b/rerun_cpp/src/rerun/archetypes/capsules3d.hpp index 1b8ecf3a86c05..a60660ace1040 100644 --- a/rerun_cpp/src/rerun/archetypes/capsules3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/capsules3d.hpp @@ -118,6 +118,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Capsules3D"; public: // START of extensions from capsules3d_ext.cpp: /// Creates a new `Capsules3D` with the given axis-aligned lengths and radii. @@ -150,6 +152,9 @@ namespace rerun::archetypes { public: Capsules3D() = default; Capsules3D(Capsules3D&& other) = default; + Capsules3D(const Capsules3D& other) = default; + Capsules3D& operator=(const Capsules3D& other) = default; + Capsules3D& operator=(Capsules3D&& other) = default; /// Optional translations of the capsules. /// diff --git a/rerun_cpp/src/rerun/archetypes/clear.hpp b/rerun_cpp/src/rerun/archetypes/clear.hpp index a1ab55645feec..4f4a12a022aa9 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.hpp +++ b/rerun_cpp/src/rerun/archetypes/clear.hpp @@ -89,6 +89,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Clear"; public: // START of extensions from clear_ext.cpp: RERUN_SDK_EXPORT static const Clear FLAT; @@ -102,6 +104,9 @@ namespace rerun::archetypes { public: Clear() = default; Clear(Clear&& other) = default; + Clear(const Clear& other) = default; + Clear& operator=(const Clear& other) = default; + Clear& operator=(Clear&& other) = default; explicit Clear(rerun::components::ClearIsRecursive _is_recursive) : is_recursive(std::move(_is_recursive)) {} diff --git a/rerun_cpp/src/rerun/archetypes/depth_image.hpp b/rerun_cpp/src/rerun/archetypes/depth_image.hpp index 66775eb9b8abc..6c1f60701e2f9 100644 --- a/rerun_cpp/src/rerun/archetypes/depth_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/depth_image.hpp @@ -128,6 +128,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.DepthImage"; public: // START of extensions from depth_image_ext.cpp: /// Constructs image from pointer + resolution, inferring the datatype from the pointer type. @@ -192,6 +194,9 @@ namespace rerun::archetypes { public: DepthImage() = default; DepthImage(DepthImage&& other) = default; + DepthImage(const DepthImage& other) = default; + DepthImage& operator=(const DepthImage& other) = default; + DepthImage& operator=(DepthImage&& other) = default; /// An optional floating point value that specifies how long a meter is in the native depth units. /// diff --git a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp index b84f7c317287e..3460a14dad739 100644 --- a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp @@ -139,6 +139,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Ellipsoids3D"; public: // START of extensions from ellipsoids3d_ext.cpp: /// Creates new `Ellipsoids3D` that are spheres, with `half_sizes` created from radii. @@ -177,6 +179,9 @@ namespace rerun::archetypes { public: Ellipsoids3D() = default; Ellipsoids3D(Ellipsoids3D&& other) = default; + Ellipsoids3D(const Ellipsoids3D& other) = default; + Ellipsoids3D& operator=(const Ellipsoids3D& other) = default; + Ellipsoids3D& operator=(Ellipsoids3D&& other) = default; /// Optional center positions of the ellipsoids. /// diff --git a/rerun_cpp/src/rerun/archetypes/encoded_image.hpp b/rerun_cpp/src/rerun/archetypes/encoded_image.hpp index 3b13684c4ddbc..602855d823c26 100644 --- a/rerun_cpp/src/rerun/archetypes/encoded_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/encoded_image.hpp @@ -77,6 +77,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.EncodedImage"; public: // START of extensions from encoded_image_ext.cpp: /// Create a new `EncodedImage` from the contents of a file on disk, e.g. a PNG or JPEG. @@ -101,6 +103,9 @@ namespace rerun::archetypes { public: EncodedImage() = default; EncodedImage(EncodedImage&& other) = default; + EncodedImage(const EncodedImage& other) = default; + EncodedImage& operator=(const EncodedImage& other) = default; + EncodedImage& operator=(EncodedImage&& other) = default; /// The Media Type of the asset. /// diff --git a/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp b/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp index 58fe88698d27b..3150f8ae9e21e 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp +++ b/rerun_cpp/src/rerun/archetypes/geo_line_strings.hpp @@ -69,10 +69,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.GeoLineStrings"; public: GeoLineStrings() = default; GeoLineStrings(GeoLineStrings&& other) = default; + GeoLineStrings(const GeoLineStrings& other) = default; + GeoLineStrings& operator=(const GeoLineStrings& other) = default; + GeoLineStrings& operator=(GeoLineStrings&& other) = default; explicit GeoLineStrings(Collection _line_strings) : line_strings(std::move(_line_strings)) {} diff --git a/rerun_cpp/src/rerun/archetypes/geo_points.hpp b/rerun_cpp/src/rerun/archetypes/geo_points.hpp index deb65bd6028be..b999665bf4e4a 100644 --- a/rerun_cpp/src/rerun/archetypes/geo_points.hpp +++ b/rerun_cpp/src/rerun/archetypes/geo_points.hpp @@ -64,6 +64,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.GeoPoints"; public: // START of extensions from geo_points_ext.cpp: /// Creates a new GeoPoints object based on [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees). @@ -78,6 +80,9 @@ namespace rerun::archetypes { public: GeoPoints() = default; GeoPoints(GeoPoints&& other) = default; + GeoPoints(const GeoPoints& other) = default; + GeoPoints& operator=(const GeoPoints& other) = default; + GeoPoints& operator=(GeoPoints&& other) = default; explicit GeoPoints(Collection _positions) : positions(std::move(_positions)) {} diff --git a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp index 7ae79b0a58b67..1f87a1886b6d8 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp @@ -59,10 +59,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.GraphEdges"; public: GraphEdges() = default; GraphEdges(GraphEdges&& other) = default; + GraphEdges(const GraphEdges& other) = default; + GraphEdges& operator=(const GraphEdges& other) = default; + GraphEdges& operator=(GraphEdges&& other) = default; explicit GraphEdges(Collection _edges) : edges(std::move(_edges)) {} diff --git a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp index 6017a265a565a..862414e3c271a 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp @@ -71,10 +71,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.GraphNodes"; public: GraphNodes() = default; GraphNodes(GraphNodes&& other) = default; + GraphNodes(const GraphNodes& other) = default; + GraphNodes& operator=(const GraphNodes& other) = default; + GraphNodes& operator=(GraphNodes&& other) = default; explicit GraphNodes(Collection _node_ids) : node_ids(std::move(_node_ids)) {} diff --git a/rerun_cpp/src/rerun/archetypes/image.hpp b/rerun_cpp/src/rerun/archetypes/image.hpp index 80d28380825bb..863b1a8e94c7c 100644 --- a/rerun_cpp/src/rerun/archetypes/image.hpp +++ b/rerun_cpp/src/rerun/archetypes/image.hpp @@ -163,6 +163,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Image"; public: // START of extensions from image_ext.cpp: /// Construct an image from bytes and image format. @@ -298,6 +300,9 @@ namespace rerun::archetypes { public: Image() = default; Image(Image&& other) = default; + Image(const Image& other) = default; + Image& operator=(const Image& other) = default; + Image& operator=(Image&& other) = default; /// Opacity of the image, useful for layering several images. /// diff --git a/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp b/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp index f85c85c565f31..8ea4c3eca2b6c 100644 --- a/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/instance_poses3d.hpp @@ -98,10 +98,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.InstancePoses3D"; public: InstancePoses3D() = default; InstancePoses3D(InstancePoses3D&& other) = default; + InstancePoses3D(const InstancePoses3D& other) = default; + InstancePoses3D& operator=(const InstancePoses3D& other) = default; + InstancePoses3D& operator=(InstancePoses3D&& other) = default; /// Translation vectors. InstancePoses3D with_translations( diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp index 1af265add4c7c..23c629c784e8c 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp @@ -121,10 +121,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.LineStrips2D"; public: LineStrips2D() = default; LineStrips2D(LineStrips2D&& other) = default; + LineStrips2D(const LineStrips2D& other) = default; + LineStrips2D& operator=(const LineStrips2D& other) = default; + LineStrips2D& operator=(LineStrips2D&& other) = default; explicit LineStrips2D(Collection _strips) : strips(std::move(_strips)) {} diff --git a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp index 63c310bf111d7..b21aef2368b0d 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp @@ -130,10 +130,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.LineStrips3D"; public: LineStrips3D() = default; LineStrips3D(LineStrips3D&& other) = default; + LineStrips3D(const LineStrips3D& other) = default; + LineStrips3D& operator=(const LineStrips3D& other) = default; + LineStrips3D& operator=(LineStrips3D&& other) = default; explicit LineStrips3D(Collection _strips) : strips(std::move(_strips)) {} diff --git a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp index e06f251216a90..653ddb99ffb10 100644 --- a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp @@ -149,10 +149,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Mesh3D"; public: Mesh3D() = default; Mesh3D(Mesh3D&& other) = default; + Mesh3D(const Mesh3D& other) = default; + Mesh3D& operator=(const Mesh3D& other) = default; + Mesh3D& operator=(Mesh3D&& other) = default; explicit Mesh3D(Collection _vertex_positions) : vertex_positions(std::move(_vertex_positions)) {} diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.hpp b/rerun_cpp/src/rerun/archetypes/pinhole.hpp index 61da282b23c3b..a2b94e070a70f 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.hpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.hpp @@ -129,6 +129,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Pinhole"; public: // START of extensions from pinhole_ext.cpp: /// Creates a pinhole from the camera focal length and resolution, both specified in pixels. @@ -188,6 +190,9 @@ namespace rerun::archetypes { public: Pinhole() = default; Pinhole(Pinhole&& other) = default; + Pinhole(const Pinhole& other) = default; + Pinhole& operator=(const Pinhole& other) = default; + Pinhole& operator=(Pinhole&& other) = default; explicit Pinhole(rerun::components::PinholeProjection _image_from_camera) : image_from_camera(std::move(_image_from_camera)) {} diff --git a/rerun_cpp/src/rerun/archetypes/points2d.hpp b/rerun_cpp/src/rerun/archetypes/points2d.hpp index eae8d28b96d14..91816f11c7ce7 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.hpp @@ -148,10 +148,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Points2D"; public: Points2D() = default; Points2D(Points2D&& other) = default; + Points2D(const Points2D& other) = default; + Points2D& operator=(const Points2D& other) = default; + Points2D& operator=(Points2D&& other) = default; explicit Points2D(Collection _positions) : positions(std::move(_positions)) {} diff --git a/rerun_cpp/src/rerun/archetypes/points3d.cpp b/rerun_cpp/src/rerun/archetypes/points3d.cpp index 45992227d6b77..ff12f08d9ccfa 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.cpp @@ -5,7 +5,30 @@ #include "../collection_adapter_builtins.hpp" -namespace rerun::archetypes {} +namespace rerun::archetypes { + Points3D Points3D::clear_fields() { + auto archetype = Points3D(); + archetype.positions = + ComponentBatch::empty(Descriptor_positions) + .value_or_throw(); + archetype.radii = + ComponentBatch::empty(Descriptor_radii).value_or_throw(); + archetype.colors = + ComponentBatch::empty(Descriptor_colors).value_or_throw(); + archetype.labels = + ComponentBatch::empty(Descriptor_labels).value_or_throw(); + archetype.show_labels = + ComponentBatch::empty(Descriptor_show_labels) + .value_or_throw(); + archetype.class_ids = + ComponentBatch::empty(Descriptor_class_ids) + .value_or_throw(); + archetype.keypoint_ids = + ComponentBatch::empty(Descriptor_keypoint_ids) + .value_or_throw(); + return archetype; + } +} // namespace rerun::archetypes namespace rerun { @@ -16,77 +39,26 @@ namespace rerun { std::vector cells; cells.reserve(8); - { - auto result = ComponentBatch::from_loggable( - archetype.positions, - ComponentDescriptor( - "rerun.archetypes.Points3D", - "positions", - "rerun.components.Position3D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.positions.has_value()) { + cells.push_back(archetype.positions.value()); } if (archetype.radii.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.radii.value(), - ComponentDescriptor("rerun.archetypes.Points3D", "radii", "rerun.components.Radius") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.radii.value()); } if (archetype.colors.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.colors.value(), - ComponentDescriptor("rerun.archetypes.Points3D", "colors", "rerun.components.Color") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.colors.value()); } if (archetype.labels.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.labels.value(), - ComponentDescriptor("rerun.archetypes.Points3D", "labels", "rerun.components.Text") - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.labels.value()); } if (archetype.show_labels.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.show_labels.value(), - ComponentDescriptor( - "rerun.archetypes.Points3D", - "show_labels", - "rerun.components.ShowLabels" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.show_labels.value()); } if (archetype.class_ids.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.class_ids.value(), - ComponentDescriptor( - "rerun.archetypes.Points3D", - "class_ids", - "rerun.components.ClassId" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.class_ids.value()); } if (archetype.keypoint_ids.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.keypoint_ids.value(), - ComponentDescriptor( - "rerun.archetypes.Points3D", - "keypoint_ids", - "rerun.components.KeypointId" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.keypoint_ids.value()); } { auto indicator = Points3D::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/archetypes/points3d.hpp b/rerun_cpp/src/rerun/archetypes/points3d.hpp index 69be252a65bb9..3a844f848e4fc 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.hpp @@ -161,27 +161,27 @@ namespace rerun::archetypes { /// ``` struct Points3D { /// All the 3D positions at which the point cloud shows points. - Collection positions; + std::optional positions; /// Optional radii for the points, effectively turning them into circles. - std::optional> radii; + std::optional radii; /// Optional colors for the points. - std::optional> colors; + std::optional colors; /// 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. - std::optional> labels; + std::optional labels; /// Optional choice of whether the text labels should be shown by default. - std::optional show_labels; + std::optional show_labels; /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. - std::optional> class_ids; + std::optional class_ids; /// Optional keypoint IDs for the points, identifying them within a class. /// @@ -191,31 +191,86 @@ namespace rerun::archetypes { /// with `class_id`). /// E.g. the classification might be 'Person' and the keypoints refer to joints on a /// detected skeleton. - std::optional> keypoint_ids; + std::optional keypoint_ids; public: static constexpr const char IndicatorComponentName[] = "rerun.components.Points3DIndicator"; /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Points3D"; + + /// `ComponentDescriptor` for the `positions` field. + static constexpr auto Descriptor_positions = ComponentDescriptor( + ArchetypeName, "positions", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `radii` field. + static constexpr auto Descriptor_radii = ComponentDescriptor( + ArchetypeName, "radii", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `colors` field. + static constexpr auto Descriptor_colors = ComponentDescriptor( + ArchetypeName, "colors", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `labels` field. + static constexpr auto Descriptor_labels = ComponentDescriptor( + ArchetypeName, "labels", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `show_labels` field. + static constexpr auto Descriptor_show_labels = ComponentDescriptor( + ArchetypeName, "show_labels", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `class_ids` field. + static constexpr auto Descriptor_class_ids = ComponentDescriptor( + ArchetypeName, "class_ids", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `keypoint_ids` field. + static constexpr auto Descriptor_keypoint_ids = ComponentDescriptor( + ArchetypeName, "keypoint_ids", + Loggable::Descriptor.component_name + ); public: Points3D() = default; Points3D(Points3D&& other) = default; + Points3D(const Points3D& other) = default; + Points3D& operator=(const Points3D& other) = default; + Points3D& operator=(Points3D&& other) = default; explicit Points3D(Collection _positions) - : positions(std::move(_positions)) {} + : positions(ComponentBatch::from_loggable(std::move(_positions), Descriptor_positions) + .value_or_throw()) {} + + /// Update only some specific fields of a `Points3D`. + static Points3D update_fields() { + return Points3D(); + } + + /// Clear all the fields of a `Points3D`. + static Points3D clear_fields(); + + /// All the 3D positions at which the point cloud shows points. + Points3D with_positions(const Collection& _positions) && { + positions = + ComponentBatch::from_loggable(_positions, Descriptor_positions).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// Optional radii for the points, effectively turning them into circles. - Points3D with_radii(Collection _radii) && { - radii = std::move(_radii); + Points3D with_radii(const Collection& _radii) && { + radii = ComponentBatch::from_loggable(_radii, Descriptor_radii).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Optional colors for the points. - Points3D with_colors(Collection _colors) && { - colors = std::move(_colors); + Points3D with_colors(const Collection& _colors) && { + colors = ComponentBatch::from_loggable(_colors, Descriptor_colors).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -224,15 +279,16 @@ namespace rerun::archetypes { /// /// 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. - Points3D with_labels(Collection _labels) && { - labels = std::move(_labels); + Points3D with_labels(const Collection& _labels) && { + labels = ComponentBatch::from_loggable(_labels, Descriptor_labels).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Optional choice of whether the text labels should be shown by default. - Points3D with_show_labels(rerun::components::ShowLabels _show_labels) && { - show_labels = std::move(_show_labels); + Points3D with_show_labels(const rerun::components::ShowLabels& _show_labels) && { + show_labels = ComponentBatch::from_loggable(_show_labels, Descriptor_show_labels) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -240,8 +296,9 @@ namespace rerun::archetypes { /// Optional class Ids for the points. /// /// The `components::ClassId` provides colors and labels if not specified explicitly. - Points3D with_class_ids(Collection _class_ids) && { - class_ids = std::move(_class_ids); + Points3D with_class_ids(const Collection& _class_ids) && { + class_ids = + ComponentBatch::from_loggable(_class_ids, Descriptor_class_ids).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -254,8 +311,10 @@ namespace rerun::archetypes { /// with `class_id`). /// E.g. the classification might be 'Person' and the keypoints refer to joints on a /// detected skeleton. - Points3D with_keypoint_ids(Collection _keypoint_ids) && { - keypoint_ids = std::move(_keypoint_ids); + Points3D with_keypoint_ids(const Collection& _keypoint_ids + ) && { + keypoint_ids = ComponentBatch::from_loggable(_keypoint_ids, Descriptor_keypoint_ids) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/archetypes/scalar.hpp b/rerun_cpp/src/rerun/archetypes/scalar.hpp index 874df670b920a..0007155f18637 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.hpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.hpp @@ -54,10 +54,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Scalar"; public: Scalar() = default; Scalar(Scalar&& other) = default; + Scalar(const Scalar& other) = default; + Scalar& operator=(const Scalar& other) = default; + Scalar& operator=(Scalar&& other) = default; explicit Scalar(rerun::components::Scalar _scalar) : scalar(std::move(_scalar)) {} }; diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp index 293fe0b954203..906e6a8631571 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp @@ -94,6 +94,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.SegmentationImage"; public: // START of extensions from segmentation_image_ext.cpp: /// Constructs image from pointer + resolution, inferring the datatype from the pointer type. @@ -161,6 +163,9 @@ namespace rerun::archetypes { public: SegmentationImage() = default; SegmentationImage(SegmentationImage&& other) = default; + SegmentationImage(const SegmentationImage& other) = default; + SegmentationImage& operator=(const SegmentationImage& other) = default; + SegmentationImage& operator=(SegmentationImage&& other) = default; /// Opacity of the image, useful for layering the segmentation image on top of another image. /// diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index 6eef6a6bfb6fd..8a49c6e070ca3 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -87,10 +87,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.SeriesLine"; public: SeriesLine() = default; SeriesLine(SeriesLine&& other) = default; + SeriesLine(const SeriesLine& other) = default; + SeriesLine& operator=(const SeriesLine& other) = default; + SeriesLine& operator=(SeriesLine&& other) = default; /// Color for the corresponding series. SeriesLine with_color(rerun::components::Color _color) && { diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index bf169c03aec06..23023ca1fbee2 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -91,10 +91,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.SeriesPoint"; public: SeriesPoint() = default; SeriesPoint(SeriesPoint&& other) = default; + SeriesPoint(const SeriesPoint& other) = default; + SeriesPoint& operator=(const SeriesPoint& other) = default; + SeriesPoint& operator=(SeriesPoint&& other) = default; /// Color for the corresponding series. SeriesPoint with_color(rerun::components::Color _color) && { diff --git a/rerun_cpp/src/rerun/archetypes/tensor.hpp b/rerun_cpp/src/rerun/archetypes/tensor.hpp index 8f2b553ab2c9a..febeaffb41b68 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.hpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.hpp @@ -74,6 +74,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Tensor"; public: // START of extensions from tensor_ext.cpp: /// New Tensor from dimensions and tensor buffer. @@ -104,6 +106,9 @@ namespace rerun::archetypes { public: Tensor() = default; Tensor(Tensor&& other) = default; + Tensor(const Tensor& other) = default; + Tensor& operator=(const Tensor& other) = default; + Tensor& operator=(Tensor&& other) = default; explicit Tensor(rerun::components::TensorData _data) : data(std::move(_data)) {} diff --git a/rerun_cpp/src/rerun/archetypes/text_document.hpp b/rerun_cpp/src/rerun/archetypes/text_document.hpp index 0fde7cc92adff..c54cc5479f597 100644 --- a/rerun_cpp/src/rerun/archetypes/text_document.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_document.hpp @@ -93,10 +93,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.TextDocument"; public: TextDocument() = default; TextDocument(TextDocument&& other) = default; + TextDocument(const TextDocument& other) = default; + TextDocument& operator=(const TextDocument& other) = default; + TextDocument& operator=(TextDocument&& other) = default; explicit TextDocument(rerun::components::Text _text) : text(std::move(_text)) {} diff --git a/rerun_cpp/src/rerun/archetypes/text_log.hpp b/rerun_cpp/src/rerun/archetypes/text_log.hpp index 588596cfde871..354a620031c5c 100644 --- a/rerun_cpp/src/rerun/archetypes/text_log.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_log.hpp @@ -95,10 +95,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.TextLog"; public: TextLog() = default; TextLog(TextLog&& other) = default; + TextLog(const TextLog& other) = default; + TextLog& operator=(const TextLog& other) = default; + TextLog& operator=(TextLog&& other) = default; explicit TextLog(rerun::components::Text _text) : text(std::move(_text)) {} diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.cpp b/rerun_cpp/src/rerun/archetypes/transform3d.cpp index d75e3b616af61..41a3722791213 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.cpp @@ -5,7 +5,33 @@ #include "../collection_adapter_builtins.hpp" -namespace rerun::archetypes {} +namespace rerun::archetypes { + Transform3D Transform3D::clear_fields() { + auto archetype = Transform3D(); + archetype.translation = + ComponentBatch::empty(Descriptor_translation) + .value_or_throw(); + archetype.rotation_axis_angle = ComponentBatch::empty( + Descriptor_rotation_axis_angle + ) + .value_or_throw(); + archetype.quaternion = + ComponentBatch::empty(Descriptor_quaternion) + .value_or_throw(); + archetype.scale = + ComponentBatch::empty(Descriptor_scale).value_or_throw(); + archetype.mat3x3 = + ComponentBatch::empty(Descriptor_mat3x3) + .value_or_throw(); + archetype.relation = + ComponentBatch::empty(Descriptor_relation) + .value_or_throw(); + archetype.axis_length = + ComponentBatch::empty(Descriptor_axis_length) + .value_or_throw(); + return archetype; + } +} // namespace rerun::archetypes namespace rerun { @@ -16,89 +42,26 @@ namespace rerun { std::vector cells; cells.reserve(8); - { - auto result = ComponentBatch::from_loggable( - archetype.translation, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "translation", - "rerun.components.Translation3D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.translation.has_value()) { + cells.push_back(archetype.translation.value()); } - { - auto result = ComponentBatch::from_loggable( - archetype.rotation_axis_angle, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "rotation_axis_angle", - "rerun.components.RotationAxisAngle" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.rotation_axis_angle.has_value()) { + cells.push_back(archetype.rotation_axis_angle.value()); } - { - auto result = ComponentBatch::from_loggable( - archetype.quaternion, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "quaternion", - "rerun.components.RotationQuat" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.quaternion.has_value()) { + cells.push_back(archetype.quaternion.value()); } - { - auto result = ComponentBatch::from_loggable( - archetype.scale, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "scale", - "rerun.components.Scale3D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.scale.has_value()) { + cells.push_back(archetype.scale.value()); } - { - auto result = ComponentBatch::from_loggable( - archetype.mat3x3, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "mat3x3", - "rerun.components.TransformMat3x3" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.mat3x3.has_value()) { + cells.push_back(archetype.mat3x3.value()); } - { - auto result = ComponentBatch::from_loggable( - archetype.relation, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "relation", - "rerun.components.TransformRelation" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.relation.has_value()) { + cells.push_back(archetype.relation.value()); } - { - auto result = ComponentBatch::from_loggable( - archetype.axis_length, - ComponentDescriptor( - "rerun.archetypes.Transform3D", - "axis_length", - "rerun.components.AxisLength" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.axis_length.has_value()) { + cells.push_back(archetype.axis_length.value()); } { auto indicator = Transform3D::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index 060b8052e8728..64e6cd60b07c8 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -152,28 +152,28 @@ namespace rerun::archetypes { /// ``` struct Transform3D { /// Translation vector. - std::optional translation; + std::optional translation; /// Rotation via axis + angle. - std::optional rotation_axis_angle; + std::optional rotation_axis_angle; /// Rotation via quaternion. - std::optional quaternion; + std::optional quaternion; /// Scaling factor. - std::optional scale; + std::optional scale; /// 3x3 transformation matrix. - std::optional mat3x3; + std::optional mat3x3; /// Specifies the relation this transform establishes between this entity and its parent. - std::optional relation; + std::optional relation; /// 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. - std::optional axis_length; + std::optional axis_length; public: static constexpr const char IndicatorComponentName[] = @@ -181,6 +181,43 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Transform3D"; + + /// `ComponentDescriptor` for the `translation` field. + static constexpr auto Descriptor_translation = ComponentDescriptor( + ArchetypeName, "translation", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `rotation_axis_angle` field. + static constexpr auto Descriptor_rotation_axis_angle = ComponentDescriptor( + ArchetypeName, "rotation_axis_angle", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `quaternion` field. + static constexpr auto Descriptor_quaternion = ComponentDescriptor( + ArchetypeName, "quaternion", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `scale` field. + static constexpr auto Descriptor_scale = ComponentDescriptor( + ArchetypeName, "scale", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `mat3x3` field. + static constexpr auto Descriptor_mat3x3 = ComponentDescriptor( + ArchetypeName, "mat3x3", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `relation` field. + static constexpr auto Descriptor_relation = ComponentDescriptor( + ArchetypeName, "relation", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `axis_length` field. + static constexpr auto Descriptor_axis_length = ComponentDescriptor( + ArchetypeName, "axis_length", + Loggable::Descriptor.component_name + ); public: // START of extensions from transform3d_ext.cpp: /// Identity transformation. @@ -194,6 +231,7 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const Transform3D INVALID; /// Creates a new 3D transform from translation and matrix provided as 3 columns. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \çopydoc Transform3D::translation /// \param columns Column vectors of 3x3 matrix. @@ -208,6 +246,7 @@ namespace rerun::archetypes { : Transform3D(translation_, components::TransformMat3x3(columns), from_parent) {} /// Creates a new 3D transform from translation/matrix. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \çopydoc Transform3D::translation /// \param mat3x3_ \copydoc Transform3D::mat3x3 @@ -215,14 +254,16 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const components::TransformMat3x3& mat3x3_, bool from_parent = false - ) - : translation(translation_), mat3x3(mat3x3_) { + ) { + *this = Transform3D::clear_fields().with_translation(translation_).with_mat3x3(mat3x3_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From a translation applied after a 3x3 matrix. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \çopydoc Transform3D::translation /// \param mat3x3 \copydoc Transform3D::mat3x3 @@ -233,6 +274,7 @@ namespace rerun::archetypes { } /// From a translation applied after a 3x3 matrix provided as 3 columns. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \çopydoc Transform3D::translation /// \param columns Column vectors of 3x3 matrix. @@ -246,17 +288,20 @@ namespace rerun::archetypes { } /// From translation only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \çopydoc Transform3D::translation /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. - Transform3D(const components::Translation3D& translation_, bool from_parent = false) - : translation(translation_) { + Transform3D(const components::Translation3D& translation_, bool from_parent = false) { + *this = Transform3D::clear_fields().with_translation(translation_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From a translation. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \çopydoc Transform3D::translation static Transform3D from_translation(const components::Translation3D& translation) { @@ -264,17 +309,20 @@ namespace rerun::archetypes { } /// From 3x3 matrix only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param mat3x3_ \copydoc Transform3D::mat3x3 /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. - Transform3D(const components::TransformMat3x3& mat3x3_, bool from_parent = false) - : mat3x3(mat3x3_) { + Transform3D(const components::TransformMat3x3& mat3x3_, bool from_parent = false) { + *this = Transform3D::clear_fields().with_mat3x3(mat3x3_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From 3x3 matrix only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param mat3x3 \copydoc Transform3D::mat3x3 static Transform3D from_mat3x3(const components::TransformMat3x3& mat3x3) { @@ -282,6 +330,7 @@ namespace rerun::archetypes { } /// From 3x3 matrix provided as 3 columns only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param columns Column vectors of 3x3 matrix. /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. @@ -289,6 +338,7 @@ namespace rerun::archetypes { : Transform3D(components::TransformMat3x3(columns), from_parent) {} /// From 3x3 matrix provided as 3 columns only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param columns Column vectors of 3x3 matrix. static Transform3D from_mat3x3(const datatypes::Vec3D (&columns)[3]) { @@ -296,6 +346,7 @@ namespace rerun::archetypes { } /// Creates a new 3D transform from translation/rotation/scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -304,15 +355,19 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const Rotation3D& rotation, const components::Scale3D& scale_, bool from_parent = false - ) - : translation(translation_), scale(scale_) { + ) { + *this = Transform3D::clear_fields() + .with_translation(translation_) + .with_scale(scale_) + .with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// Creates a new 3D transform from translation/rotation/uniform-scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -329,6 +384,7 @@ namespace rerun::archetypes { } /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -341,6 +397,7 @@ namespace rerun::archetypes { } /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -353,6 +410,7 @@ namespace rerun::archetypes { } /// Creates a new rigid transform (translation & rotation only). + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -360,15 +418,17 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const Rotation3D& rotation, bool from_parent = false - ) - : translation(translation_) { + ) { + *this = + Transform3D::clear_fields().with_translation(translation_).with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// From a rotation & scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -379,6 +439,7 @@ namespace rerun::archetypes { } /// From translation & scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param scale_ Transform3D::scale @@ -386,14 +447,16 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const components::Scale3D& scale_, bool from_parent = false - ) - : translation(translation_), scale(scale_) { + ) { + *this = Transform3D::clear_fields().with_translation(translation_).with_scale(scale_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From a translation applied after a scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param scale Transform3D::scale @@ -404,6 +467,7 @@ namespace rerun::archetypes { } /// From translation & uniform scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param uniform_scale Uniform scale factor that is applied to all axis equally. @@ -418,21 +482,23 @@ namespace rerun::archetypes { : Transform3D(translation_, components::Scale3D(uniform_scale), from_parent) {} /// From rotation & scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param scale_ Transform3D::scale /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. Transform3D( const Rotation3D& rotation, const components::Scale3D& scale_, bool from_parent = false - ) - : scale(scale_) { + ) { + *this = Transform3D::clear_fields().with_scale(scale_).with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// From rotation & uniform scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param uniform_scale Uniform scale factor that is applied to all axis equally. @@ -444,6 +510,7 @@ namespace rerun::archetypes { : Transform3D(rotation, components::Scale3D(uniform_scale), from_parent) {} /// From a rotation & scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param scale Transform3D::scale @@ -454,6 +521,7 @@ namespace rerun::archetypes { } /// From a rotation & uniform scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param uniform_scale Uniform scale factor that is applied to all axis equally. @@ -462,17 +530,20 @@ namespace rerun::archetypes { } /// From rotation only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. Transform3D(const Rotation3D& rotation, bool from_parent = false) { + *this = Transform3D::clear_fields().with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// From rotation only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. static Transform3D from_rotation(const Rotation3D& rotation) { @@ -480,16 +551,20 @@ namespace rerun::archetypes { } /// From scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param scale_ If true, the transform relation to `TransformRelation::ChildFromParent`. /// \param from_parent \copydoc Transform3D::scale - Transform3D(const components::Scale3D& scale_, bool from_parent = false) : scale(scale_) { + Transform3D(const components::Scale3D& scale_, bool from_parent = false) { + *this = Transform3D::clear_fields().with_scale(scale_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = + std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param scale Transform3D::scale static Transform3D from_scale(const components::Scale3D& scale) { @@ -497,22 +572,22 @@ namespace rerun::archetypes { } /// From scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param uniform_scale Uniform scale factor that is applied to all axis equally. static Transform3D from_scale(float uniform_scale) { return Transform3D(components::Scale3D(uniform_scale), false); } - private: /// Set the rotation component of the transform using the `rerun::Rotation3D` utility. - void set_rotation(const Rotation3D& rotation) { + Transform3D with_rotation(const Rotation3D& rotation) && { if (rotation.axis_angle.has_value()) { - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(rotation_axis_angle = - rotation.axis_angle.value();) + *this = std::move(*this).with_rotation_axis_angle(rotation.axis_angle.value()); } if (rotation.quaternion.has_value()) { - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(quaternion = rotation.quaternion.value();) + *this = std::move(*this).with_quaternion(rotation.quaternion.value()); } + return std::move(*this); } // END of extensions from transform3d_ext.cpp, start of generated code: @@ -520,47 +595,63 @@ namespace rerun::archetypes { public: Transform3D() = default; Transform3D(Transform3D&& other) = default; + Transform3D(const Transform3D& other) = default; + Transform3D& operator=(const Transform3D& other) = default; + Transform3D& operator=(Transform3D&& other) = default; + + /// Update only some specific fields of a `Transform3D`. + static Transform3D update_fields() { + return Transform3D(); + } + + /// Clear all the fields of a `Transform3D`. + static Transform3D clear_fields(); /// Translation vector. - Transform3D with_translation(rerun::components::Translation3D _translation) && { - translation = std::move(_translation); + Transform3D with_translation(const rerun::components::Translation3D& _translation) && { + translation = ComponentBatch::from_loggable(_translation, Descriptor_translation) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Rotation via axis + angle. Transform3D with_rotation_axis_angle( - rerun::components::RotationAxisAngle _rotation_axis_angle + const rerun::components::RotationAxisAngle& _rotation_axis_angle ) && { - rotation_axis_angle = std::move(_rotation_axis_angle); + rotation_axis_angle = + ComponentBatch::from_loggable(_rotation_axis_angle, Descriptor_rotation_axis_angle) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Rotation via quaternion. - Transform3D with_quaternion(rerun::components::RotationQuat _quaternion) && { - quaternion = std::move(_quaternion); + Transform3D with_quaternion(const rerun::components::RotationQuat& _quaternion) && { + quaternion = + ComponentBatch::from_loggable(_quaternion, Descriptor_quaternion).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Scaling factor. - Transform3D with_scale(rerun::components::Scale3D _scale) && { - scale = std::move(_scale); + Transform3D with_scale(const rerun::components::Scale3D& _scale) && { + scale = ComponentBatch::from_loggable(_scale, Descriptor_scale).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// 3x3 transformation matrix. - Transform3D with_mat3x3(rerun::components::TransformMat3x3 _mat3x3) && { - mat3x3 = std::move(_mat3x3); + Transform3D with_mat3x3(const rerun::components::TransformMat3x3& _mat3x3) && { + mat3x3 = ComponentBatch::from_loggable(_mat3x3, Descriptor_mat3x3).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Specifies the relation this transform establishes between this entity and its parent. - Transform3D with_relation(rerun::components::TransformRelation _relation) && { - relation = std::move(_relation); + Transform3D with_relation(const rerun::components::TransformRelation& _relation) && { + relation = + ComponentBatch::from_loggable(_relation, Descriptor_relation).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -569,8 +660,9 @@ namespace rerun::archetypes { /// /// The length is interpreted in the local coordinate system of the transform. /// If the transform is scaled, the axes will be scaled accordingly. - Transform3D with_axis_length(rerun::components::AxisLength _axis_length) && { - axis_length = std::move(_axis_length); + Transform3D with_axis_length(const rerun::components::AxisLength& _axis_length) && { + axis_length = ComponentBatch::from_loggable(_axis_length, Descriptor_axis_length) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp index 9e9b04087e1e3..fdd9fabecd367 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp @@ -22,6 +22,7 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const Transform3D INVALID; /// Creates a new 3D transform from translation and matrix provided as 3 columns. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \çopydoc Transform3D::translation /// \param columns Column vectors of 3x3 matrix. @@ -36,6 +37,7 @@ namespace rerun::archetypes { : Transform3D(translation_, components::TransformMat3x3(columns), from_parent) {} /// Creates a new 3D transform from translation/matrix. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \çopydoc Transform3D::translation /// \param mat3x3_ \copydoc Transform3D::mat3x3 @@ -43,14 +45,15 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const components::TransformMat3x3& mat3x3_, bool from_parent = false - ) - : translation(translation_), mat3x3(mat3x3_) { + ) { + *this = Transform3D::clear_fields().with_translation(translation_).with_mat3x3(mat3x3_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From a translation applied after a 3x3 matrix. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \çopydoc Transform3D::translation /// \param mat3x3 \copydoc Transform3D::mat3x3 @@ -61,6 +64,7 @@ namespace rerun::archetypes { } /// From a translation applied after a 3x3 matrix provided as 3 columns. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \çopydoc Transform3D::translation /// \param columns Column vectors of 3x3 matrix. @@ -74,17 +78,19 @@ namespace rerun::archetypes { } /// From translation only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \çopydoc Transform3D::translation /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. - Transform3D(const components::Translation3D& translation_, bool from_parent = false) - : translation(translation_) { + Transform3D(const components::Translation3D& translation_, bool from_parent = false) { + *this = Transform3D::clear_fields().with_translation(translation_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From a translation. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \çopydoc Transform3D::translation static Transform3D from_translation(const components::Translation3D& translation) { @@ -92,17 +98,19 @@ namespace rerun::archetypes { } /// From 3x3 matrix only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param mat3x3_ \copydoc Transform3D::mat3x3 /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. - Transform3D(const components::TransformMat3x3& mat3x3_, bool from_parent = false) - : mat3x3(mat3x3_) { + Transform3D(const components::TransformMat3x3& mat3x3_, bool from_parent = false) { + *this = Transform3D::clear_fields().with_mat3x3(mat3x3_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From 3x3 matrix only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param mat3x3 \copydoc Transform3D::mat3x3 static Transform3D from_mat3x3(const components::TransformMat3x3& mat3x3) { @@ -110,6 +118,7 @@ namespace rerun::archetypes { } /// From 3x3 matrix provided as 3 columns only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param columns Column vectors of 3x3 matrix. /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. @@ -117,6 +126,7 @@ namespace rerun::archetypes { : Transform3D(components::TransformMat3x3(columns), from_parent) {} /// From 3x3 matrix provided as 3 columns only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param columns Column vectors of 3x3 matrix. static Transform3D from_mat3x3(const datatypes::Vec3D (&columns)[3]) { @@ -124,6 +134,7 @@ namespace rerun::archetypes { } /// Creates a new 3D transform from translation/rotation/scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -132,15 +143,15 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const Rotation3D& rotation, const components::Scale3D& scale_, bool from_parent = false - ) - : translation(translation_), scale(scale_) { + ) { + *this = Transform3D::clear_fields().with_translation(translation_).with_scale(scale_).with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// Creates a new 3D transform from translation/rotation/uniform-scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -156,6 +167,7 @@ namespace rerun::archetypes { : Transform3D(translation_, rotation, components::Scale3D(uniform_scale), from_parent) {} /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -168,6 +180,7 @@ namespace rerun::archetypes { } /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -180,6 +193,7 @@ namespace rerun::archetypes { } /// Creates a new rigid transform (translation & rotation only). + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -187,15 +201,15 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const Rotation3D& rotation, bool from_parent = false - ) - : translation(translation_) { + ) { + *this = Transform3D::clear_fields().with_translation(translation_).with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// From a rotation & scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. @@ -206,6 +220,7 @@ namespace rerun::archetypes { } /// From translation & scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param scale_ Transform3D::scale @@ -213,14 +228,15 @@ namespace rerun::archetypes { Transform3D( const components::Translation3D& translation_, const components::Scale3D& scale_, bool from_parent = false - ) - : translation(translation_), scale(scale_) { + ) { + *this = Transform3D::clear_fields().with_translation(translation_).with_scale(scale_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From a translation applied after a scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation \copydoc Transform3D::translation /// \param scale Transform3D::scale @@ -231,6 +247,7 @@ namespace rerun::archetypes { } /// From translation & uniform scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param translation_ \copydoc Transform3D::translation /// \param uniform_scale Uniform scale factor that is applied to all axis equally. @@ -244,21 +261,22 @@ namespace rerun::archetypes { : Transform3D(translation_, components::Scale3D(uniform_scale), from_parent) {} /// From rotation & scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param scale_ Transform3D::scale /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. Transform3D( const Rotation3D& rotation, const components::Scale3D& scale_, bool from_parent = false - ) - : scale(scale_) { + ) { + *this = Transform3D::clear_fields().with_scale(scale_).with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// From rotation & uniform scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param uniform_scale Uniform scale factor that is applied to all axis equally. @@ -270,6 +288,7 @@ namespace rerun::archetypes { : Transform3D(rotation, components::Scale3D(uniform_scale), from_parent) {} /// From a rotation & scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param scale Transform3D::scale @@ -280,6 +299,7 @@ namespace rerun::archetypes { } /// From a rotation & uniform scale. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param uniform_scale Uniform scale factor that is applied to all axis equally. @@ -288,17 +308,19 @@ namespace rerun::archetypes { } /// From rotation only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. /// \param from_parent If true, the transform relation to `TransformRelation::ChildFromParent`. Transform3D(const Rotation3D& rotation, bool from_parent = false) { + *this = Transform3D::clear_fields().with_rotation(rotation); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } - set_rotation(rotation); } /// From rotation only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param rotation Rotation represented either as a quaternion or axis + angle rotation. static Transform3D from_rotation(const Rotation3D& rotation) { @@ -306,16 +328,19 @@ namespace rerun::archetypes { } /// From scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param scale_ If true, the transform relation to `TransformRelation::ChildFromParent`. /// \param from_parent \copydoc Transform3D::scale - Transform3D(const components::Scale3D& scale_, bool from_parent = false) : scale(scale_) { + Transform3D(const components::Scale3D& scale_, bool from_parent = false) { + *this = Transform3D::clear_fields().with_scale(scale_); if (from_parent) { - relation = components::TransformRelation::ChildFromParent; + *this = std::move(*this).with_relation(components::TransformRelation::ChildFromParent); } } /// From scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param scale Transform3D::scale static Transform3D from_scale(const components::Scale3D& scale) { @@ -323,21 +348,22 @@ namespace rerun::archetypes { } /// From scale only. + /// Clears out all other components like `Transform3D::clear_fields`. /// /// \param uniform_scale Uniform scale factor that is applied to all axis equally. static Transform3D from_scale(float uniform_scale) { return Transform3D(components::Scale3D(uniform_scale), false); } - private: /// Set the rotation component of the transform using the `rerun::Rotation3D` utility. - void set_rotation(const Rotation3D& rotation) { + Transform3D with_rotation(const Rotation3D& rotation) && { if (rotation.axis_angle.has_value()) { - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(rotation_axis_angle = rotation.axis_angle.value();) + *this = std::move(*this).with_rotation_axis_angle(rotation.axis_angle.value()); } if (rotation.quaternion.has_value()) { - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(quaternion = rotation.quaternion.value();) + *this = std::move(*this).with_quaternion(rotation.quaternion.value()); } + return std::move(*this); } // diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp index b6566f6437777..c1cb1ea1a2d13 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp @@ -139,10 +139,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.VideoFrameReference"; public: VideoFrameReference() = default; VideoFrameReference(VideoFrameReference&& other) = default; + VideoFrameReference(const VideoFrameReference& other) = default; + VideoFrameReference& operator=(const VideoFrameReference& other) = default; + VideoFrameReference& operator=(VideoFrameReference&& other) = default; explicit VideoFrameReference(rerun::components::VideoTimestamp _timestamp) : timestamp(std::move(_timestamp)) {} diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index e23893a79f89f..c3a1ab9433fea 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -58,6 +58,8 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.ViewCoordinates"; public: // START of extensions from view_coordinates_ext.cpp: /// Construct Vec3D from x/y/z values. @@ -313,6 +315,9 @@ namespace rerun::archetypes { public: ViewCoordinates() = default; ViewCoordinates(ViewCoordinates&& other) = default; + ViewCoordinates(const ViewCoordinates& other) = default; + ViewCoordinates& operator=(const ViewCoordinates& other) = default; + ViewCoordinates& operator=(ViewCoordinates&& other) = default; explicit ViewCoordinates(rerun::components::ViewCoordinates _xyz) : xyz(std::move(_xyz)) {} }; diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp index da81f2e5cc173..5905601598458 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp @@ -5,7 +5,17 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + Background Background::clear_fields() { + auto archetype = Background(); + archetype.kind = + ComponentBatch::empty(Descriptor_kind) + .value_or_throw(); + archetype.color = + ComponentBatch::empty(Descriptor_color).value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -16,29 +26,11 @@ namespace rerun { std::vector cells; cells.reserve(3); - { - auto result = ComponentBatch::from_loggable( - archetype.kind, - ComponentDescriptor( - "rerun.blueprint.archetypes.Background", - "kind", - "rerun.blueprint.components.BackgroundKind" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.kind.has_value()) { + cells.push_back(archetype.kind.value()); } if (archetype.color.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.color.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.Background", - "color", - "rerun.components.Color" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.color.value()); } { auto indicator = Background::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp index 4f66607a5cb44..a8cb04fcbc80c 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp @@ -20,10 +20,10 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Configuration for the background of a view. struct Background { /// The type of the background. - rerun::blueprint::components::BackgroundKind kind; + std::optional kind; /// Color used for the solid background type. - std::optional color; + std::optional color; public: static constexpr const char IndicatorComponentName[] = @@ -31,17 +31,48 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.Background"; + + /// `ComponentDescriptor` for the `kind` field. + static constexpr auto Descriptor_kind = ComponentDescriptor( + ArchetypeName, "kind", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `color` field. + static constexpr auto Descriptor_color = ComponentDescriptor( + ArchetypeName, "color", Loggable::Descriptor.component_name + ); public: Background() = default; Background(Background&& other) = default; + Background(const Background& other) = default; + Background& operator=(const Background& other) = default; + Background& operator=(Background&& other) = default; explicit Background(rerun::blueprint::components::BackgroundKind _kind) - : kind(std::move(_kind)) {} + : kind(ComponentBatch::from_loggable(std::move(_kind), Descriptor_kind).value_or_throw() + ) {} + + /// Update only some specific fields of a `Background`. + static Background update_fields() { + return Background(); + } + + /// Clear all the fields of a `Background`. + static Background clear_fields(); + + /// The type of the background. + Background with_kind(const rerun::blueprint::components::BackgroundKind& _kind) && { + kind = ComponentBatch::from_loggable(_kind, Descriptor_kind).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// Color used for the solid background type. - Background with_color(rerun::components::Color _color) && { - color = std::move(_color); + Background with_color(const rerun::components::Color& _color) && { + color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp index 8e197acfea17e..b607521b996cc 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.cpp @@ -5,7 +5,40 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ContainerBlueprint ContainerBlueprint::clear_fields() { + auto archetype = ContainerBlueprint(); + archetype.container_kind = + ComponentBatch::empty( + Descriptor_container_kind + ) + .value_or_throw(); + archetype.display_name = + ComponentBatch::empty(Descriptor_display_name) + .value_or_throw(); + archetype.contents = + ComponentBatch::empty(Descriptor_contents + ) + .value_or_throw(); + archetype.col_shares = + ComponentBatch::empty(Descriptor_col_shares) + .value_or_throw(); + archetype.row_shares = + ComponentBatch::empty(Descriptor_row_shares) + .value_or_throw(); + archetype.active_tab = + ComponentBatch::empty(Descriptor_active_tab) + .value_or_throw(); + archetype.visible = + ComponentBatch::empty(Descriptor_visible) + .value_or_throw(); + archetype.grid_columns = + ComponentBatch::empty(Descriptor_grid_columns + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,101 +50,29 @@ namespace rerun { std::vector cells; cells.reserve(9); - { - auto result = ComponentBatch::from_loggable( - archetype.container_kind, - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "container_kind", - "rerun.blueprint.components.ContainerKind" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.container_kind.has_value()) { + cells.push_back(archetype.container_kind.value()); } if (archetype.display_name.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.display_name.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "display_name", - "rerun.components.Name" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.display_name.value()); } if (archetype.contents.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.contents.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "contents", - "rerun.blueprint.components.IncludedContent" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.contents.value()); } if (archetype.col_shares.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.col_shares.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "col_shares", - "rerun.blueprint.components.ColumnShare" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.col_shares.value()); } if (archetype.row_shares.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.row_shares.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "row_shares", - "rerun.blueprint.components.RowShare" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.row_shares.value()); } if (archetype.active_tab.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.active_tab.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "active_tab", - "rerun.blueprint.components.ActiveTab" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.active_tab.value()); } if (archetype.visible.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.visible.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "visible", - "rerun.blueprint.components.Visible" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.visible.value()); } if (archetype.grid_columns.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.grid_columns.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ContainerBlueprint", - "grid_columns", - "rerun.blueprint.components.GridColumns" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.grid_columns.value()); } { auto indicator = ContainerBlueprint::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp index caff22d94b70f..657763eaea81d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp @@ -26,44 +26,44 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: The description of a container. struct ContainerBlueprint { /// The class of the view. - rerun::blueprint::components::ContainerKind container_kind; + std::optional container_kind; /// The name of the container. - std::optional display_name; + std::optional display_name; /// `ContainerId`s or `ViewId`s that are children of this container. - std::optional> contents; + std::optional contents; /// The layout shares of each column in the container. /// /// For `components::ContainerKind::Horizontal` containers, the length of this list should always match the number of contents. /// /// Ignored for `components::ContainerKind::Vertical` containers. - std::optional> col_shares; + std::optional col_shares; /// The layout shares of each row of the container. /// /// For `components::ContainerKind::Vertical` containers, the length of this list should always match the number of contents. /// /// Ignored for `components::ContainerKind::Horizontal` containers. - std::optional> row_shares; + std::optional row_shares; /// Which tab is active. /// /// Only applies to `Tabs` containers. - std::optional active_tab; + std::optional active_tab; /// Whether this container is visible. /// /// Defaults to true if not specified. - std::optional visible; + std::optional visible; /// How many columns this grid should have. /// /// If unset, the grid layout will be auto. /// /// Ignored for `components::ContainerKind::Horizontal`/`components::ContainerKind::Vertical` containers. - std::optional grid_columns; + std::optional grid_columns; public: static constexpr const char IndicatorComponentName[] = @@ -71,26 +71,97 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = + "rerun.blueprint.archetypes.ContainerBlueprint"; + + /// `ComponentDescriptor` for the `container_kind` field. + static constexpr auto Descriptor_container_kind = ComponentDescriptor( + ArchetypeName, "container_kind", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `display_name` field. + static constexpr auto Descriptor_display_name = ComponentDescriptor( + ArchetypeName, "display_name", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `contents` field. + static constexpr auto Descriptor_contents = ComponentDescriptor( + ArchetypeName, "contents", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `col_shares` field. + static constexpr auto Descriptor_col_shares = ComponentDescriptor( + ArchetypeName, "col_shares", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `row_shares` field. + static constexpr auto Descriptor_row_shares = ComponentDescriptor( + ArchetypeName, "row_shares", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `active_tab` field. + static constexpr auto Descriptor_active_tab = ComponentDescriptor( + ArchetypeName, "active_tab", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `visible` field. + static constexpr auto Descriptor_visible = ComponentDescriptor( + ArchetypeName, "visible", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `grid_columns` field. + static constexpr auto Descriptor_grid_columns = ComponentDescriptor( + ArchetypeName, "grid_columns", + Loggable::Descriptor.component_name + ); public: ContainerBlueprint() = default; ContainerBlueprint(ContainerBlueprint&& other) = default; + ContainerBlueprint(const ContainerBlueprint& other) = default; + ContainerBlueprint& operator=(const ContainerBlueprint& other) = default; + ContainerBlueprint& operator=(ContainerBlueprint&& other) = default; explicit ContainerBlueprint(rerun::blueprint::components::ContainerKind _container_kind) - : container_kind(std::move(_container_kind)) {} + : container_kind(ComponentBatch::from_loggable( + std::move(_container_kind), Descriptor_container_kind + ) + .value_or_throw()) {} + + /// Update only some specific fields of a `ContainerBlueprint`. + static ContainerBlueprint update_fields() { + return ContainerBlueprint(); + } + + /// Clear all the fields of a `ContainerBlueprint`. + static ContainerBlueprint clear_fields(); + + /// The class of the view. + ContainerBlueprint with_container_kind( + const rerun::blueprint::components::ContainerKind& _container_kind + ) && { + container_kind = + ComponentBatch::from_loggable(_container_kind, Descriptor_container_kind) + .value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// The name of the container. - ContainerBlueprint with_display_name(rerun::components::Name _display_name) && { - display_name = std::move(_display_name); + ContainerBlueprint with_display_name(const rerun::components::Name& _display_name) && { + display_name = ComponentBatch::from_loggable(_display_name, Descriptor_display_name) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// `ContainerId`s or `ViewId`s that are children of this container. ContainerBlueprint with_contents( - Collection _contents + const Collection& _contents ) && { - contents = std::move(_contents); + contents = + ComponentBatch::from_loggable(_contents, Descriptor_contents).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -101,9 +172,10 @@ namespace rerun::blueprint::archetypes { /// /// Ignored for `components::ContainerKind::Vertical` containers. ContainerBlueprint with_col_shares( - Collection _col_shares + const Collection& _col_shares ) && { - col_shares = std::move(_col_shares); + col_shares = + ComponentBatch::from_loggable(_col_shares, Descriptor_col_shares).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -114,9 +186,10 @@ namespace rerun::blueprint::archetypes { /// /// Ignored for `components::ContainerKind::Horizontal` containers. ContainerBlueprint with_row_shares( - Collection _row_shares + const Collection& _row_shares ) && { - row_shares = std::move(_row_shares); + row_shares = + ComponentBatch::from_loggable(_row_shares, Descriptor_row_shares).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -124,8 +197,11 @@ namespace rerun::blueprint::archetypes { /// Which tab is active. /// /// Only applies to `Tabs` containers. - ContainerBlueprint with_active_tab(rerun::blueprint::components::ActiveTab _active_tab) && { - active_tab = std::move(_active_tab); + ContainerBlueprint with_active_tab( + const rerun::blueprint::components::ActiveTab& _active_tab + ) && { + active_tab = + ComponentBatch::from_loggable(_active_tab, Descriptor_active_tab).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -133,8 +209,8 @@ namespace rerun::blueprint::archetypes { /// Whether this container is visible. /// /// Defaults to true if not specified. - ContainerBlueprint with_visible(rerun::blueprint::components::Visible _visible) && { - visible = std::move(_visible); + ContainerBlueprint with_visible(const rerun::blueprint::components::Visible& _visible) && { + visible = ComponentBatch::from_loggable(_visible, Descriptor_visible).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -144,9 +220,11 @@ namespace rerun::blueprint::archetypes { /// If unset, the grid layout will be auto. /// /// Ignored for `components::ContainerKind::Horizontal`/`components::ContainerKind::Vertical` containers. - ContainerBlueprint with_grid_columns(rerun::blueprint::components::GridColumns _grid_columns + ContainerBlueprint with_grid_columns( + const rerun::blueprint::components::GridColumns& _grid_columns ) && { - grid_columns = std::move(_grid_columns); + grid_columns = ComponentBatch::from_loggable(_grid_columns, Descriptor_grid_columns) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp index f24cf3f2b6a33..a2e97aec62b0f 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.cpp @@ -5,7 +5,33 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + DataframeQuery DataframeQuery::clear_fields() { + auto archetype = DataframeQuery(); + archetype.timeline = + ComponentBatch::empty(Descriptor_timeline) + .value_or_throw(); + archetype.filter_by_range = + ComponentBatch::empty( + Descriptor_filter_by_range + ) + .value_or_throw(); + archetype.filter_is_not_null = + ComponentBatch::empty( + Descriptor_filter_is_not_null + ) + .value_or_throw(); + archetype.apply_latest_at = + ComponentBatch::empty( + Descriptor_apply_latest_at + ) + .value_or_throw(); + archetype.select = + ComponentBatch::empty(Descriptor_select) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,64 +44,19 @@ namespace rerun { cells.reserve(6); if (archetype.timeline.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.timeline.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.DataframeQuery", - "timeline", - "rerun.blueprint.components.TimelineName" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.timeline.value()); } if (archetype.filter_by_range.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.filter_by_range.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.DataframeQuery", - "filter_by_range", - "rerun.blueprint.components.FilterByRange" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.filter_by_range.value()); } if (archetype.filter_is_not_null.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.filter_is_not_null.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.DataframeQuery", - "filter_is_not_null", - "rerun.blueprint.components.FilterIsNotNull" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.filter_is_not_null.value()); } if (archetype.apply_latest_at.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.apply_latest_at.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.DataframeQuery", - "apply_latest_at", - "rerun.blueprint.components.ApplyLatestAt" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.apply_latest_at.value()); } if (archetype.select.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.select.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.DataframeQuery", - "select", - "rerun.blueprint.components.SelectedColumns" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.select.value()); } { auto indicator = DataframeQuery::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp index 7b2c54a574195..60ec5708b1554 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/dataframe_query.hpp @@ -25,21 +25,21 @@ namespace rerun::blueprint::archetypes { /// The timeline for this query. /// /// If unset, the timeline currently active on the time panel is used. - std::optional timeline; + std::optional timeline; /// If provided, only rows whose timestamp is within this range will be shown. /// /// Note: will be unset as soon as `timeline` is changed. - std::optional filter_by_range; + std::optional filter_by_range; /// If provided, only show rows which contains a logged event for the specified component. - std::optional filter_is_not_null; + std::optional filter_is_not_null; /// Should empty cells be filled with latest-at queries? - std::optional apply_latest_at; + std::optional apply_latest_at; /// Selected columns. If unset, all columns are selected. - std::optional select; + std::optional select; public: static constexpr const char IndicatorComponentName[] = @@ -47,16 +47,57 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.DataframeQuery"; + + /// `ComponentDescriptor` for the `timeline` field. + static constexpr auto Descriptor_timeline = ComponentDescriptor( + ArchetypeName, "timeline", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `filter_by_range` field. + static constexpr auto Descriptor_filter_by_range = ComponentDescriptor( + ArchetypeName, "filter_by_range", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `filter_is_not_null` field. + static constexpr auto Descriptor_filter_is_not_null = ComponentDescriptor( + ArchetypeName, "filter_is_not_null", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `apply_latest_at` field. + static constexpr auto Descriptor_apply_latest_at = ComponentDescriptor( + ArchetypeName, "apply_latest_at", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `select` field. + static constexpr auto Descriptor_select = ComponentDescriptor( + ArchetypeName, "select", + Loggable::Descriptor.component_name + ); public: DataframeQuery() = default; DataframeQuery(DataframeQuery&& other) = default; + DataframeQuery(const DataframeQuery& other) = default; + DataframeQuery& operator=(const DataframeQuery& other) = default; + DataframeQuery& operator=(DataframeQuery&& other) = default; + + /// Update only some specific fields of a `DataframeQuery`. + static DataframeQuery update_fields() { + return DataframeQuery(); + } + + /// Clear all the fields of a `DataframeQuery`. + static DataframeQuery clear_fields(); /// The timeline for this query. /// /// If unset, the timeline currently active on the time panel is used. - DataframeQuery with_timeline(rerun::blueprint::components::TimelineName _timeline) && { - timeline = std::move(_timeline); + DataframeQuery with_timeline(const rerun::blueprint::components::TimelineName& _timeline + ) && { + timeline = + ComponentBatch::from_loggable(_timeline, Descriptor_timeline).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -65,34 +106,41 @@ namespace rerun::blueprint::archetypes { /// /// Note: will be unset as soon as `timeline` is changed. DataframeQuery with_filter_by_range( - rerun::blueprint::components::FilterByRange _filter_by_range + const rerun::blueprint::components::FilterByRange& _filter_by_range ) && { - filter_by_range = std::move(_filter_by_range); + filter_by_range = + ComponentBatch::from_loggable(_filter_by_range, Descriptor_filter_by_range) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// If provided, only show rows which contains a logged event for the specified component. DataframeQuery with_filter_is_not_null( - rerun::blueprint::components::FilterIsNotNull _filter_is_not_null + const rerun::blueprint::components::FilterIsNotNull& _filter_is_not_null ) && { - filter_is_not_null = std::move(_filter_is_not_null); + filter_is_not_null = + ComponentBatch::from_loggable(_filter_is_not_null, Descriptor_filter_is_not_null) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Should empty cells be filled with latest-at queries? DataframeQuery with_apply_latest_at( - rerun::blueprint::components::ApplyLatestAt _apply_latest_at + const rerun::blueprint::components::ApplyLatestAt& _apply_latest_at ) && { - apply_latest_at = std::move(_apply_latest_at); + apply_latest_at = + ComponentBatch::from_loggable(_apply_latest_at, Descriptor_apply_latest_at) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Selected columns. If unset, all columns are selected. - DataframeQuery with_select(rerun::blueprint::components::SelectedColumns _select) && { - select = std::move(_select); + DataframeQuery with_select(const rerun::blueprint::components::SelectedColumns& _select + ) && { + select = ComponentBatch::from_loggable(_select, Descriptor_select).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp index a05527d07e182..92f6f668f6714 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp @@ -5,7 +5,18 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ForceCenter ForceCenter::clear_fields() { + auto archetype = ForceCenter(); + archetype.enabled = + ComponentBatch::empty(Descriptor_enabled) + .value_or_throw(); + archetype.strength = + ComponentBatch::empty(Descriptor_strength) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,28 +28,10 @@ namespace rerun { cells.reserve(3); if (archetype.enabled.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.enabled.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceCenter", - "enabled", - "rerun.blueprint.components.Enabled" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.enabled.value()); } if (archetype.strength.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.strength.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceCenter", - "strength", - "rerun.blueprint.components.ForceStrength" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.strength.value()); } { auto indicator = ForceCenter::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp index 4a76fb9c2ff77..e79756b9e8924 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp @@ -22,10 +22,10 @@ namespace rerun::blueprint::archetypes { /// Whether the center force is enabled. /// /// The center force tries to move the center of mass of the graph towards the origin. - std::optional enabled; + std::optional enabled; /// The strength of the force. - std::optional strength; + std::optional strength; public: static constexpr const char IndicatorComponentName[] = @@ -33,23 +33,48 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ForceCenter"; + + /// `ComponentDescriptor` for the `enabled` field. + static constexpr auto Descriptor_enabled = ComponentDescriptor( + ArchetypeName, "enabled", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `strength` field. + static constexpr auto Descriptor_strength = ComponentDescriptor( + ArchetypeName, "strength", + Loggable::Descriptor.component_name + ); public: ForceCenter() = default; ForceCenter(ForceCenter&& other) = default; + ForceCenter(const ForceCenter& other) = default; + ForceCenter& operator=(const ForceCenter& other) = default; + ForceCenter& operator=(ForceCenter&& other) = default; + + /// Update only some specific fields of a `ForceCenter`. + static ForceCenter update_fields() { + return ForceCenter(); + } + + /// Clear all the fields of a `ForceCenter`. + static ForceCenter clear_fields(); /// Whether the center force is enabled. /// /// The center force tries to move the center of mass of the graph towards the origin. - ForceCenter with_enabled(rerun::blueprint::components::Enabled _enabled) && { - enabled = std::move(_enabled); + ForceCenter with_enabled(const rerun::blueprint::components::Enabled& _enabled) && { + enabled = ComponentBatch::from_loggable(_enabled, Descriptor_enabled).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// The strength of the force. - ForceCenter with_strength(rerun::blueprint::components::ForceStrength _strength) && { - strength = std::move(_strength); + ForceCenter with_strength(const rerun::blueprint::components::ForceStrength& _strength) && { + strength = + ComponentBatch::from_loggable(_strength, Descriptor_strength).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } 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 1fd8539d8a547..447c1077bb0d4 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp @@ -5,7 +5,22 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ForceCollisionRadius ForceCollisionRadius::clear_fields() { + auto archetype = ForceCollisionRadius(); + archetype.enabled = + ComponentBatch::empty(Descriptor_enabled) + .value_or_throw(); + archetype.strength = + ComponentBatch::empty(Descriptor_strength) + .value_or_throw(); + archetype.iterations = ComponentBatch::empty( + Descriptor_iterations + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,40 +33,13 @@ namespace rerun { cells.reserve(4); if (archetype.enabled.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.enabled.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceCollisionRadius", - "enabled", - "rerun.blueprint.components.Enabled" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.enabled.value()); } if (archetype.strength.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.strength.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceCollisionRadius", - "strength", - "rerun.blueprint.components.ForceStrength" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.strength.value()); } if (archetype.iterations.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.iterations.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceCollisionRadius", - "iterations", - "rerun.blueprint.components.ForceIterations" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.iterations.value()); } { auto indicator = ForceCollisionRadius::IndicatorComponent(); 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 f51201ee8bd02..abcd2f1ebfac3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp @@ -23,15 +23,15 @@ namespace rerun::blueprint::archetypes { /// Whether the collision force is enabled. /// /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. - std::optional enabled; + std::optional enabled; /// The strength of the force. - std::optional strength; + std::optional strength; /// Specifies how often this force should be applied per iteration. /// /// Increasing this parameter can lead to better results at the cost of longer computation time. - std::optional iterations; + std::optional iterations; public: static constexpr const char IndicatorComponentName[] = @@ -39,24 +39,57 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = + "rerun.blueprint.archetypes.ForceCollisionRadius"; + + /// `ComponentDescriptor` for the `enabled` field. + static constexpr auto Descriptor_enabled = ComponentDescriptor( + ArchetypeName, "enabled", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `strength` field. + static constexpr auto Descriptor_strength = ComponentDescriptor( + ArchetypeName, "strength", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `iterations` field. + static constexpr auto Descriptor_iterations = ComponentDescriptor( + ArchetypeName, "iterations", + Loggable::Descriptor.component_name + ); public: ForceCollisionRadius() = default; ForceCollisionRadius(ForceCollisionRadius&& other) = default; + ForceCollisionRadius(const ForceCollisionRadius& other) = default; + ForceCollisionRadius& operator=(const ForceCollisionRadius& other) = default; + ForceCollisionRadius& operator=(ForceCollisionRadius&& other) = default; + + /// Update only some specific fields of a `ForceCollisionRadius`. + static ForceCollisionRadius update_fields() { + return ForceCollisionRadius(); + } + + /// Clear all the fields of a `ForceCollisionRadius`. + static ForceCollisionRadius clear_fields(); /// Whether the collision force is enabled. /// /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. - ForceCollisionRadius with_enabled(rerun::blueprint::components::Enabled _enabled) && { - enabled = std::move(_enabled); + ForceCollisionRadius with_enabled(const rerun::blueprint::components::Enabled& _enabled + ) && { + enabled = ComponentBatch::from_loggable(_enabled, Descriptor_enabled).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// The strength of the force. - ForceCollisionRadius with_strength(rerun::blueprint::components::ForceStrength _strength + ForceCollisionRadius with_strength( + const rerun::blueprint::components::ForceStrength& _strength ) && { - strength = std::move(_strength); + strength = + ComponentBatch::from_loggable(_strength, Descriptor_strength).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -65,9 +98,10 @@ namespace rerun::blueprint::archetypes { /// /// Increasing this parameter can lead to better results at the cost of longer computation time. ForceCollisionRadius with_iterations( - rerun::blueprint::components::ForceIterations _iterations + const rerun::blueprint::components::ForceIterations& _iterations ) && { - iterations = std::move(_iterations); + iterations = + ComponentBatch::from_loggable(_iterations, Descriptor_iterations).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp index 7cda317fa91be..59d086a65836c 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp @@ -5,7 +5,22 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ForceLink ForceLink::clear_fields() { + auto archetype = ForceLink(); + archetype.enabled = + ComponentBatch::empty(Descriptor_enabled) + .value_or_throw(); + archetype.distance = + ComponentBatch::empty(Descriptor_distance) + .value_or_throw(); + archetype.iterations = ComponentBatch::empty( + Descriptor_iterations + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,40 +32,13 @@ namespace rerun { cells.reserve(4); if (archetype.enabled.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.enabled.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceLink", - "enabled", - "rerun.blueprint.components.Enabled" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.enabled.value()); } if (archetype.distance.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.distance.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceLink", - "distance", - "rerun.blueprint.components.ForceDistance" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.distance.value()); } if (archetype.iterations.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.iterations.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceLink", - "iterations", - "rerun.blueprint.components.ForceIterations" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.iterations.value()); } { auto indicator = ForceLink::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp index b543152710b49..dbedc1fc1c0c5 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp @@ -23,15 +23,15 @@ namespace rerun::blueprint::archetypes { /// Whether the link force is enabled. /// /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. - std::optional enabled; + std::optional enabled; /// The target distance between two nodes. - std::optional distance; + std::optional distance; /// Specifies how often this force should be applied per iteration. /// /// Increasing this parameter can lead to better results at the cost of longer computation time. - std::optional iterations; + std::optional iterations; public: static constexpr const char IndicatorComponentName[] = @@ -39,23 +39,53 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ForceLink"; + + /// `ComponentDescriptor` for the `enabled` field. + static constexpr auto Descriptor_enabled = ComponentDescriptor( + ArchetypeName, "enabled", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `distance` field. + static constexpr auto Descriptor_distance = ComponentDescriptor( + ArchetypeName, "distance", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `iterations` field. + static constexpr auto Descriptor_iterations = ComponentDescriptor( + ArchetypeName, "iterations", + Loggable::Descriptor.component_name + ); public: ForceLink() = default; ForceLink(ForceLink&& other) = default; + ForceLink(const ForceLink& other) = default; + ForceLink& operator=(const ForceLink& other) = default; + ForceLink& operator=(ForceLink&& other) = default; + + /// Update only some specific fields of a `ForceLink`. + static ForceLink update_fields() { + return ForceLink(); + } + + /// Clear all the fields of a `ForceLink`. + static ForceLink clear_fields(); /// Whether the link force is enabled. /// /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. - ForceLink with_enabled(rerun::blueprint::components::Enabled _enabled) && { - enabled = std::move(_enabled); + ForceLink with_enabled(const rerun::blueprint::components::Enabled& _enabled) && { + enabled = ComponentBatch::from_loggable(_enabled, Descriptor_enabled).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// The target distance between two nodes. - ForceLink with_distance(rerun::blueprint::components::ForceDistance _distance) && { - distance = std::move(_distance); + ForceLink with_distance(const rerun::blueprint::components::ForceDistance& _distance) && { + distance = + ComponentBatch::from_loggable(_distance, Descriptor_distance).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -63,8 +93,10 @@ namespace rerun::blueprint::archetypes { /// Specifies how often this force should be applied per iteration. /// /// Increasing this parameter can lead to better results at the cost of longer computation time. - ForceLink with_iterations(rerun::blueprint::components::ForceIterations _iterations) && { - iterations = std::move(_iterations); + ForceLink with_iterations(const rerun::blueprint::components::ForceIterations& _iterations + ) && { + iterations = + ComponentBatch::from_loggable(_iterations, Descriptor_iterations).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } 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 58a115516b29f..757618c5c1f8b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp @@ -5,7 +5,18 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ForceManyBody ForceManyBody::clear_fields() { + auto archetype = ForceManyBody(); + archetype.enabled = + ComponentBatch::empty(Descriptor_enabled) + .value_or_throw(); + archetype.strength = + ComponentBatch::empty(Descriptor_strength) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,28 +29,10 @@ namespace rerun { cells.reserve(3); if (archetype.enabled.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.enabled.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceManyBody", - "enabled", - "rerun.blueprint.components.Enabled" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.enabled.value()); } if (archetype.strength.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.strength.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForceManyBody", - "strength", - "rerun.blueprint.components.ForceStrength" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.strength.value()); } { auto indicator = ForceManyBody::IndicatorComponent(); 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 9b0e2686745de..b5a6aad2aaf36 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp @@ -25,12 +25,12 @@ namespace rerun::blueprint::archetypes { /// /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. - std::optional enabled; + std::optional enabled; /// The strength of the force. /// /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. - std::optional strength; + std::optional strength; public: static constexpr const char IndicatorComponentName[] = @@ -38,17 +38,41 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ForceManyBody"; + + /// `ComponentDescriptor` for the `enabled` field. + static constexpr auto Descriptor_enabled = ComponentDescriptor( + ArchetypeName, "enabled", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `strength` field. + static constexpr auto Descriptor_strength = ComponentDescriptor( + ArchetypeName, "strength", + Loggable::Descriptor.component_name + ); public: ForceManyBody() = default; ForceManyBody(ForceManyBody&& other) = default; + ForceManyBody(const ForceManyBody& other) = default; + ForceManyBody& operator=(const ForceManyBody& other) = default; + ForceManyBody& operator=(ForceManyBody&& other) = default; + + /// Update only some specific fields of a `ForceManyBody`. + static ForceManyBody update_fields() { + return ForceManyBody(); + } + + /// Clear all the fields of a `ForceManyBody`. + static ForceManyBody clear_fields(); /// Whether the many body force is enabled. /// /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. - ForceManyBody with_enabled(rerun::blueprint::components::Enabled _enabled) && { - enabled = std::move(_enabled); + ForceManyBody with_enabled(const rerun::blueprint::components::Enabled& _enabled) && { + enabled = ComponentBatch::from_loggable(_enabled, Descriptor_enabled).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -56,8 +80,10 @@ namespace rerun::blueprint::archetypes { /// The strength of the force. /// /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. - ForceManyBody with_strength(rerun::blueprint::components::ForceStrength _strength) && { - strength = std::move(_strength); + ForceManyBody with_strength(const rerun::blueprint::components::ForceStrength& _strength + ) && { + strength = + ComponentBatch::from_loggable(_strength, Descriptor_strength).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp index d305426735135..45d7a0913db0e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp @@ -5,7 +5,21 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ForcePosition ForcePosition::clear_fields() { + auto archetype = ForcePosition(); + archetype.enabled = + ComponentBatch::empty(Descriptor_enabled) + .value_or_throw(); + archetype.strength = + ComponentBatch::empty(Descriptor_strength) + .value_or_throw(); + archetype.position = + ComponentBatch::empty(Descriptor_position) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,40 +32,13 @@ namespace rerun { cells.reserve(4); if (archetype.enabled.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.enabled.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForcePosition", - "enabled", - "rerun.blueprint.components.Enabled" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.enabled.value()); } if (archetype.strength.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.strength.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForcePosition", - "strength", - "rerun.blueprint.components.ForceStrength" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.strength.value()); } if (archetype.position.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.position.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ForcePosition", - "position", - "rerun.components.Position2D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.position.value()); } { auto indicator = ForcePosition::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp index 3c6fbf9d266bd..7f1b5fba8bfc6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp @@ -23,13 +23,13 @@ namespace rerun::blueprint::archetypes { /// Whether the position force is enabled. /// /// The position force pulls nodes towards a specific position, similar to gravity. - std::optional enabled; + std::optional enabled; /// The strength of the force. - std::optional strength; + std::optional strength; /// The position where the nodes should be pulled towards. - std::optional position; + std::optional position; public: static constexpr const char IndicatorComponentName[] = @@ -37,30 +37,62 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ForcePosition"; + + /// `ComponentDescriptor` for the `enabled` field. + static constexpr auto Descriptor_enabled = ComponentDescriptor( + ArchetypeName, "enabled", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `strength` field. + static constexpr auto Descriptor_strength = ComponentDescriptor( + ArchetypeName, "strength", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `position` field. + static constexpr auto Descriptor_position = ComponentDescriptor( + ArchetypeName, "position", + Loggable::Descriptor.component_name + ); public: ForcePosition() = default; ForcePosition(ForcePosition&& other) = default; + ForcePosition(const ForcePosition& other) = default; + ForcePosition& operator=(const ForcePosition& other) = default; + ForcePosition& operator=(ForcePosition&& other) = default; + + /// Update only some specific fields of a `ForcePosition`. + static ForcePosition update_fields() { + return ForcePosition(); + } + + /// Clear all the fields of a `ForcePosition`. + static ForcePosition clear_fields(); /// Whether the position force is enabled. /// /// The position force pulls nodes towards a specific position, similar to gravity. - ForcePosition with_enabled(rerun::blueprint::components::Enabled _enabled) && { - enabled = std::move(_enabled); + ForcePosition with_enabled(const rerun::blueprint::components::Enabled& _enabled) && { + enabled = ComponentBatch::from_loggable(_enabled, Descriptor_enabled).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// The strength of the force. - ForcePosition with_strength(rerun::blueprint::components::ForceStrength _strength) && { - strength = std::move(_strength); + ForcePosition with_strength(const rerun::blueprint::components::ForceStrength& _strength + ) && { + strength = + ComponentBatch::from_loggable(_strength, Descriptor_strength).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// The position where the nodes should be pulled towards. - ForcePosition with_position(rerun::components::Position2D _position) && { - position = std::move(_position); + ForcePosition with_position(const rerun::components::Position2D& _position) && { + position = + ComponentBatch::from_loggable(_position, Descriptor_position).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp index fffa50ee1e492..118023b1c9768 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.cpp @@ -5,7 +5,25 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + LineGrid3D LineGrid3D::clear_fields() { + auto archetype = LineGrid3D(); + archetype.visible = + ComponentBatch::empty(Descriptor_visible) + .value_or_throw(); + archetype.spacing = + ComponentBatch::empty(Descriptor_spacing) + .value_or_throw(); + archetype.plane = + ComponentBatch::empty(Descriptor_plane).value_or_throw(); + archetype.stroke_width = + ComponentBatch::empty(Descriptor_stroke_width) + .value_or_throw(); + archetype.color = + ComponentBatch::empty(Descriptor_color).value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,64 +35,19 @@ namespace rerun { cells.reserve(6); if (archetype.visible.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.visible.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.LineGrid3D", - "visible", - "rerun.blueprint.components.Visible" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.visible.value()); } if (archetype.spacing.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.spacing.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.LineGrid3D", - "spacing", - "rerun.blueprint.components.GridSpacing" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.spacing.value()); } if (archetype.plane.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.plane.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.LineGrid3D", - "plane", - "rerun.components.Plane3D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.plane.value()); } if (archetype.stroke_width.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.stroke_width.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.LineGrid3D", - "stroke_width", - "rerun.components.StrokeWidth" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.stroke_width.value()); } if (archetype.color.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.color.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.LineGrid3D", - "color", - "rerun.components.Color" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.color.value()); } { auto indicator = LineGrid3D::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp index 6cc5e342dc38e..acb414914d4b0 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/line_grid3d.hpp @@ -25,29 +25,29 @@ namespace rerun::blueprint::archetypes { /// Whether the grid is visible. /// /// Defaults to true. - std::optional visible; + std::optional visible; /// Space between grid lines spacing of one line to the next in scene units. /// /// As you zoom out, successively only every tenth line is shown. /// This controls the closest zoom level. - std::optional spacing; + std::optional spacing; /// In what plane the grid is drawn. /// /// Defaults to whatever plane is determined as the plane at zero units up/down as defined by `components::ViewCoordinates` if present. - std::optional plane; + std::optional plane; /// How thick the lines should be in ui units. /// /// Default is 1.0 ui unit. - std::optional stroke_width; + std::optional stroke_width; /// Color used for the grid. /// /// Transparency via alpha channel is supported. /// Defaults to a slightly transparent light gray. - std::optional color; + std::optional color; public: static constexpr const char IndicatorComponentName[] = @@ -55,16 +55,53 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.LineGrid3D"; + + /// `ComponentDescriptor` for the `visible` field. + static constexpr auto Descriptor_visible = ComponentDescriptor( + ArchetypeName, "visible", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `spacing` field. + static constexpr auto Descriptor_spacing = ComponentDescriptor( + ArchetypeName, "spacing", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `plane` field. + static constexpr auto Descriptor_plane = ComponentDescriptor( + ArchetypeName, "plane", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `stroke_width` field. + static constexpr auto Descriptor_stroke_width = ComponentDescriptor( + ArchetypeName, "stroke_width", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `color` field. + static constexpr auto Descriptor_color = ComponentDescriptor( + ArchetypeName, "color", Loggable::Descriptor.component_name + ); public: LineGrid3D() = default; LineGrid3D(LineGrid3D&& other) = default; + LineGrid3D(const LineGrid3D& other) = default; + LineGrid3D& operator=(const LineGrid3D& other) = default; + LineGrid3D& operator=(LineGrid3D&& other) = default; + + /// Update only some specific fields of a `LineGrid3D`. + static LineGrid3D update_fields() { + return LineGrid3D(); + } + + /// Clear all the fields of a `LineGrid3D`. + static LineGrid3D clear_fields(); /// Whether the grid is visible. /// /// Defaults to true. - LineGrid3D with_visible(rerun::blueprint::components::Visible _visible) && { - visible = std::move(_visible); + LineGrid3D with_visible(const rerun::blueprint::components::Visible& _visible) && { + visible = ComponentBatch::from_loggable(_visible, Descriptor_visible).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -73,8 +110,8 @@ namespace rerun::blueprint::archetypes { /// /// As you zoom out, successively only every tenth line is shown. /// This controls the closest zoom level. - LineGrid3D with_spacing(rerun::blueprint::components::GridSpacing _spacing) && { - spacing = std::move(_spacing); + LineGrid3D with_spacing(const rerun::blueprint::components::GridSpacing& _spacing) && { + spacing = ComponentBatch::from_loggable(_spacing, Descriptor_spacing).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -82,8 +119,8 @@ namespace rerun::blueprint::archetypes { /// In what plane the grid is drawn. /// /// Defaults to whatever plane is determined as the plane at zero units up/down as defined by `components::ViewCoordinates` if present. - LineGrid3D with_plane(rerun::components::Plane3D _plane) && { - plane = std::move(_plane); + LineGrid3D with_plane(const rerun::components::Plane3D& _plane) && { + plane = ComponentBatch::from_loggable(_plane, Descriptor_plane).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -91,8 +128,9 @@ namespace rerun::blueprint::archetypes { /// How thick the lines should be in ui units. /// /// Default is 1.0 ui unit. - LineGrid3D with_stroke_width(rerun::components::StrokeWidth _stroke_width) && { - stroke_width = std::move(_stroke_width); + LineGrid3D with_stroke_width(const rerun::components::StrokeWidth& _stroke_width) && { + stroke_width = ComponentBatch::from_loggable(_stroke_width, Descriptor_stroke_width) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -101,8 +139,8 @@ namespace rerun::blueprint::archetypes { /// /// Transparency via alpha channel is supported. /// Defaults to a slightly transparent light gray. - LineGrid3D with_color(rerun::components::Color _color) && { - color = std::move(_color); + LineGrid3D with_color(const rerun::components::Color& _color) && { + color = ComponentBatch::from_loggable(_color, Descriptor_color).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp index 47e424f3ea5f3..ac30cb43f8325 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + MapBackground MapBackground::clear_fields() { + auto archetype = MapBackground(); + archetype.provider = + ComponentBatch::empty(Descriptor_provider) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,17 +25,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.provider, - ComponentDescriptor( - "rerun.blueprint.archetypes.MapBackground", - "provider", - "rerun.blueprint.components.MapProvider" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.provider.has_value()) { + cells.push_back(archetype.provider.value()); } { auto indicator = MapBackground::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp index 3d63b252107f2..e2081f8e9f8d3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp @@ -5,11 +5,13 @@ #include "../../blueprint/components/map_provider.hpp" #include "../../collection.hpp" +#include "../../compiler_utils.hpp" #include "../../component_batch.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" #include +#include #include #include @@ -19,7 +21,7 @@ namespace rerun::blueprint::archetypes { /// Map provider and style to use. /// /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. - rerun::blueprint::components::MapProvider provider; + std::optional provider; public: static constexpr const char IndicatorComponentName[] = @@ -27,13 +29,43 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.MapBackground"; + + /// `ComponentDescriptor` for the `provider` field. + static constexpr auto Descriptor_provider = ComponentDescriptor( + ArchetypeName, "provider", + Loggable::Descriptor.component_name + ); public: MapBackground() = default; MapBackground(MapBackground&& other) = default; + MapBackground(const MapBackground& other) = default; + MapBackground& operator=(const MapBackground& other) = default; + MapBackground& operator=(MapBackground&& other) = default; explicit MapBackground(rerun::blueprint::components::MapProvider _provider) - : provider(std::move(_provider)) {} + : provider(ComponentBatch::from_loggable(std::move(_provider), Descriptor_provider) + .value_or_throw()) {} + + /// Update only some specific fields of a `MapBackground`. + static MapBackground update_fields() { + return MapBackground(); + } + + /// Clear all the fields of a `MapBackground`. + static MapBackground clear_fields(); + + /// Map provider and style to use. + /// + /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + MapBackground with_provider(const rerun::blueprint::components::MapProvider& _provider) && { + provider = + ComponentBatch::from_loggable(_provider, Descriptor_provider).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // 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 fa5393a4f11a5..66c72513058ee 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + MapZoom MapZoom::clear_fields() { + auto archetype = MapZoom(); + archetype.zoom = + ComponentBatch::empty(Descriptor_zoom) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -16,17 +24,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.zoom, - ComponentDescriptor( - "rerun.blueprint.archetypes.MapZoom", - "zoom", - "rerun.blueprint.components.ZoomLevel" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.zoom.has_value()) { + cells.push_back(archetype.zoom.value()); } { auto indicator = MapZoom::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp index 4c4b3a65901a4..d81d95ab23815 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp @@ -5,11 +5,13 @@ #include "../../blueprint/components/zoom_level.hpp" #include "../../collection.hpp" +#include "../../compiler_utils.hpp" #include "../../component_batch.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" #include +#include #include #include @@ -19,7 +21,7 @@ namespace rerun::blueprint::archetypes { /// Zoom level for the map. /// /// Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). - rerun::blueprint::components::ZoomLevel zoom; + std::optional zoom; public: static constexpr const char IndicatorComponentName[] = @@ -27,12 +29,42 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.MapZoom"; + + /// `ComponentDescriptor` for the `zoom` field. + static constexpr auto Descriptor_zoom = ComponentDescriptor( + ArchetypeName, "zoom", + Loggable::Descriptor.component_name + ); public: MapZoom() = default; MapZoom(MapZoom&& other) = default; + MapZoom(const MapZoom& other) = default; + MapZoom& operator=(const MapZoom& other) = default; + MapZoom& operator=(MapZoom&& other) = default; + + explicit MapZoom(rerun::blueprint::components::ZoomLevel _zoom) + : zoom(ComponentBatch::from_loggable(std::move(_zoom), Descriptor_zoom).value_or_throw() + ) {} + + /// Update only some specific fields of a `MapZoom`. + static MapZoom update_fields() { + return MapZoom(); + } - explicit MapZoom(rerun::blueprint::components::ZoomLevel _zoom) : zoom(std::move(_zoom)) {} + /// Clear all the fields of a `MapZoom`. + static MapZoom clear_fields(); + + /// Zoom level for the map. + /// + /// Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). + MapZoom with_zoom(const rerun::blueprint::components::ZoomLevel& _zoom) && { + zoom = ComponentBatch::from_loggable(_zoom, Descriptor_zoom).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // 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 2e16afb302abd..8957d6b381c26 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.cpp @@ -5,7 +5,17 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + NearClipPlane NearClipPlane::clear_fields() { + auto archetype = NearClipPlane(); + archetype.near_clip_plane = + ComponentBatch::empty( + Descriptor_near_clip_plane + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,17 +27,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.near_clip_plane, - ComponentDescriptor( - "rerun.blueprint.archetypes.NearClipPlane", - "near_clip_plane", - "rerun.blueprint.components.NearClipPlane" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.near_clip_plane.has_value()) { + cells.push_back(archetype.near_clip_plane.value()); } { auto indicator = NearClipPlane::IndicatorComponent(); 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 b01dee338d3cb..91bda2234be83 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/near_clip_plane.hpp @@ -5,11 +5,13 @@ #include "../../blueprint/components/near_clip_plane.hpp" #include "../../collection.hpp" +#include "../../compiler_utils.hpp" #include "../../component_batch.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" #include +#include #include #include @@ -19,7 +21,7 @@ namespace rerun::blueprint::archetypes { /// Controls the distance to the near clip plane in 3D scene units. /// /// Content closer than this distance will not be visible. - rerun::blueprint::components::NearClipPlane near_clip_plane; + std::optional near_clip_plane; public: static constexpr const char IndicatorComponentName[] = @@ -27,13 +29,48 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.NearClipPlane"; + + /// `ComponentDescriptor` for the `near_clip_plane` field. + static constexpr auto Descriptor_near_clip_plane = ComponentDescriptor( + ArchetypeName, "near_clip_plane", + Loggable::Descriptor.component_name + ); public: NearClipPlane() = default; NearClipPlane(NearClipPlane&& other) = default; + NearClipPlane(const NearClipPlane& other) = default; + NearClipPlane& operator=(const NearClipPlane& other) = default; + NearClipPlane& operator=(NearClipPlane&& other) = default; explicit NearClipPlane(rerun::blueprint::components::NearClipPlane _near_clip_plane) - : near_clip_plane(std::move(_near_clip_plane)) {} + : near_clip_plane(ComponentBatch::from_loggable( + std::move(_near_clip_plane), Descriptor_near_clip_plane + ) + .value_or_throw()) {} + + /// Update only some specific fields of a `NearClipPlane`. + static NearClipPlane update_fields() { + return NearClipPlane(); + } + + /// Clear all the fields of a `NearClipPlane`. + static NearClipPlane clear_fields(); + + /// Controls the distance to the near clip plane in 3D scene units. + /// + /// Content closer than this distance will not be visible. + NearClipPlane with_near_clip_plane( + const rerun::blueprint::components::NearClipPlane& _near_clip_plane + ) && { + near_clip_plane = + ComponentBatch::from_loggable(_near_clip_plane, Descriptor_near_clip_plane) + .value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // 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 9a1167cd7efd9..fb44e43b22b7b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + PanelBlueprint PanelBlueprint::clear_fields() { + auto archetype = PanelBlueprint(); + archetype.state = + ComponentBatch::empty(Descriptor_state) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,16 +26,7 @@ namespace rerun { cells.reserve(2); if (archetype.state.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.state.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.PanelBlueprint", - "state", - "rerun.blueprint.components.PanelState" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.state.value()); } { auto indicator = PanelBlueprint::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp index 79c674928cfa7..7dbc740044dd3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp @@ -19,7 +19,7 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Shared state for the 3 collapsible panels. struct PanelBlueprint { /// Current state of the panels. - std::optional state; + std::optional state; public: static constexpr const char IndicatorComponentName[] = @@ -27,14 +27,33 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.PanelBlueprint"; + + /// `ComponentDescriptor` for the `state` field. + static constexpr auto Descriptor_state = ComponentDescriptor( + ArchetypeName, "state", + Loggable::Descriptor.component_name + ); public: PanelBlueprint() = default; PanelBlueprint(PanelBlueprint&& other) = default; + PanelBlueprint(const PanelBlueprint& other) = default; + PanelBlueprint& operator=(const PanelBlueprint& other) = default; + PanelBlueprint& operator=(PanelBlueprint&& other) = default; + + /// Update only some specific fields of a `PanelBlueprint`. + static PanelBlueprint update_fields() { + return PanelBlueprint(); + } + + /// Clear all the fields of a `PanelBlueprint`. + static PanelBlueprint clear_fields(); /// Current state of the panels. - PanelBlueprint with_state(rerun::blueprint::components::PanelState _state) && { - state = std::move(_state); + PanelBlueprint with_state(const rerun::blueprint::components::PanelState& _state) && { + state = ComponentBatch::from_loggable(_state, Descriptor_state).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp index 9533c1371c0ba..933e6549842fb 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.cpp @@ -5,7 +5,18 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + PlotLegend PlotLegend::clear_fields() { + auto archetype = PlotLegend(); + archetype.corner = + ComponentBatch::empty(Descriptor_corner) + .value_or_throw(); + archetype.visible = + ComponentBatch::empty(Descriptor_visible) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,28 +28,10 @@ namespace rerun { cells.reserve(3); if (archetype.corner.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.corner.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.PlotLegend", - "corner", - "rerun.blueprint.components.Corner2D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.corner.value()); } if (archetype.visible.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.visible.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.PlotLegend", - "visible", - "rerun.blueprint.components.Visible" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.visible.value()); } { auto indicator = PlotLegend::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp index 64ec599076079..8c34e1420e5bd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp @@ -22,12 +22,12 @@ namespace rerun::blueprint::archetypes { /// To what corner the legend is aligned. /// /// Defaults to the right bottom corner. - std::optional corner; + std::optional corner; /// Whether the legend is shown at all. /// /// True by default. - std::optional visible; + std::optional visible; public: static constexpr const char IndicatorComponentName[] = @@ -35,16 +35,40 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.PlotLegend"; + + /// `ComponentDescriptor` for the `corner` field. + static constexpr auto Descriptor_corner = ComponentDescriptor( + ArchetypeName, "corner", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `visible` field. + static constexpr auto Descriptor_visible = ComponentDescriptor( + ArchetypeName, "visible", + Loggable::Descriptor.component_name + ); public: PlotLegend() = default; PlotLegend(PlotLegend&& other) = default; + PlotLegend(const PlotLegend& other) = default; + PlotLegend& operator=(const PlotLegend& other) = default; + PlotLegend& operator=(PlotLegend&& other) = default; + + /// Update only some specific fields of a `PlotLegend`. + static PlotLegend update_fields() { + return PlotLegend(); + } + + /// Clear all the fields of a `PlotLegend`. + static PlotLegend clear_fields(); /// To what corner the legend is aligned. /// /// Defaults to the right bottom corner. - PlotLegend with_corner(rerun::blueprint::components::Corner2D _corner) && { - corner = std::move(_corner); + PlotLegend with_corner(const rerun::blueprint::components::Corner2D& _corner) && { + corner = ComponentBatch::from_loggable(_corner, Descriptor_corner).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -52,8 +76,8 @@ namespace rerun::blueprint::archetypes { /// Whether the legend is shown at all. /// /// True by default. - PlotLegend with_visible(rerun::blueprint::components::Visible _visible) && { - visible = std::move(_visible); + PlotLegend with_visible(const rerun::blueprint::components::Visible& _visible) && { + visible = ComponentBatch::from_loggable(_visible, Descriptor_visible).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp index da9db9ccec3a6..f7f54d449aa5a 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.cpp @@ -5,7 +5,19 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ScalarAxis ScalarAxis::clear_fields() { + auto archetype = ScalarAxis(); + archetype.range = + ComponentBatch::empty(Descriptor_range).value_or_throw(); + archetype.zoom_lock = + ComponentBatch::empty( + Descriptor_zoom_lock + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,28 +29,10 @@ namespace rerun { cells.reserve(3); if (archetype.range.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.range.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ScalarAxis", - "range", - "rerun.components.Range1D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.range.value()); } if (archetype.zoom_lock.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.zoom_lock.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ScalarAxis", - "zoom_lock", - "rerun.blueprint.components.LockRangeDuringZoom" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.zoom_lock.value()); } { auto indicator = ScalarAxis::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp index d04cd46376e97..b56c95b4797f5 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp @@ -22,10 +22,10 @@ namespace rerun::blueprint::archetypes { /// The range of the axis. /// /// If unset, the range well be automatically determined based on the queried data. - std::optional range; + std::optional range; /// If enabled, the Y axis range will remain locked to the specified range when zooming. - std::optional zoom_lock; + std::optional zoom_lock; public: static constexpr const char IndicatorComponentName[] = @@ -33,23 +33,49 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ScalarAxis"; + + /// `ComponentDescriptor` for the `range` field. + static constexpr auto Descriptor_range = ComponentDescriptor( + ArchetypeName, "range", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `zoom_lock` field. + static constexpr auto Descriptor_zoom_lock = ComponentDescriptor( + ArchetypeName, "zoom_lock", + Loggable::Descriptor.component_name + ); public: ScalarAxis() = default; ScalarAxis(ScalarAxis&& other) = default; + ScalarAxis(const ScalarAxis& other) = default; + ScalarAxis& operator=(const ScalarAxis& other) = default; + ScalarAxis& operator=(ScalarAxis&& other) = default; + + /// Update only some specific fields of a `ScalarAxis`. + static ScalarAxis update_fields() { + return ScalarAxis(); + } + + /// Clear all the fields of a `ScalarAxis`. + static ScalarAxis clear_fields(); /// The range of the axis. /// /// If unset, the range well be automatically determined based on the queried data. - ScalarAxis with_range(rerun::components::Range1D _range) && { - range = std::move(_range); + ScalarAxis with_range(const rerun::components::Range1D& _range) && { + range = ComponentBatch::from_loggable(_range, Descriptor_range).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// If enabled, the Y axis range will remain locked to the specified range when zooming. - ScalarAxis with_zoom_lock(rerun::blueprint::components::LockRangeDuringZoom _zoom_lock) && { - zoom_lock = std::move(_zoom_lock); + ScalarAxis with_zoom_lock( + const rerun::blueprint::components::LockRangeDuringZoom& _zoom_lock + ) && { + zoom_lock = + ComponentBatch::from_loggable(_zoom_lock, Descriptor_zoom_lock).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } 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 c5cfdb3193735..3ee67b908f17d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.cpp @@ -5,7 +5,20 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + TensorScalarMapping TensorScalarMapping::clear_fields() { + auto archetype = TensorScalarMapping(); + archetype.mag_filter = + ComponentBatch::empty(Descriptor_mag_filter) + .value_or_throw(); + archetype.colormap = ComponentBatch::empty(Descriptor_colormap) + .value_or_throw(); + archetype.gamma = + ComponentBatch::empty(Descriptor_gamma) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,40 +31,13 @@ namespace rerun { cells.reserve(4); if (archetype.mag_filter.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.mag_filter.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorScalarMapping", - "mag_filter", - "rerun.components.MagnificationFilter" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.mag_filter.value()); } if (archetype.colormap.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.colormap.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorScalarMapping", - "colormap", - "rerun.components.Colormap" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.colormap.value()); } if (archetype.gamma.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.gamma.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorScalarMapping", - "gamma", - "rerun.components.GammaCorrection" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.gamma.value()); } { auto indicator = TensorScalarMapping::IndicatorComponent(); 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 4f85781fefec9..073b6cb836ecf 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_scalar_mapping.hpp @@ -23,10 +23,10 @@ namespace rerun::blueprint::archetypes { /// Filter used when zooming in on the tensor. /// /// Note that the filter is applied to the scalar values *before* they are mapped to color. - std::optional mag_filter; + std::optional mag_filter; /// How scalar values map to colors. - std::optional colormap; + std::optional colormap; /// Gamma exponent applied to normalized values before mapping to color. /// @@ -35,7 +35,7 @@ namespace rerun::blueprint::archetypes { /// /// The final value for display is set as: /// `colormap( ((value - data_display_range.min) / (data_display_range.max - data_display_range.min)) ** gamma )` - std::optional gamma; + std::optional gamma; public: static constexpr const char IndicatorComponentName[] = @@ -43,23 +43,57 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = + "rerun.blueprint.archetypes.TensorScalarMapping"; + + /// `ComponentDescriptor` for the `mag_filter` field. + static constexpr auto Descriptor_mag_filter = ComponentDescriptor( + ArchetypeName, "mag_filter", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `colormap` field. + static constexpr auto Descriptor_colormap = ComponentDescriptor( + ArchetypeName, "colormap", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `gamma` field. + static constexpr auto Descriptor_gamma = ComponentDescriptor( + ArchetypeName, "gamma", + Loggable::Descriptor.component_name + ); public: TensorScalarMapping() = default; TensorScalarMapping(TensorScalarMapping&& other) = default; + TensorScalarMapping(const TensorScalarMapping& other) = default; + TensorScalarMapping& operator=(const TensorScalarMapping& other) = default; + TensorScalarMapping& operator=(TensorScalarMapping&& other) = default; + + /// Update only some specific fields of a `TensorScalarMapping`. + static TensorScalarMapping update_fields() { + return TensorScalarMapping(); + } + + /// Clear all the fields of a `TensorScalarMapping`. + static TensorScalarMapping clear_fields(); /// Filter used when zooming in on the tensor. /// /// Note that the filter is applied to the scalar values *before* they are mapped to color. - TensorScalarMapping with_mag_filter(rerun::components::MagnificationFilter _mag_filter) && { - mag_filter = std::move(_mag_filter); + TensorScalarMapping with_mag_filter( + const rerun::components::MagnificationFilter& _mag_filter + ) && { + mag_filter = + ComponentBatch::from_loggable(_mag_filter, Descriptor_mag_filter).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// How scalar values map to colors. - TensorScalarMapping with_colormap(rerun::components::Colormap _colormap) && { - colormap = std::move(_colormap); + TensorScalarMapping with_colormap(const rerun::components::Colormap& _colormap) && { + colormap = + ComponentBatch::from_loggable(_colormap, Descriptor_colormap).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -71,8 +105,8 @@ namespace rerun::blueprint::archetypes { /// /// The final value for display is set as: /// `colormap( ((value - data_display_range.min) / (data_display_range.max - data_display_range.min)) ** gamma )` - TensorScalarMapping with_gamma(rerun::components::GammaCorrection _gamma) && { - gamma = std::move(_gamma); + TensorScalarMapping with_gamma(const rerun::components::GammaCorrection& _gamma) && { + gamma = ComponentBatch::from_loggable(_gamma, Descriptor_gamma).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } 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 59de883f0b2cf..48bffb17840f3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.cpp @@ -5,7 +5,27 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + TensorSliceSelection TensorSliceSelection::clear_fields() { + auto archetype = TensorSliceSelection(); + archetype.width = + ComponentBatch::empty(Descriptor_width) + .value_or_throw(); + archetype.height = + ComponentBatch::empty(Descriptor_height) + .value_or_throw(); + archetype.indices = ComponentBatch::empty( + Descriptor_indices + ) + .value_or_throw(); + archetype.slider = + ComponentBatch::empty( + Descriptor_slider + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,52 +38,16 @@ namespace rerun { cells.reserve(5); if (archetype.width.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.width.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorSliceSelection", - "width", - "rerun.components.TensorWidthDimension" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.width.value()); } if (archetype.height.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.height.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorSliceSelection", - "height", - "rerun.components.TensorHeightDimension" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.height.value()); } if (archetype.indices.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.indices.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorSliceSelection", - "indices", - "rerun.components.TensorDimensionIndexSelection" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.indices.value()); } if (archetype.slider.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.slider.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorSliceSelection", - "slider", - "rerun.blueprint.components.TensorDimensionIndexSlider" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.slider.value()); } { auto indicator = TensorSliceSelection::IndicatorComponent(); 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 37c63ae59b752..7bc6615c607f6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_slice_selection.hpp @@ -24,24 +24,24 @@ namespace rerun::blueprint::archetypes { /// Which dimension to map to width. /// /// If not specified, the height will be determined automatically based on the name and index of the dimension. - std::optional width; + std::optional width; /// Which dimension to map to height. /// /// If not specified, the height will be determined automatically based on the name and index of the dimension. - std::optional height; + std::optional height; /// Selected indices for all other dimensions. /// /// If any of the here listed dimensions is equal to `width` or `height`, it will be ignored. - std::optional> indices; + std::optional indices; /// Any dimension listed here will have a slider for the index. /// /// Edits to the sliders will directly manipulate dimensions on the `indices` list. /// If any of the here listed dimensions is equal to `width` or `height`, it will be ignored. /// If not specified, adds slides for any dimension in `indices`. - std::optional> slider; + std::optional slider; public: static constexpr const char IndicatorComponentName[] = @@ -49,16 +49,52 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = + "rerun.blueprint.archetypes.TensorSliceSelection"; + + /// `ComponentDescriptor` for the `width` field. + static constexpr auto Descriptor_width = ComponentDescriptor( + ArchetypeName, "width", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `height` field. + static constexpr auto Descriptor_height = ComponentDescriptor( + ArchetypeName, "height", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `indices` field. + static constexpr auto Descriptor_indices = ComponentDescriptor( + ArchetypeName, "indices", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `slider` field. + static constexpr auto Descriptor_slider = ComponentDescriptor( + ArchetypeName, "slider", + Loggable::Descriptor + .component_name + ); public: TensorSliceSelection() = default; TensorSliceSelection(TensorSliceSelection&& other) = default; + TensorSliceSelection(const TensorSliceSelection& other) = default; + TensorSliceSelection& operator=(const TensorSliceSelection& other) = default; + TensorSliceSelection& operator=(TensorSliceSelection&& other) = default; + + /// Update only some specific fields of a `TensorSliceSelection`. + static TensorSliceSelection update_fields() { + return TensorSliceSelection(); + } + + /// Clear all the fields of a `TensorSliceSelection`. + static TensorSliceSelection clear_fields(); /// Which dimension to map to width. /// /// If not specified, the height will be determined automatically based on the name and index of the dimension. - TensorSliceSelection with_width(rerun::components::TensorWidthDimension _width) && { - width = std::move(_width); + TensorSliceSelection with_width(const rerun::components::TensorWidthDimension& _width) && { + width = ComponentBatch::from_loggable(_width, Descriptor_width).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -66,8 +102,9 @@ namespace rerun::blueprint::archetypes { /// Which dimension to map to height. /// /// If not specified, the height will be determined automatically based on the name and index of the dimension. - TensorSliceSelection with_height(rerun::components::TensorHeightDimension _height) && { - height = std::move(_height); + TensorSliceSelection with_height(const rerun::components::TensorHeightDimension& _height + ) && { + height = ComponentBatch::from_loggable(_height, Descriptor_height).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -76,9 +113,9 @@ namespace rerun::blueprint::archetypes { /// /// If any of the here listed dimensions is equal to `width` or `height`, it will be ignored. TensorSliceSelection with_indices( - Collection _indices + const Collection& _indices ) && { - indices = std::move(_indices); + indices = ComponentBatch::from_loggable(_indices, Descriptor_indices).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -89,9 +126,9 @@ namespace rerun::blueprint::archetypes { /// If any of the here listed dimensions is equal to `width` or `height`, it will be ignored. /// If not specified, adds slides for any dimension in `indices`. TensorSliceSelection with_slider( - Collection _slider + const Collection& _slider ) && { - slider = std::move(_slider); + slider = ComponentBatch::from_loggable(_slider, Descriptor_slider).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } 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 0cd0674ea46da..d9930607253ea 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + TensorViewFit TensorViewFit::clear_fields() { + auto archetype = TensorViewFit(); + archetype.scaling = + ComponentBatch::empty(Descriptor_scaling) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,16 +26,7 @@ namespace rerun { cells.reserve(2); if (archetype.scaling.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.scaling.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.TensorViewFit", - "scaling", - "rerun.blueprint.components.ViewFit" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.scaling.value()); } { auto indicator = TensorViewFit::IndicatorComponent(); 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 059925a958459..1ad22cc3ce090 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/tensor_view_fit.hpp @@ -19,7 +19,7 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Configures how a selected tensor slice is shown on screen. struct TensorViewFit { /// How the image is scaled to fit the view. - std::optional scaling; + std::optional scaling; public: static constexpr const char IndicatorComponentName[] = @@ -27,14 +27,33 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.TensorViewFit"; + + /// `ComponentDescriptor` for the `scaling` field. + static constexpr auto Descriptor_scaling = ComponentDescriptor( + ArchetypeName, "scaling", + Loggable::Descriptor.component_name + ); public: TensorViewFit() = default; TensorViewFit(TensorViewFit&& other) = default; + TensorViewFit(const TensorViewFit& other) = default; + TensorViewFit& operator=(const TensorViewFit& other) = default; + TensorViewFit& operator=(TensorViewFit&& other) = default; + + /// Update only some specific fields of a `TensorViewFit`. + static TensorViewFit update_fields() { + return TensorViewFit(); + } + + /// Clear all the fields of a `TensorViewFit`. + static TensorViewFit clear_fields(); /// How the image is scaled to fit the view. - TensorViewFit with_scaling(rerun::blueprint::components::ViewFit _scaling) && { - scaling = std::move(_scaling); + TensorViewFit with_scaling(const rerun::blueprint::components::ViewFit& _scaling) && { + scaling = ComponentBatch::from_loggable(_scaling, Descriptor_scaling).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp index 4ce5f6614fe79..69f88044b52bf 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.cpp @@ -5,7 +5,25 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ViewBlueprint ViewBlueprint::clear_fields() { + auto archetype = ViewBlueprint(); + archetype.class_identifier = ComponentBatch::empty( + Descriptor_class_identifier + ) + .value_or_throw(); + archetype.display_name = + ComponentBatch::empty(Descriptor_display_name) + .value_or_throw(); + archetype.space_origin = + ComponentBatch::empty(Descriptor_space_origin) + .value_or_throw(); + archetype.visible = + ComponentBatch::empty(Descriptor_visible) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,53 +35,17 @@ namespace rerun { std::vector cells; cells.reserve(5); - { - auto result = ComponentBatch::from_loggable( - archetype.class_identifier, - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewBlueprint", - "class_identifier", - "rerun.blueprint.components.ViewClass" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.class_identifier.has_value()) { + cells.push_back(archetype.class_identifier.value()); } if (archetype.display_name.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.display_name.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewBlueprint", - "display_name", - "rerun.components.Name" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.display_name.value()); } if (archetype.space_origin.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.space_origin.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewBlueprint", - "space_origin", - "rerun.blueprint.components.ViewOrigin" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.space_origin.value()); } if (archetype.visible.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.visible.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewBlueprint", - "visible", - "rerun.blueprint.components.Visible" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.visible.value()); } { auto indicator = ViewBlueprint::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp index b01bf69b239e5..dfe535379bf83 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_blueprint.hpp @@ -22,10 +22,10 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: The description of a single view. struct ViewBlueprint { /// The class of the view. - rerun::blueprint::components::ViewClass class_identifier; + std::optional class_identifier; /// The name of the view. - std::optional display_name; + std::optional display_name; /// The "anchor point" of this view. /// @@ -34,12 +34,12 @@ namespace rerun::blueprint::archetypes { /// The transform at this path forms the reference point for all scene->world transforms in this view. /// I.e. the position of this entity path in space forms the origin of the coordinate system in this view. /// Furthermore, this is the primary indicator for heuristics on what entities we show in this view. - std::optional space_origin; + std::optional space_origin; /// Whether this view is visible. /// /// Defaults to true if not specified. - std::optional visible; + std::optional visible; public: static constexpr const char IndicatorComponentName[] = @@ -47,17 +47,66 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ViewBlueprint"; + + /// `ComponentDescriptor` for the `class_identifier` field. + static constexpr auto Descriptor_class_identifier = ComponentDescriptor( + ArchetypeName, "class_identifier", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `display_name` field. + static constexpr auto Descriptor_display_name = ComponentDescriptor( + ArchetypeName, "display_name", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `space_origin` field. + static constexpr auto Descriptor_space_origin = ComponentDescriptor( + ArchetypeName, "space_origin", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `visible` field. + static constexpr auto Descriptor_visible = ComponentDescriptor( + ArchetypeName, "visible", + Loggable::Descriptor.component_name + ); public: ViewBlueprint() = default; ViewBlueprint(ViewBlueprint&& other) = default; + ViewBlueprint(const ViewBlueprint& other) = default; + ViewBlueprint& operator=(const ViewBlueprint& other) = default; + ViewBlueprint& operator=(ViewBlueprint&& other) = default; explicit ViewBlueprint(rerun::blueprint::components::ViewClass _class_identifier) - : class_identifier(std::move(_class_identifier)) {} + : class_identifier(ComponentBatch::from_loggable( + std::move(_class_identifier), Descriptor_class_identifier + ) + .value_or_throw()) {} + + /// Update only some specific fields of a `ViewBlueprint`. + static ViewBlueprint update_fields() { + return ViewBlueprint(); + } + + /// Clear all the fields of a `ViewBlueprint`. + static ViewBlueprint clear_fields(); + + /// The class of the view. + ViewBlueprint with_class_identifier( + const rerun::blueprint::components::ViewClass& _class_identifier + ) && { + class_identifier = + ComponentBatch::from_loggable(_class_identifier, Descriptor_class_identifier) + .value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// The name of the view. - ViewBlueprint with_display_name(rerun::components::Name _display_name) && { - display_name = std::move(_display_name); + ViewBlueprint with_display_name(const rerun::components::Name& _display_name) && { + display_name = ComponentBatch::from_loggable(_display_name, Descriptor_display_name) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -69,8 +118,11 @@ namespace rerun::blueprint::archetypes { /// The transform at this path forms the reference point for all scene->world transforms in this view. /// I.e. the position of this entity path in space forms the origin of the coordinate system in this view. /// Furthermore, this is the primary indicator for heuristics on what entities we show in this view. - ViewBlueprint with_space_origin(rerun::blueprint::components::ViewOrigin _space_origin) && { - space_origin = std::move(_space_origin); + ViewBlueprint with_space_origin( + const rerun::blueprint::components::ViewOrigin& _space_origin + ) && { + space_origin = ComponentBatch::from_loggable(_space_origin, Descriptor_space_origin) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -78,8 +130,8 @@ namespace rerun::blueprint::archetypes { /// Whether this view is visible. /// /// Defaults to true if not specified. - ViewBlueprint with_visible(rerun::blueprint::components::Visible _visible) && { - visible = std::move(_visible); + ViewBlueprint with_visible(const rerun::blueprint::components::Visible& _visible) && { + visible = ComponentBatch::from_loggable(_visible, Descriptor_visible).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp index 4a506dfae983c..1350503bbe04c 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ViewContents ViewContents::clear_fields() { + auto archetype = ViewContents(); + archetype.query = + ComponentBatch::empty(Descriptor_query) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,17 +25,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.query, - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewContents", - "query", - "rerun.blueprint.components.QueryExpression" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.query.has_value()) { + cells.push_back(archetype.query.value()); } { auto indicator = ViewContents::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp index 82f4b01d36e3d..a3dbac0184ce3 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/view_contents.hpp @@ -5,11 +5,13 @@ #include "../../blueprint/components/query_expression.hpp" #include "../../collection.hpp" +#include "../../compiler_utils.hpp" #include "../../component_batch.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" #include +#include #include #include @@ -56,7 +58,7 @@ namespace rerun::blueprint::archetypes { /// The `QueryExpression` that populates the contents for the view. /// /// They determine which entities are part of the view. - Collection query; + std::optional query; public: static constexpr const char IndicatorComponentName[] = @@ -64,13 +66,44 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.ViewContents"; + + /// `ComponentDescriptor` for the `query` field. + static constexpr auto Descriptor_query = ComponentDescriptor( + ArchetypeName, "query", + Loggable::Descriptor.component_name + ); public: ViewContents() = default; ViewContents(ViewContents&& other) = default; + ViewContents(const ViewContents& other) = default; + ViewContents& operator=(const ViewContents& other) = default; + ViewContents& operator=(ViewContents&& other) = default; explicit ViewContents(Collection _query) - : query(std::move(_query)) {} + : query(ComponentBatch::from_loggable(std::move(_query), Descriptor_query) + .value_or_throw()) {} + + /// Update only some specific fields of a `ViewContents`. + static ViewContents update_fields() { + return ViewContents(); + } + + /// Clear all the fields of a `ViewContents`. + static ViewContents clear_fields(); + + /// The `QueryExpression` that populates the contents for the view. + /// + /// They determine which entities are part of the view. + ViewContents with_query( + const Collection& _query + ) && { + query = ComponentBatch::from_loggable(_query, Descriptor_query).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // 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 40accef09eb8a..547d9b7ddf229 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp @@ -5,7 +5,31 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + ViewportBlueprint ViewportBlueprint::clear_fields() { + auto archetype = ViewportBlueprint(); + archetype.root_container = + ComponentBatch::empty( + Descriptor_root_container + ) + .value_or_throw(); + archetype.maximized = + ComponentBatch::empty(Descriptor_maximized) + .value_or_throw(); + archetype.auto_layout = + ComponentBatch::empty(Descriptor_auto_layout) + .value_or_throw(); + archetype.auto_views = + ComponentBatch::empty(Descriptor_auto_views) + .value_or_throw(); + archetype.past_viewer_recommendations = + ComponentBatch::empty( + Descriptor_past_viewer_recommendations + ) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -18,64 +42,19 @@ namespace rerun { cells.reserve(6); if (archetype.root_container.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.root_container.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewportBlueprint", - "root_container", - "rerun.blueprint.components.RootContainer" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.root_container.value()); } if (archetype.maximized.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.maximized.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewportBlueprint", - "maximized", - "rerun.blueprint.components.ViewMaximized" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.maximized.value()); } if (archetype.auto_layout.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.auto_layout.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewportBlueprint", - "auto_layout", - "rerun.blueprint.components.AutoLayout" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.auto_layout.value()); } if (archetype.auto_views.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.auto_views.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewportBlueprint", - "auto_views", - "rerun.blueprint.components.AutoViews" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.auto_views.value()); } if (archetype.past_viewer_recommendations.has_value()) { - auto result = ComponentBatch::from_loggable( - archetype.past_viewer_recommendations.value(), - ComponentDescriptor( - "rerun.blueprint.archetypes.ViewportBlueprint", - "past_viewer_recommendations", - "rerun.blueprint.components.ViewerRecommendationHash" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + cells.push_back(archetype.past_viewer_recommendations.value()); } { auto indicator = ViewportBlueprint::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp index ab43837facf76..cf89e006fdcac 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp @@ -23,23 +23,23 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: The top-level description of the viewport. struct ViewportBlueprint { /// The layout of the views - std::optional root_container; + std::optional root_container; /// Show one tab as maximized? - std::optional maximized; + std::optional maximized; /// Whether the viewport layout is determined automatically. /// /// If `true`, the container layout will be reset whenever a new view is added or removed. /// This defaults to `false` and is automatically set to `false` when there is user determined layout. - std::optional auto_layout; + std::optional auto_layout; /// Whether or not views should be created automatically. /// /// If `true`, the viewer will only add views that it hasn't considered previously (as identified by `past_viewer_recommendations`) /// and which aren't deemed redundant to existing views. /// This defaults to `false` and is automatically set to `false` when the user adds views manually in the viewer. - std::optional auto_views; + std::optional auto_views; /// Hashes of all recommended views the viewer has already added and that should not be added again. /// @@ -47,8 +47,7 @@ namespace rerun::blueprint::archetypes { /// If you want the viewer from stopping to add views, you should set `auto_views` to `false`. /// /// The viewer uses this to determine whether it should keep adding views. - std::optional> - past_viewer_recommendations; + std::optional past_viewer_recommendations; public: static constexpr const char IndicatorComponentName[] = @@ -56,24 +55,69 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = + "rerun.blueprint.archetypes.ViewportBlueprint"; + + /// `ComponentDescriptor` for the `root_container` field. + static constexpr auto Descriptor_root_container = ComponentDescriptor( + ArchetypeName, "root_container", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `maximized` field. + static constexpr auto Descriptor_maximized = ComponentDescriptor( + ArchetypeName, "maximized", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `auto_layout` field. + static constexpr auto Descriptor_auto_layout = ComponentDescriptor( + ArchetypeName, "auto_layout", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `auto_views` field. + static constexpr auto Descriptor_auto_views = ComponentDescriptor( + ArchetypeName, "auto_views", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `past_viewer_recommendations` field. + static constexpr auto Descriptor_past_viewer_recommendations = ComponentDescriptor( + ArchetypeName, "past_viewer_recommendations", + Loggable::Descriptor + .component_name + ); public: ViewportBlueprint() = default; ViewportBlueprint(ViewportBlueprint&& other) = default; + ViewportBlueprint(const ViewportBlueprint& other) = default; + ViewportBlueprint& operator=(const ViewportBlueprint& other) = default; + ViewportBlueprint& operator=(ViewportBlueprint&& other) = default; + + /// Update only some specific fields of a `ViewportBlueprint`. + static ViewportBlueprint update_fields() { + return ViewportBlueprint(); + } + + /// Clear all the fields of a `ViewportBlueprint`. + static ViewportBlueprint clear_fields(); /// The layout of the views ViewportBlueprint with_root_container( - rerun::blueprint::components::RootContainer _root_container + const rerun::blueprint::components::RootContainer& _root_container ) && { - root_container = std::move(_root_container); + root_container = + ComponentBatch::from_loggable(_root_container, Descriptor_root_container) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } /// Show one tab as maximized? - ViewportBlueprint with_maximized(rerun::blueprint::components::ViewMaximized _maximized + ViewportBlueprint with_maximized( + const rerun::blueprint::components::ViewMaximized& _maximized ) && { - maximized = std::move(_maximized); + maximized = + ComponentBatch::from_loggable(_maximized, Descriptor_maximized).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -82,9 +126,11 @@ namespace rerun::blueprint::archetypes { /// /// If `true`, the container layout will be reset whenever a new view is added or removed. /// This defaults to `false` and is automatically set to `false` when there is user determined layout. - ViewportBlueprint with_auto_layout(rerun::blueprint::components::AutoLayout _auto_layout + ViewportBlueprint with_auto_layout( + const rerun::blueprint::components::AutoLayout& _auto_layout ) && { - auto_layout = std::move(_auto_layout); + auto_layout = ComponentBatch::from_loggable(_auto_layout, Descriptor_auto_layout) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -94,8 +140,10 @@ namespace rerun::blueprint::archetypes { /// If `true`, the viewer will only add views that it hasn't considered previously (as identified by `past_viewer_recommendations`) /// and which aren't deemed redundant to existing views. /// This defaults to `false` and is automatically set to `false` when the user adds views manually in the viewer. - ViewportBlueprint with_auto_views(rerun::blueprint::components::AutoViews _auto_views) && { - auto_views = std::move(_auto_views); + ViewportBlueprint with_auto_views(const rerun::blueprint::components::AutoViews& _auto_views + ) && { + auto_views = + ComponentBatch::from_loggable(_auto_views, Descriptor_auto_views).value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } @@ -107,10 +155,14 @@ namespace rerun::blueprint::archetypes { /// /// The viewer uses this to determine whether it should keep adding views. ViewportBlueprint with_past_viewer_recommendations( - Collection + const Collection& _past_viewer_recommendations ) && { - past_viewer_recommendations = std::move(_past_viewer_recommendations); + past_viewer_recommendations = ComponentBatch::from_loggable( + _past_viewer_recommendations, + Descriptor_past_viewer_recommendations + ) + .value_or_throw(); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } 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 2decd46e74f06..c6013adc6cb30 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + VisibleTimeRanges VisibleTimeRanges::clear_fields() { + auto archetype = VisibleTimeRanges(); + archetype.ranges = + ComponentBatch::empty(Descriptor_ranges) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,17 +25,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.ranges, - ComponentDescriptor( - "rerun.blueprint.archetypes.VisibleTimeRanges", - "ranges", - "rerun.blueprint.components.VisibleTimeRange" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.ranges.has_value()) { + cells.push_back(archetype.ranges.value()); } { auto indicator = VisibleTimeRanges::IndicatorComponent(); 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 1ff2ee6489f37..186b5fbbdf50b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_ranges.hpp @@ -5,11 +5,13 @@ #include "../../blueprint/components/visible_time_range.hpp" #include "../../collection.hpp" +#include "../../compiler_utils.hpp" #include "../../component_batch.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" #include +#include #include #include @@ -27,7 +29,7 @@ namespace rerun::blueprint::archetypes { /// The time ranges to show for each timeline unless specified otherwise on a per-entity basis. /// /// If a timeline is specified more than once, the first entry will be used. - Collection ranges; + std::optional ranges; public: static constexpr const char IndicatorComponentName[] = @@ -35,15 +37,47 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = + "rerun.blueprint.archetypes.VisibleTimeRanges"; + + /// `ComponentDescriptor` for the `ranges` field. + static constexpr auto Descriptor_ranges = ComponentDescriptor( + ArchetypeName, "ranges", + Loggable::Descriptor.component_name + ); public: VisibleTimeRanges() = default; VisibleTimeRanges(VisibleTimeRanges&& other) = default; + VisibleTimeRanges(const VisibleTimeRanges& other) = default; + VisibleTimeRanges& operator=(const VisibleTimeRanges& other) = default; + VisibleTimeRanges& operator=(VisibleTimeRanges&& other) = default; explicit VisibleTimeRanges( Collection _ranges ) - : ranges(std::move(_ranges)) {} + : ranges(ComponentBatch::from_loggable(std::move(_ranges), Descriptor_ranges) + .value_or_throw()) {} + + /// Update only some specific fields of a `VisibleTimeRanges`. + static VisibleTimeRanges update_fields() { + return VisibleTimeRanges(); + } + + /// Clear all the fields of a `VisibleTimeRanges`. + static VisibleTimeRanges clear_fields(); + + /// The time ranges to show for each timeline unless specified otherwise on a per-entity basis. + /// + /// If a timeline is specified more than once, the first entry will be used. + VisibleTimeRanges with_ranges( + const Collection& _ranges + ) && { + ranges = ComponentBatch::from_loggable(_ranges, Descriptor_ranges).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // 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 9326c22b35487..5a5e5135abe10 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.cpp @@ -5,7 +5,15 @@ #include "../../collection_adapter_builtins.hpp" -namespace rerun::blueprint::archetypes {} +namespace rerun::blueprint::archetypes { + VisualBounds2D VisualBounds2D::clear_fields() { + auto archetype = VisualBounds2D(); + archetype.range = + ComponentBatch::empty(Descriptor_range) + .value_or_throw(); + return archetype; + } +} // namespace rerun::blueprint::archetypes namespace rerun { @@ -17,17 +25,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - { - auto result = ComponentBatch::from_loggable( - archetype.range, - ComponentDescriptor( - "rerun.blueprint.archetypes.VisualBounds2D", - "range", - "rerun.blueprint.components.VisualBounds2D" - ) - ); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); + if (archetype.range.has_value()) { + cells.push_back(archetype.range.value()); } { auto indicator = VisualBounds2D::IndicatorComponent(); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp index fc0f11e560f16..9b1f00f5695bb 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds2d.hpp @@ -5,11 +5,13 @@ #include "../../blueprint/components/visual_bounds2d.hpp" #include "../../collection.hpp" +#include "../../compiler_utils.hpp" #include "../../component_batch.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" #include +#include #include #include @@ -25,7 +27,7 @@ namespace rerun::blueprint::archetypes { /// Controls the visible range of a 2D view. /// /// Use this to control pan & zoom of the view. - rerun::blueprint::components::VisualBounds2D range; + std::optional range; public: static constexpr const char IndicatorComponentName[] = @@ -33,13 +35,42 @@ namespace rerun::blueprint::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.blueprint.archetypes.VisualBounds2D"; + + /// `ComponentDescriptor` for the `range` field. + static constexpr auto Descriptor_range = ComponentDescriptor( + ArchetypeName, "range", + Loggable::Descriptor.component_name + ); public: VisualBounds2D() = default; VisualBounds2D(VisualBounds2D&& other) = default; + VisualBounds2D(const VisualBounds2D& other) = default; + VisualBounds2D& operator=(const VisualBounds2D& other) = default; + VisualBounds2D& operator=(VisualBounds2D&& other) = default; explicit VisualBounds2D(rerun::blueprint::components::VisualBounds2D _range) - : range(std::move(_range)) {} + : range(ComponentBatch::from_loggable(std::move(_range), Descriptor_range) + .value_or_throw()) {} + + /// Update only some specific fields of a `VisualBounds2D`. + static VisualBounds2D update_fields() { + return VisualBounds2D(); + } + + /// Clear all the fields of a `VisualBounds2D`. + static VisualBounds2D clear_fields(); + + /// Controls the visible range of a 2D view. + /// + /// Use this to control pan & zoom of the view. + VisualBounds2D with_range(const rerun::blueprint::components::VisualBounds2D& _range) && { + range = ComponentBatch::from_loggable(_range, Descriptor_range).value_or_throw(); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/component_batch.hpp b/rerun_cpp/src/rerun/component_batch.hpp index eeaf4cf338e90..3ada800330cc8 100644 --- a/rerun_cpp/src/rerun/component_batch.hpp +++ b/rerun_cpp/src/rerun/component_batch.hpp @@ -18,9 +18,9 @@ namespace arrow { struct rr_component_batch; namespace rerun { - /// Arrow-encoded data of a single batch components for a single entity. + /// Arrow-encoded data of a single batch of components together with a component descriptor. /// - /// Note that this doesn't own `datatype` and `component_name`. + /// Component descriptors are registered when first encountered. struct ComponentBatch { /// Arrow-encoded data of the component instances. std::shared_ptr array; @@ -29,6 +29,18 @@ 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) { + 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. diff --git a/rerun_cpp/src/rerun/components/transform_mat3x3.hpp b/rerun_cpp/src/rerun/components/transform_mat3x3.hpp index 04623cfa267a6..6fea4672d5a16 100644 --- a/rerun_cpp/src/rerun/components/transform_mat3x3.hpp +++ b/rerun_cpp/src/rerun/components/transform_mat3x3.hpp @@ -28,6 +28,11 @@ namespace rerun::components { struct TransformMat3x3 { rerun::datatypes::Mat3x3 matrix; + public: // START of extensions from transform_mat3x3_ext.cpp: + TransformMat3x3(const rerun::datatypes::Vec3D (&columns)[3]) : matrix(columns) {} + + // END of extensions from transform_mat3x3_ext.cpp, start of generated code: + public: TransformMat3x3() = default; diff --git a/rerun_cpp/src/rerun/components/transform_mat3x3_ext.cpp b/rerun_cpp/src/rerun/components/transform_mat3x3_ext.cpp new file mode 100644 index 0000000000000..9ec58aef31943 --- /dev/null +++ b/rerun_cpp/src/rerun/components/transform_mat3x3_ext.cpp @@ -0,0 +1,9 @@ +namespace rerun::components { +#if 0 + // + + TransformMat3x3(const rerun::datatypes::Vec3D (&columns)[3]) : matrix(columns) {} + + // +#endif +} // namespace rerun::components diff --git a/rerun_cpp/src/rerun/error.hpp b/rerun_cpp/src/rerun/error.hpp index 979b493249108..9e42c53fcb228 100644 --- a/rerun_cpp/src/rerun/error.hpp +++ b/rerun_cpp/src/rerun/error.hpp @@ -156,15 +156,21 @@ namespace rerun { void handle() const; /// Calls the `handle` method and then exits the application with code 1 if the error is not `Ok`. + /// @see throw_on_failure void exit_on_failure() const; -#ifdef __cpp_exceptions /// Throws a `std::runtime_error` if the status is not `Ok`. + /// + /// If exceptions are disabled, this will forward to `exit_on_failure` instead. + /// @see exit_on_failure void throw_on_failure() const { +#ifdef __cpp_exceptions if (is_err()) { throw std::runtime_error(description); } - } +#else + exit_on_failure(); #endif + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/result.hpp b/rerun_cpp/src/rerun/result.hpp index d9fd1009fad3d..97f3ff2b483ac 100644 --- a/rerun_cpp/src/rerun/result.hpp +++ b/rerun_cpp/src/rerun/result.hpp @@ -45,19 +45,37 @@ namespace rerun { return error.is_err(); } -#ifdef __cpp_exceptions /// Returns the value if status is ok, throws otherwise. + /// + /// If exceptions are disabled, this will exit the application instead. + /// @see error::value_or_exit const T& value_or_throw() const& { error.throw_on_failure(); return value; } /// Returns the value if status is ok, throws otherwise. + /// + /// If exceptions are disabled, this will exit the application instead. + /// @see error::value_or_exit T value_or_throw() && { error.throw_on_failure(); return std::move(value); } -#endif + + /// Returns the value if status is ok, exits the application otherwise. + /// @see error::value_or_throw + const T& value_or_exit() const& { + error.exit_on_failure(); + return value; + } + + /// Returns the value if status is ok, exits the application otherwise. + /// @see error::value_or_throw + T value_or_exit() && { + error.exit_on_failure(); + return std::move(value); + } public: T value; diff --git a/rerun_cpp/tests/archetypes/annotation_context.cpp b/rerun_cpp/tests/archetypes/annotation_context.cpp index a6336ab13dd4a..844551dcf6f98 100644 --- a/rerun_cpp/tests/archetypes/annotation_context.cpp +++ b/rerun_cpp/tests/archetypes/annotation_context.cpp @@ -85,7 +85,11 @@ SCENARIO( class_map.push_back(element); } } - manual_archetype.context.class_map = std::move(class_map); + manual_archetype.context = rerun::ComponentBatch::from_loggable( + rerun::components::AnnotationContext(class_map), + AnnotationContext::Descriptor_context + ) + .value_or_throw(); test_compare_archetype_serialization(from_utilities, manual_archetype); } diff --git a/rerun_cpp/tests/archetypes/archetype_test.hpp b/rerun_cpp/tests/archetypes/archetype_test.hpp index cb9fd2268b034..0cc5b023e6284 100644 --- a/rerun_cpp/tests/archetypes/archetype_test.hpp +++ b/rerun_cpp/tests/archetypes/archetype_test.hpp @@ -25,7 +25,7 @@ void test_compare_archetype_serialization(const T& arch_a, const T& arch_b) { for (size_t i = 0; i < arch_b_serialized.size(); ++i) { INFO("Component batch #" << i); CHECK( - arch_b_serialized[i].component_type == arch_a_serialized[i].component_type + arch_a_serialized[i].component_type == arch_b_serialized[i].component_type ); INFO( "Array diff: " diff --git a/rerun_cpp/tests/archetypes/arrows3d.cpp b/rerun_cpp/tests/archetypes/arrows3d.cpp index 6822342697b91..6c1455102eab8 100644 --- a/rerun_cpp/tests/archetypes/arrows3d.cpp +++ b/rerun_cpp/tests/archetypes/arrows3d.cpp @@ -20,12 +20,36 @@ SCENARIO( .with_class_ids({126, 127}); Arrows3D from_manual; - from_manual.vectors = {{1.0, 2.0, 3.0}, {10.0, 20.0, 30.0}}; - from_manual.origins = {{4.0, 5.0, 6.0}, {40.0, 50.0, 60.0}}; - from_manual.radii = {1.0, 10.0}; - from_manual.colors = {{0xAA, 0x00, 0x00, 0xCC}, {0x00, 0xBB, 0x00, 0xDD}}; - from_manual.labels = {"hello", "friend"}; - from_manual.class_ids = {126, 127}; + from_manual.vectors = rerun::ComponentBatch::from_loggable( + {{1.0, 2.0, 3.0}, {10.0, 20.0, 30.0}}, + Arrows3D::Descriptor_vectors + ) + .value_or_throw(); + from_manual.origins = rerun::ComponentBatch::from_loggable( + {{4.0, 5.0, 6.0}, {40.0, 50.0, 60.0}}, + Arrows3D::Descriptor_origins + ) + .value_or_throw(); + from_manual.radii = rerun::ComponentBatch::from_loggable( + {1.0, 10.0}, + Arrows3D::Descriptor_radii + ) + .value_or_throw(); + from_manual.colors = rerun::ComponentBatch::from_loggable( + {{0xAA, 0x00, 0x00, 0xCC}, {0x00, 0xBB, 0x00, 0xDD}}, + Arrows3D::Descriptor_colors + ) + .value_or_throw(); + from_manual.labels = rerun::ComponentBatch::from_loggable( + {"hello", "friend"}, + Arrows3D::Descriptor_labels + ) + .value_or_throw(); + from_manual.class_ids = rerun::ComponentBatch::from_loggable( + {126, 127}, + Arrows3D::Descriptor_class_ids + ) + .value_or_throw(); test_compare_archetype_serialization(from_manual, from_builder); } diff --git a/rerun_cpp/tests/archetypes/points3d.cpp b/rerun_cpp/tests/archetypes/points3d.cpp index 7a74a4734ac82..414855a07fb80 100644 --- a/rerun_cpp/tests/archetypes/points3d.cpp +++ b/rerun_cpp/tests/archetypes/points3d.cpp @@ -2,6 +2,7 @@ #include +using namespace rerun; using namespace rerun::archetypes; #define TEST_TAG "[points3d][archetypes]" @@ -17,15 +18,45 @@ SCENARIO( .with_colors({{0xAA, 0x00, 0x00, 0xCC}, {0x00, 0xBB, 0x00, 0xDD}}) .with_labels({"hello", "friend"}) .with_class_ids({126, 127}) - .with_keypoint_ids({1, 2}); + .with_keypoint_ids({1, 2}) + .with_show_labels(true); Points3D from_manual; - from_manual.positions = {{1.0, 2.0, 3.0}, {10.0, 20.0, 30.0}}; - from_manual.radii = {1.0, 10.0}; - from_manual.colors = {{0xAA, 0x00, 0x00, 0xCC}, {0x00, 0xBB, 0x00, 0xDD}}; - from_manual.labels = {"hello", "friend"}; - from_manual.keypoint_ids = {1, 2}; - from_manual.class_ids = {126, 127}; + from_manual.positions = ComponentBatch::from_loggable( + {{1.0, 2.0, 3.0}, {10.0, 20.0, 30.0}}, + Points3D::Descriptor_positions + ) + .value_or_throw(); + from_manual.radii = ComponentBatch::from_loggable( + {1.0, 10.0}, + Points3D::Descriptor_radii + ) + .value_or_throw(); + from_manual.colors = ComponentBatch::from_loggable( + {{0xAA, 0x00, 0x00, 0xCC}, {0x00, 0xBB, 0x00, 0xDD}}, + Points3D::Descriptor_colors + ) + .value_or_throw(); + from_manual.labels = ComponentBatch::from_loggable( + {"hello", "friend"}, + Points3D::Descriptor_labels + ) + .value_or_throw(); + from_manual.show_labels = ComponentBatch::from_loggable( + components::ShowLabels(true), + Points3D::Descriptor_show_labels + ) + .value_or_throw(); + from_manual.class_ids = ComponentBatch::from_loggable( + {126, 127}, + Points3D::Descriptor_class_ids + ) + .value_or_throw(); + from_manual.keypoint_ids = ComponentBatch::from_loggable( + {1, 2}, + Points3D::Descriptor_keypoint_ids + ) + .value_or_throw(); test_compare_archetype_serialization(from_manual, from_builder); } diff --git a/rerun_cpp/tests/archetypes/transform3d.cpp b/rerun_cpp/tests/archetypes/transform3d.cpp index a09836a259b2d..903b725b7fb0e 100644 --- a/rerun_cpp/tests/archetypes/transform3d.cpp +++ b/rerun_cpp/tests/archetypes/transform3d.cpp @@ -5,7 +5,9 @@ #include namespace rrd = rerun::datatypes; +namespace rrc = rerun::components; using namespace rerun::archetypes; +using ComponentBatch = rerun::ComponentBatch; #define TEST_TAG "[transform3d][archetypes]" @@ -29,34 +31,38 @@ SCENARIO( const auto quaternion = rrd::Quaternion::from_xyzw(1.0f, 2.0f, 3.0f, 4.0f); const auto axis_angle = rrd::RotationAxisAngle({1.0f, 2.0f, 3.0f}, rrd::Angle::degrees(90.0f)); - // List out everything so that GCC doesn't get nervous around uninitialized values. - Transform3D manual; - manual.scale = std::nullopt; - manual.mat3x3 = std::nullopt; - manual.translation = std::nullopt; - manual.relation = std::nullopt; - manual.axis_length = std::nullopt; + Transform3D manual = Transform3D::clear_fields(); GIVEN("Transform3D from translation") { auto utility = Transform3D::from_translation({1.0f, 2.0f, 3.0f}); - manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); + manual.translation = ComponentBatch::from_loggable( + {1.0f, 2.0f, 3.0f}, + Transform3D::Descriptor_translation + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } GIVEN("Transform3D from 3x3 matrix") { - manual.translation = std::nullopt; - AND_GIVEN("matrix as initializer list") { auto utility = Transform3D::from_mat3x3(MATRIX_ILIST); - manual.mat3x3 = rrd::Mat3x3(MATRIX_ILIST); + manual.mat3x3 = ComponentBatch::from_loggable( + rrc::TransformMat3x3(MATRIX_ILIST), + Transform3D::Descriptor_mat3x3 + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } AND_GIVEN("matrix as column vectors") { auto utility = Transform3D::from_mat3x3(columns); - manual.mat3x3 = rrd::Mat3x3(columns); + manual.mat3x3 = ComponentBatch::from_loggable( + rrc::TransformMat3x3(columns), + Transform3D::Descriptor_mat3x3 + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } @@ -65,23 +71,39 @@ SCENARIO( GIVEN("Transform3D from scale") { auto utility = Transform3D::from_scale({3.0f, 2.0f, 1.0f}); - manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); + manual.scale = ComponentBatch::from_loggable( + rrc::Scale3D(3.0f, 2.0f, 1.0f), + Transform3D::Descriptor_scale + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } GIVEN("Transform3D from translation & 3x3 matrix") { - manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); + manual.translation = ComponentBatch::from_loggable( + rrc::Translation3D(1.0f, 2.0f, 3.0f), + Transform3D::Descriptor_translation + ) + .value_or_throw(); AND_GIVEN("matrix as initializer list") { auto utility = Transform3D::from_translation_mat3x3({1.0f, 2.0f, 3.0f}, MATRIX_ILIST); - manual.mat3x3 = rrd::Mat3x3(MATRIX_ILIST); + manual.mat3x3 = ComponentBatch::from_loggable( + rrc::TransformMat3x3(MATRIX_ILIST), + Transform3D::Descriptor_mat3x3 + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } AND_GIVEN("matrix as column vectors") { auto utility = Transform3D::from_translation_mat3x3({1.0f, 2.0f, 3.0f}, columns); - manual.mat3x3 = rrd::Mat3x3(columns); + manual.mat3x3 = ComponentBatch::from_loggable( + rrc::TransformMat3x3(columns), + Transform3D::Descriptor_mat3x3 + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } @@ -90,8 +112,16 @@ SCENARIO( GIVEN("Transform3D from translation & scale") { auto utility = Transform3D::from_translation_scale({1.0f, 2.0f, 3.0f}, {3.0f, 2.0f, 1.0f}); - manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); - manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); + manual.translation = ComponentBatch::from_loggable( + rrc::Translation3D(1.0f, 2.0f, 3.0f), + Transform3D::Descriptor_translation + ) + .value_or_throw(); + manual.scale = ComponentBatch::from_loggable( + rrc::Scale3D(3.0f, 2.0f, 1.0f), + Transform3D::Descriptor_scale + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } @@ -103,9 +133,21 @@ SCENARIO( {3.0f, 2.0f, 1.0f} ); - manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); - manual.quaternion = quaternion; - manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); + manual.translation = ComponentBatch::from_loggable( + rrc::Translation3D(1.0f, 2.0f, 3.0f), + Transform3D::Descriptor_translation + ) + .value_or_throw(); + manual.quaternion = ComponentBatch::from_loggable( + rrc::RotationQuat(quaternion), + Transform3D::Descriptor_quaternion + ) + .value_or_throw(); + manual.scale = ComponentBatch::from_loggable( + rrc::Scale3D(3.0f, 2.0f, 1.0f), + Transform3D::Descriptor_scale + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } @@ -117,9 +159,21 @@ SCENARIO( {3.0f, 2.0f, 1.0f} ); - manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); - manual.rotation_axis_angle = axis_angle; - manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); + manual.translation = ComponentBatch::from_loggable( + rrc::Translation3D(1.0f, 2.0f, 3.0f), + Transform3D::Descriptor_translation + ) + .value_or_throw(); + manual.rotation_axis_angle = ComponentBatch::from_loggable( + rrc::RotationAxisAngle(axis_angle), + Transform3D::Descriptor_rotation_axis_angle + ) + .value_or_throw(); + manual.scale = ComponentBatch::from_loggable( + rrc::Scale3D(3.0f, 2.0f, 1.0f), + Transform3D::Descriptor_scale + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } @@ -127,8 +181,16 @@ SCENARIO( GIVEN("Transform3D from rotation (quaternion) & scale") { auto utility = Transform3D::from_rotation_scale(quaternion, {3.0f, 2.0f, 1.0f}); - manual.quaternion = quaternion; - manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); + manual.quaternion = ComponentBatch::from_loggable( + rrc::RotationQuat(quaternion), + Transform3D::Descriptor_quaternion + ) + .value_or_throw(); + manual.scale = ComponentBatch::from_loggable( + rrc::Scale3D(3.0f, 2.0f, 1.0f), + Transform3D::Descriptor_scale + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } @@ -136,28 +198,48 @@ SCENARIO( GIVEN("Transform3D from rotation (axis angle) & scale") { auto utility = Transform3D::from_rotation_scale(axis_angle, {3.0f, 2.0f, 1.0f}); - manual.rotation_axis_angle = axis_angle; - manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); + manual.rotation_axis_angle = ComponentBatch::from_loggable( + rrc::RotationAxisAngle(axis_angle), + Transform3D::Descriptor_rotation_axis_angle + ) + .value_or_throw(); + manual.scale = ComponentBatch::from_loggable( + rrc::Scale3D(3.0f, 2.0f, 1.0f), + Transform3D::Descriptor_scale + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } GIVEN("Transform3D from rotation (quaternion)") { auto utility = Transform3D::from_rotation(quaternion); - manual.quaternion = quaternion; + manual.quaternion = ComponentBatch::from_loggable( + rrc::RotationQuat(quaternion), + Transform3D::Descriptor_quaternion + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } GIVEN("Transform3D from rotation (axis angle)") { auto utility = Transform3D::from_rotation(axis_angle); - manual.rotation_axis_angle = axis_angle; + manual.rotation_axis_angle = ComponentBatch::from_loggable( + rrc::RotationAxisAngle(axis_angle), + Transform3D::Descriptor_rotation_axis_angle + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } GIVEN("A custom relation") { auto utility = - Transform3D().with_relation(rerun::components::TransformRelation::ChildFromParent); - manual.relation = rerun::components::TransformRelation::ChildFromParent; + Transform3D::clear_fields().with_relation(rrc::TransformRelation::ChildFromParent); + manual.relation = ComponentBatch::from_loggable( + rrc::TransformRelation::ChildFromParent, + Transform3D::Descriptor_relation + ) + .value_or_throw(); test_compare_archetype_serialization(manual, utility); } diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp index 7cc786918022a..f617a423c4205 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp @@ -86,10 +86,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.testing.archetypes.AffixFuzzer1"; public: AffixFuzzer1() = default; AffixFuzzer1(AffixFuzzer1&& other) = default; + AffixFuzzer1(const AffixFuzzer1& other) = default; + AffixFuzzer1& operator=(const AffixFuzzer1& other) = default; + AffixFuzzer1& operator=(AffixFuzzer1&& other) = default; explicit AffixFuzzer1( rerun::components::AffixFuzzer1 _fuzz1001, rerun::components::AffixFuzzer2 _fuzz1002, diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp index 544da9c955f83..e16c9571d537b 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp @@ -77,10 +77,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.testing.archetypes.AffixFuzzer2"; public: AffixFuzzer2() = default; AffixFuzzer2(AffixFuzzer2&& other) = default; + AffixFuzzer2(const AffixFuzzer2& other) = default; + AffixFuzzer2& operator=(const AffixFuzzer2& other) = default; + AffixFuzzer2& operator=(AffixFuzzer2&& other) = default; explicit AffixFuzzer2( Collection _fuzz1101, diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp index 9a8239b86c636..64c76c113b338 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp @@ -76,10 +76,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.testing.archetypes.AffixFuzzer3"; public: AffixFuzzer3() = default; AffixFuzzer3(AffixFuzzer3&& other) = default; + AffixFuzzer3(const AffixFuzzer3& other) = default; + AffixFuzzer3& operator=(const AffixFuzzer3& other) = default; + AffixFuzzer3& operator=(AffixFuzzer3&& other) = default; AffixFuzzer3 with_fuzz2001(rerun::components::AffixFuzzer1 _fuzz2001) && { fuzz2001 = std::move(_fuzz2001); diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp index 79bafdb0f42c2..e227e849a5496 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp @@ -76,10 +76,15 @@ namespace rerun::archetypes { /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.testing.archetypes.AffixFuzzer4"; public: AffixFuzzer4() = default; AffixFuzzer4(AffixFuzzer4&& other) = default; + AffixFuzzer4(const AffixFuzzer4& other) = default; + AffixFuzzer4& operator=(const AffixFuzzer4& other) = default; + AffixFuzzer4& operator=(AffixFuzzer4&& other) = default; AffixFuzzer4 with_fuzz2101(Collection _fuzz2101) && { fuzz2101 = std::move(_fuzz2101); diff --git a/scripts/ci/check_large_files.py b/scripts/ci/check_large_files.py index 52c35878f3c4d..ab2a786a9f195 100755 --- a/scripts/ci/check_large_files.py +++ b/scripts/ci/check_large_files.py @@ -7,6 +7,7 @@ FILES_ALLOWED_TO_BE_LARGE = { "CHANGELOG.md", "Cargo.lock", + "crates/build/re_types_builder/src/codegen/cpp/mod.rs", # TODO(andreas, #7245): This file should really be split up. Might get shorter after removing non-eager serialization path. "crates/build/re_types_builder/src/reflection.rs", "crates/store/re_dataframe/src/query.rs", "crates/store/re_types/src/datatypes/tensor_buffer.rs", From 85fc27d195f5c23fa31ead68b8566ea031a69c94 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:22:12 +0100 Subject: [PATCH 4/4] Filter entities in the UI (part 5): Add snapshot tests for the blueprint tree (#8728) --- Cargo.lock | 4 +- .../src/path/entity_path_filter.rs | 1 + crates/viewer/re_blueprint_tree/Cargo.toml | 9 + .../re_blueprint_tree/src/blueprint_tree.rs | 5 + .../tests/blueprint_tree_tests.rs | 208 ++++++++++++++++++ .../tests/snapshots/basic_blueprint_panel.png | 3 + ...print_panel_filter_active_above_origin.png | 3 + ...rint_panel_filter_active_inside_origin.png | 3 + ...int_panel_filter_active_outside_origin.png | 3 + .../collapse_all_blueprint_panel.png | 3 + .../snapshots/expand_all_blueprint_panel.png | 3 + crates/viewer/re_view_graph/Cargo.toml | 2 +- crates/viewer/re_view_graph/tests/basic.rs | 137 +++--------- .../re_viewer_context/src/query_context.rs | 1 + .../re_viewer_context/src/test_context.rs | 28 ++- .../src/view/view_class_registry.rs | 4 +- .../viewer/re_viewport_blueprint/Cargo.toml | 4 + .../viewer/re_viewport_blueprint/src/lib.rs | 2 + .../src/test_context_ext.rs | 106 +++++++++ .../viewer/re_viewport_blueprint/src/view.rs | 4 +- .../src/view_properties.rs | 1 + 21 files changed, 419 insertions(+), 115 deletions(-) create mode 100644 crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/basic_blueprint_panel.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_above_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_inside_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_outside_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/collapse_all_blueprint_panel.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/expand_all_blueprint_panel.png create mode 100644 crates/viewer/re_viewport_blueprint/src/test_context_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 2ac7c476b53eb..9b82beceace70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5636,7 +5636,9 @@ name = "re_blueprint_tree" version = "0.22.0-alpha.1+dev" dependencies = [ "egui", + "egui_kittest", "itertools 0.13.0", + "re_chunk_store", "re_context_menu", "re_data_ui", "re_entity_db", @@ -5645,6 +5647,7 @@ dependencies = [ "re_tracing", "re_types", "re_ui", + "re_view_spatial", "re_viewer_context", "re_viewport_blueprint", "smallvec", @@ -6761,7 +6764,6 @@ version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "egui", - "egui_kittest", "fjadra", "itertools 0.13.0", "nohash-hasher", diff --git a/crates/store/re_log_types/src/path/entity_path_filter.rs b/crates/store/re_log_types/src/path/entity_path_filter.rs index aef37f1449e33..1250f4f2ed40c 100644 --- a/crates/store/re_log_types/src/path/entity_path_filter.rs +++ b/crates/store/re_log_types/src/path/entity_path_filter.rs @@ -19,6 +19,7 @@ pub enum EntityPathFilterError { /// /// Important: the same substitutions must be used in every place we resolve [`EntityPathFilter`] to /// [`ResolvedEntityPathFilter`]. +#[derive(Debug)] pub struct EntityPathSubs(HashMap); impl EntityPathSubs { diff --git a/crates/viewer/re_blueprint_tree/Cargo.toml b/crates/viewer/re_blueprint_tree/Cargo.toml index a4d87551b123f..a6489b8d63263 100644 --- a/crates/viewer/re_blueprint_tree/Cargo.toml +++ b/crates/viewer/re_blueprint_tree/Cargo.toml @@ -33,3 +33,12 @@ re_viewport_blueprint.workspace = true egui.workspace = true itertools.workspace = 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 + +egui_kittest.workspace = true diff --git a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs index 483219af4282d..8fb9b8d967f08 100644 --- a/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs +++ b/crates/viewer/re_blueprint_tree/src/blueprint_tree.rs @@ -53,6 +53,11 @@ pub struct BlueprintTree { } impl BlueprintTree { + /// Activates the search filter (for e.g. test purposes). + pub fn activate_filter(&mut self, query: &str) { + self.filter_state.activate(query); + } + /// Show the Blueprint section of the left panel based on the current [`ViewportBlueprint`] pub fn show( &mut self, diff --git a/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs b/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs new file mode 100644 index 0000000000000..a5763373ac071 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/blueprint_tree_tests.rs @@ -0,0 +1,208 @@ +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_types::archetypes::Points3D; +use re_viewer_context::{test_context::TestContext, CollapseScope, RecommendedView, ViewClass}; +use re_viewport_blueprint::{ + test_context_ext::TestContextExt as _, ViewBlueprint, ViewportBlueprint, +}; + +#[test] +fn basic_blueprint_panel_should_match_snapshot() { + let mut test_context = TestContext::default(); + + test_context.register_view_class::(); + + test_context.log_entity("/entity0".into(), add_point_to_chunk_builder); + test_context.log_entity("/entity1".into(), add_point_to_chunk_builder); + test_context.log_entity("/entity2".into(), add_point_to_chunk_builder); + + test_context.setup_viewport_blueprint(|_, blueprint| { + blueprint.add_views( + std::iter::once(ViewBlueprint::new( + re_view_spatial::SpatialView3D::identifier(), + RecommendedView::root(), + )), + None, + None, + ); + }); + + let blueprint_tree = BlueprintTree::default(); + run_blueprint_panel_and_save_snapshot(test_context, blueprint_tree, "basic_blueprint_panel"); +} + +// --- + +#[test] +fn collapse_expand_all_blueprint_panel_should_match_snapshot() { + for (snapshot_name, should_expand) in &[ + ("expand_all_blueprint_panel", true), + ("collapse_all_blueprint_panel", false), + ] { + let mut test_context = TestContext::default(); + + test_context.register_view_class::(); + + test_context.log_entity("/path/to/entity0".into(), add_point_to_chunk_builder); + 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( + re_view_spatial::SpatialView3D::identifier(), + RecommendedView::root(), + ); + + 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(); + + 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, + CollapseScope::BlueprintTree, + *should_expand, + ); + + 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(); + harness.snapshot(snapshot_name); + } +} + +// --- + +#[test] +fn blueprint_panel_filter_active_inside_origin_should_match_snapshot() { + let (test_context, blueprint_tree) = setup_filter_test(Some("left")); + + run_blueprint_panel_and_save_snapshot( + test_context, + blueprint_tree, + "blueprint_panel_filter_active_inside_origin", + ); +} + +#[test] +fn blueprint_panel_filter_active_outside_origin_should_match_snapshot() { + let (test_context, blueprint_tree) = setup_filter_test(Some("out")); + + run_blueprint_panel_and_save_snapshot( + test_context, + blueprint_tree, + "blueprint_panel_filter_active_outside_origin", + ); +} + +#[test] +fn blueprint_panel_filter_active_above_origin_should_match_snapshot() { + let (test_context, blueprint_tree) = setup_filter_test(Some("path")); + + run_blueprint_panel_and_save_snapshot( + test_context, + blueprint_tree, + "blueprint_panel_filter_active_above_origin", + ); +} + +fn setup_filter_test(query: Option<&str>) -> (TestContext, BlueprintTree) { + let mut test_context = TestContext::default(); + test_context.register_view_class::(); + + 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/is/outside".into(), add_point_to_chunk_builder); + + test_context.setup_viewport_blueprint(|_, blueprint| { + blueprint.add_views( + std::iter::once(ViewBlueprint::new( + re_view_spatial::SpatialView3D::identifier(), + RecommendedView { + origin: "/path/to".into(), + query_filter: "+ /**".try_into().expect("valid entity path filter"), + }, + )), + None, + None, + ); + }); + + 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(query) = query { + blueprint_tree.activate_filter(query); + } + + (test_context, blueprint_tree) +} + +// --- + +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]]), + ) +} + +fn run_blueprint_panel_and_save_snapshot( + mut test_context: TestContext, + mut blueprint_tree: BlueprintTree, + snapshot_name: &str, +) { + 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| { + 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(); + harness.snapshot(snapshot_name); +} diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/basic_blueprint_panel.png b/crates/viewer/re_blueprint_tree/tests/snapshots/basic_blueprint_panel.png new file mode 100644 index 0000000000000..ec63a4bb16fe9 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/basic_blueprint_panel.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:769ca0cce66cec8bc8e7621aa2ae48353b3d26e191b486e6e5bd4a3f2c1299d9 +size 20147 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 new file mode 100644 index 0000000000000..a7fa222be7b68 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_above_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f6d2f7f5ee34fa4fc0609c55a3dca06cea2984d1d6a99569014e8801fcb07a0 +size 22280 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_inside_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_inside_origin.png new file mode 100644 index 0000000000000..d4f645488e610 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_inside_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36a77c9ce18d5ebc02d81159e9797df347a86156b76057bf4a54309885a72675 +size 16574 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_outside_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_outside_origin.png new file mode 100644 index 0000000000000..56b52bfcf0ff0 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/blueprint_panel_filter_active_outside_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d4c2af6873f1d57ba79f2058a9016adb1a91a59503f004ae8e9b2ab9f5f20b7 +size 22099 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/collapse_all_blueprint_panel.png b/crates/viewer/re_blueprint_tree/tests/snapshots/collapse_all_blueprint_panel.png new file mode 100644 index 0000000000000..342cbb6654882 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/collapse_all_blueprint_panel.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:856663346b399727c2dd57d085f421086ec8fc523301be7c4be18081af9c7ed6 +size 14096 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/expand_all_blueprint_panel.png b/crates/viewer/re_blueprint_tree/tests/snapshots/expand_all_blueprint_panel.png new file mode 100644 index 0000000000000..ba779adf09972 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/expand_all_blueprint_panel.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d42b9a800aa1c9d9fb7bafcab051fb387522da5d1b3fa9afdd3ffcdeaba4347 +size 25646 diff --git a/crates/viewer/re_view_graph/Cargo.toml b/crates/viewer/re_view_graph/Cargo.toml index 576f8330d97c8..e1f2b4f4b7324 100644 --- a/crates/viewer/re_view_graph/Cargo.toml +++ b/crates/viewer/re_view_graph/Cargo.toml @@ -41,7 +41,7 @@ itertools.workspace = true nohash-hasher.workspace = true [dev-dependencies] -egui_kittest.workspace = true re_chunk_store.workspace = true re_viewer_context = { workspace = true, features = ["testing"] } re_viewport.workspace = true +re_viewport_blueprint = { workspace = true, features = ["testing"] } diff --git a/crates/viewer/re_view_graph/tests/basic.rs b/crates/viewer/re_view_graph/tests/basic.rs index e5f41e850ec1c..6198c76b1be6d 100644 --- a/crates/viewer/re_view_graph/tests/basic.rs +++ b/crates/viewer/re_view_graph/tests/basic.rs @@ -3,11 +3,13 @@ use std::sync::Arc; use egui::Vec2; + use re_chunk_store::{Chunk, RowId}; use re_entity_db::EntityPath; use re_types::{components, Component as _}; use re_view_graph::{GraphView, GraphViewState}; -use re_viewer_context::{test_context::TestContext, ViewClass, ViewClassExt as _, ViewId}; +use re_viewer_context::{test_context::TestContext, RecommendedView, ViewClass}; +use re_viewport_blueprint::test_context_ext::TestContextExt as _; use re_viewport_blueprint::ViewBlueprint; #[test] @@ -18,10 +20,7 @@ pub fn coincident_nodes() { // It's important to first register the view class before adding any entities, // otherwise the `VisualizerEntitySubscriber` for our visualizers doesn't exist yet, // and thus will not find anything applicable to the visualizer. - test_context - .view_class_registry - .add_class::() - .unwrap(); + test_context.register_view_class::(); let entity_path = EntityPath::from(name); @@ -56,7 +55,7 @@ pub fn coincident_nodes() { .add_chunk(&Arc::new(builder.build().unwrap())) .unwrap(); - run_graph_view_and_save_snapshot(&mut test_context, name, Vec2::new(100.0, 100.0)).unwrap(); + run_graph_view_and_save_snapshot(&mut test_context, name, Vec2::new(100.0, 100.0)); } #[test] @@ -120,124 +119,50 @@ pub fn self_and_multi_edges() { .add_chunk(&Arc::new(builder.build().unwrap())) .unwrap(); - run_graph_view_and_save_snapshot(&mut test_context, name, Vec2::new(400.0, 400.0)).unwrap(); + run_graph_view_and_save_snapshot(&mut test_context, name, Vec2::new(400.0, 400.0)); } -pub fn setup_graph_view_blueprint( - test_context: &mut TestContext, -) -> Result> { - // Views are always logged at `/{view_id}` in the blueprint store. - let view_id = ViewId::hashed_from_str("/graph"); - - // Use the timeline that is queried for blueprints. - let timepoint = [(test_context.blueprint_query.timeline(), 0)]; - - let view_chunk = Chunk::builder(view_id.as_entity_path().clone()) - .with_archetype( - RowId::new(), - timepoint, - &re_types::blueprint::archetypes::ViewBlueprint::new(GraphView::identifier().as_str()), - ) - .build()?; - test_context - .blueprint_store - .add_chunk(&Arc::new(view_chunk))?; - - // TODO(andreas): can we use the `ViewProperty` utilities for this? - let view_contents_chunk = - Chunk::builder(format!("{}/ViewContents", view_id.as_entity_path()).into()) - .with_archetype( - RowId::new(), - timepoint, - &re_types::blueprint::archetypes::ViewContents::new(std::iter::once( - re_types::datatypes::Utf8::from("/**"), - )), - ) - .build()?; - test_context - .blueprint_store - .add_chunk(&Arc::new(view_contents_chunk))?; - - Ok(view_id) -} +fn run_graph_view_and_save_snapshot(test_context: &mut TestContext, name: &str, size: Vec2) { + let view_id = test_context.setup_viewport_blueprint(|_, blueprint| { + let view_blueprint = ViewBlueprint::new( + re_view_graph::GraphView::identifier(), + RecommendedView::root(), + ); -fn run_graph_view_and_save_snapshot( - test_context: &mut TestContext, - _name: &str, - size: Vec2, -) -> Result<(), Box> { - let view_id = setup_graph_view_blueprint(test_context)?; - let view_blueprint = ViewBlueprint::try_from_db( - view_id, - &test_context.blueprint_store, - &test_context.blueprint_query, - ) - .expect("failed to get view blueprint"); + let view_id = view_blueprint.id; + blueprint.add_views(std::iter::once(view_blueprint), None, None); + view_id + }); let mut view_state = GraphViewState::default(); - let class_identifier = GraphView::identifier(); - - let view_class_registry = &mut test_context.view_class_registry; - let applicable_entities_per_visualizer = view_class_registry - .applicable_entities_for_visualizer_systems(&test_context.recording_store.store_id()); - - // TODO(andreas): this is c&p from TestContext::run. Make it nicer plz ;) - let store_context = re_viewer_context::StoreContext { - app_id: "rerun_test".into(), - blueprint: &test_context.blueprint_store, - default_blueprint: None, - recording: &test_context.recording_store, - bundle: &Default::default(), - caches: &Default::default(), - hub: &Default::default(), - should_enable_heuristics: false, - }; - - // Execute the queries for every `View` - test_context.query_results = std::iter::once((view_id, { - // TODO(andreas): This needs to be done in a store subscriber that exists per view (instance, not class!). - // Note that right now we determine *all* visualizable entities, not just the queried ones. - // In a store subscriber set this is fine, but on a per-frame basis it's wasteful. - let visualizable_entities = view_class_registry - .get_class_or_log_error(class_identifier) - .determine_visualizable_entities( - &applicable_entities_per_visualizer, - &test_context.recording_store, - &view_class_registry.new_visualizer_collection(class_identifier), - &view_blueprint.space_origin, - ); - - view_blueprint.contents.execute_query( - &store_context, - view_class_registry, - &test_context.blueprint_query, - view_id, - &visualizable_entities, - ) - })) - .collect(); - - //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(size) .with_max_steps(256) // Give it some time to settle the graph. .build_ui(|ui| { - test_context.run(&ui.ctx().clone(), |viewer_ctx| { - let view_class = test_context + test_context.run(&ui.ctx().clone(), |ctx| { + let view_class = ctx .view_class_registry .get_class_or_log_error(GraphView::identifier()); + let view_blueprint = ViewBlueprint::try_from_db( + view_id, + ctx.store_context.blueprint, + ctx.blueprint_query, + ) + .expect("we just created that view"); + let (view_query, system_execution_output) = re_viewport::execute_systems_for_view( - viewer_ctx, + ctx, &view_blueprint, - viewer_ctx.current_query().at(), // TODO(andreas): why is this even needed to be passed in? + ctx.current_query().at(), // TODO(andreas): why is this even needed to be passed in? &view_state, ); view_class .ui( - viewer_ctx, + ctx, ui, &mut view_state, &view_query, @@ -250,7 +175,5 @@ fn run_graph_view_and_save_snapshot( }); harness.run(); - harness.snapshot(_name); - - Ok(()) + harness.snapshot(name); } diff --git a/crates/viewer/re_viewer_context/src/query_context.rs b/crates/viewer/re_viewer_context/src/query_context.rs index b0968b20050b3..c355c35544cfd 100644 --- a/crates/viewer/re_viewer_context/src/query_context.rs +++ b/crates/viewer/re_viewer_context/src/query_context.rs @@ -49,6 +49,7 @@ impl QueryContext<'_> { } /// The result of executing a single data query for a specific view. +#[derive(Debug)] pub struct DataQueryResult { /// The [`DataResultTree`] for the query pub tree: DataResultTree, diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 7d01791232a43..cc4da30510d2c 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -5,15 +5,16 @@ use ahash::HashMap; use once_cell::sync::Lazy; use parking_lot::Mutex; +use re_chunk::{Chunk, ChunkBuilder}; use re_chunk_store::LatestAtQuery; use re_entity_db::EntityDb; -use re_log_types::{StoreId, StoreKind}; +use re_log_types::{EntityPath, StoreId, StoreKind}; use re_types_core::reflection::Reflection; use crate::{ blueprint_timeline, command_channel, ApplicationSelectionState, CommandReceiver, CommandSender, ComponentUiRegistry, DataQueryResult, ItemCollection, RecordingConfig, StoreContext, - SystemCommand, ViewClassRegistry, ViewId, ViewerContext, + SystemCommand, ViewClass, ViewClassRegistry, ViewId, ViewerContext, }; /// Harness to execute code that rely on [`crate::ViewerContext`]. @@ -207,6 +208,29 @@ impl TestContext { self.selection_state.on_frame_start(|_| true, None); } + /// Log an entity to the recording store. + /// + /// The provided closure should add content using the [`ChunkBuilder`] passed as argument. + pub fn log_entity( + &mut self, + entity_path: EntityPath, + build_chunk: impl FnOnce(ChunkBuilder) -> ChunkBuilder, + ) { + let builder = build_chunk(Chunk::builder(entity_path)); + self.recording_store + .add_chunk(&Arc::new( + builder.build().expect("chunk should be successfully built"), + )) + .expect("chunk should be successfully added"); + } + + /// Register a view class. + pub fn register_view_class(&mut self) { + self.view_class_registry + .add_class::() + .expect("registering a class should succeed"); + } + /// Run the provided closure with a [`ViewerContext`] produced by the [`Self`]. /// /// IMPORTANT: call [`Self::handle_system_commands`] after calling this function if your test diff --git a/crates/viewer/re_viewer_context/src/view/view_class_registry.rs b/crates/viewer/re_viewer_context/src/view/view_class_registry.rs index 58ba77b776b2a..566dc3e0b25c1 100644 --- a/crates/viewer/re_viewer_context/src/view/view_class_registry.rs +++ b/crates/viewer/re_viewer_context/src/view/view_class_registry.rs @@ -238,7 +238,7 @@ impl ViewClassRegistry { } /// Queries a View type by class name, returning `None` if it is not registered. - fn get_class(&self, name: ViewClassIdentifier) -> Option<&dyn ViewClass> { + pub fn class(&self, name: ViewClassIdentifier) -> Option<&dyn ViewClass> { self.view_classes .get(&name) .map(|boxed| boxed.class.as_ref()) @@ -255,7 +255,7 @@ impl ViewClassRegistry { /// Queries a View type by class name and logs if it fails, returning a placeholder class. pub fn get_class_or_log_error(&self, name: ViewClassIdentifier) -> &dyn ViewClass { - if let Some(result) = self.get_class(name) { + if let Some(result) = self.class(name) { result } else { re_log::error_once!("Unknown view class {:?}", name); diff --git a/crates/viewer/re_viewport_blueprint/Cargo.toml b/crates/viewer/re_viewport_blueprint/Cargo.toml index 8b324a16620f9..bc32895ceb266 100644 --- a/crates/viewer/re_viewport_blueprint/Cargo.toml +++ b/crates/viewer/re_viewport_blueprint/Cargo.toml @@ -18,6 +18,10 @@ workspace = true [package.metadata.docs.rs] all-features = true +[features] +## Enable for testing utilities. +testing = ["re_viewer_context/testing"] + [dependencies] re_chunk.workspace = true re_chunk_store.workspace = true diff --git a/crates/viewer/re_viewport_blueprint/src/lib.rs b/crates/viewer/re_viewport_blueprint/src/lib.rs index 442afe92eedd3..f7135a4f44d85 100644 --- a/crates/viewer/re_viewport_blueprint/src/lib.rs +++ b/crates/viewer/re_viewport_blueprint/src/lib.rs @@ -5,6 +5,8 @@ mod auto_layout; mod container; mod entity_add_info; +#[cfg(feature = "testing")] +pub mod test_context_ext; pub mod ui; mod view; mod view_contents; diff --git a/crates/viewer/re_viewport_blueprint/src/test_context_ext.rs b/crates/viewer/re_viewport_blueprint/src/test_context_ext.rs new file mode 100644 index 0000000000000..fdb6247bef314 --- /dev/null +++ b/crates/viewer/re_viewport_blueprint/src/test_context_ext.rs @@ -0,0 +1,106 @@ +use ahash::HashMap; + +use re_viewer_context::{test_context::TestContext, Contents, ViewClassExt, ViewerContext}; + +use crate::ViewportBlueprint; + +/// Extension trait to [`TestContext`] for blueprint-related features. +pub trait TestContextExt { + /// See docstring on the implementation below. + fn setup_viewport_blueprint( + &mut self, + setup_blueprint: impl FnOnce(&ViewerContext<'_>, &mut ViewportBlueprint) -> R, + ) -> R; +} + +impl TestContextExt for TestContext { + /// Inspect or update the blueprint of a [`TestContext`]. + /// + /// This helper works by deserializing the current blueprint, providing it to the provided + /// closure, and saving it back to the blueprint store. The closure should call the appropriate + /// methods of [`ViewportBlueprint`] to inspect and/or create views and containers as required. + /// + /// Each time [`TestContextExt::setup_viewport_blueprint`] is called, it entirely recomputes the + /// "query results", i.e., the [`re_viewer_context::DataResult`]s that each view contains, based + /// on the current content of the recording store. + /// + /// Important pre-requisite: + /// - The view classes used by view must be already registered (see + /// [`TestContext::register_view_class`]). + /// - The data store must be already populated for the views to have any content (see, e.g., + /// [`TestContext::log_entity`]). + /// + fn setup_viewport_blueprint( + &mut self, + setup_blueprint: impl FnOnce(&ViewerContext<'_>, &mut ViewportBlueprint) -> R, + ) -> R { + let mut setup_blueprint: Option<_> = Some(setup_blueprint); + + let mut result = None; + + egui::__run_test_ctx(|egui_ctx| { + // We use `take` to ensure that the blueprint is setup only once, since egui forces + // us to a `FnMut` closure. + if let Some(setup_blueprint) = setup_blueprint.take() { + self.run(egui_ctx, |ctx| { + let mut viewport_blueprint = ViewportBlueprint::try_from_db( + &self.blueprint_store, + &self.blueprint_query, + ); + result = Some(setup_blueprint(ctx, &mut viewport_blueprint)); + viewport_blueprint.save_to_blueprint_store(ctx); + }); + + self.handle_system_commands(); + + // Reload the blueprint store and execute all view queries. + let viewport_blueprint = + ViewportBlueprint::try_from_db(&self.blueprint_store, &self.blueprint_query); + + let applicable_entities_per_visualizer = self + .view_class_registry + .applicable_entities_for_visualizer_systems(&self.recording_store.store_id()); + let mut query_results = HashMap::default(); + self.run(egui_ctx, |ctx| { + viewport_blueprint.visit_contents(&mut |contents, _| { + if let Contents::View(view_id) = contents { + let view_blueprint = viewport_blueprint + .view(view_id) + .expect("view is known to exist"); + let class_identifier = view_blueprint.class_identifier(); + + let data_query_result = { + let visualizable_entities = ctx + .view_class_registry + .class(class_identifier) + .expect("The class must be registered beforehand") + .determine_visualizable_entities( + &applicable_entities_per_visualizer, + ctx.recording(), + &ctx.view_class_registry + .new_visualizer_collection(class_identifier), + &view_blueprint.space_origin, + ); + + view_blueprint.contents.execute_query( + ctx.store_context, + ctx.view_class_registry, + ctx.blueprint_query, + *view_id, + &visualizable_entities, + ) + }; + query_results.insert(*view_id, data_query_result); + } + + true + }); + }); + + self.query_results = query_results; + } + }); + + result.expect("The `setup_closure` is expected to be called at least once") + } +} diff --git a/crates/viewer/re_viewport_blueprint/src/view.rs b/crates/viewer/re_viewport_blueprint/src/view.rs index 7d223dff19fb6..6e77e3f51487e 100644 --- a/crates/viewer/re_viewport_blueprint/src/view.rs +++ b/crates/viewer/re_viewport_blueprint/src/view.rs @@ -148,7 +148,7 @@ impl ViewBlueprint { let space_env = EntityPathSubs::new_with_origin(&space_origin); - let content = + let contents = ViewContents::from_db_or_default(id, blueprint_db, query, class_identifier, &space_env); let visible = visible.map_or(true, |v| *v.0); let defaults_path = id.as_entity_path().join(&"defaults".into()); @@ -158,7 +158,7 @@ impl ViewBlueprint { display_name, class_identifier, space_origin, - contents: content, + contents, visible, defaults_path, pending_writes: Default::default(), diff --git a/crates/viewer/re_viewport_blueprint/src/view_properties.rs b/crates/viewer/re_viewport_blueprint/src/view_properties.rs index 7ff14aa1b92ad..9361ba14844ca 100644 --- a/crates/viewer/re_viewport_blueprint/src/view_properties.rs +++ b/crates/viewer/re_viewport_blueprint/src/view_properties.rs @@ -26,6 +26,7 @@ impl From for ViewSystemExecutionError { } /// Utility for querying view properties. +#[derive(Debug)] pub struct ViewProperty { /// Entity path in the blueprint store where all components of this view property archetype are /// stored.