From 8f58dcffd4398677a1d78334519286058e7b8524 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 26 Apr 2024 09:11:37 +0200 Subject: [PATCH 01/20] Add .fbs definitions for visual bounds and AABB2D --- .../src/latest_at/to_archetype/.gitattributes | 1 + .../src/latest_at/to_archetype/mod.rs | 1 + .../latest_at/to_archetype/visual_bounds.rs | 44 ++ crates/re_space_view_spatial/src/ui_2d.rs | 2 +- .../re_types/definitions/rerun/blueprint.fbs | 1 + .../rerun/blueprint/archetypes/background.fbs | 2 - .../blueprint/archetypes/visual_bounds.fbs | 23 + .../rerun/blueprint/views/spatial2d.fbs | 6 + .../re_types/definitions/rerun/components.fbs | 1 + .../definitions/rerun/components/aabb2d.fbs | 18 + .../re_types/definitions/rerun/datatypes.fbs | 1 + .../definitions/rerun/datatypes/aabb2d.fbs | 21 + .../src/blueprint/archetypes/.gitattributes | 1 + .../re_types/src/blueprint/archetypes/mod.rs | 2 + .../src/blueprint/archetypes/visual_bounds.rs | 159 +++++++ crates/re_types/src/components/.gitattributes | 1 + crates/re_types/src/components/aabb2d.rs | 148 ++++++ crates/re_types/src/components/mod.rs | 2 + crates/re_types/src/datatypes/.gitattributes | 1 + crates/re_types/src/datatypes/aabb2d.rs | 434 ++++++++++++++++++ crates/re_types/src/datatypes/mod.rs | 2 + docs/content/reference/types/components.md | 1 + .../reference/types/components/.gitattributes | 1 + .../reference/types/components/aabb2d.md | 16 + docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../reference/types/datatypes/aabb2d.md | 20 + rerun_cpp/src/rerun/blueprint/archetypes.hpp | 1 + .../rerun/blueprint/archetypes/.gitattributes | 2 + .../blueprint/archetypes/visual_bounds.cpp | 33 ++ .../blueprint/archetypes/visual_bounds.hpp | 64 +++ rerun_cpp/src/rerun/components.hpp | 1 + rerun_cpp/src/rerun/components/.gitattributes | 1 + rerun_cpp/src/rerun/components/aabb2d.hpp | 54 +++ rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + rerun_cpp/src/rerun/datatypes/aabb2d.cpp | 91 ++++ rerun_cpp/src/rerun/datatypes/aabb2d.hpp | 54 +++ .../rerun/blueprint/archetypes/.gitattributes | 1 + .../rerun/blueprint/archetypes/__init__.py | 2 + .../blueprint/archetypes/visual_bounds.py | 69 +++ .../rerun/blueprint/views/spatial2d_view.py | 11 + .../rerun_sdk/rerun/components/.gitattributes | 1 + .../rerun_sdk/rerun/components/__init__.py | 4 + rerun_py/rerun_sdk/rerun/components/aabb2d.py | 28 ++ .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py | 90 ++++ 48 files changed, 1425 insertions(+), 3 deletions(-) create mode 100644 crates/re_query/src/latest_at/to_archetype/visual_bounds.rs create mode 100644 crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs create mode 100644 crates/re_types/definitions/rerun/components/aabb2d.fbs create mode 100644 crates/re_types/definitions/rerun/datatypes/aabb2d.fbs create mode 100644 crates/re_types/src/blueprint/archetypes/visual_bounds.rs create mode 100644 crates/re_types/src/components/aabb2d.rs create mode 100644 crates/re_types/src/datatypes/aabb2d.rs create mode 100644 docs/content/reference/types/components/aabb2d.md create mode 100644 docs/content/reference/types/datatypes/aabb2d.md create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp create mode 100644 rerun_cpp/src/rerun/components/aabb2d.hpp create mode 100644 rerun_cpp/src/rerun/datatypes/aabb2d.cpp create mode 100644 rerun_cpp/src/rerun/datatypes/aabb2d.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py create mode 100644 rerun_py/rerun_sdk/rerun/components/aabb2d.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py diff --git a/crates/re_query/src/latest_at/to_archetype/.gitattributes b/crates/re_query/src/latest_at/to_archetype/.gitattributes index d8ec507351e..e128a891fe9 100644 --- a/crates/re_query/src/latest_at/to_archetype/.gitattributes +++ b/crates/re_query/src/latest_at/to_archetype/.gitattributes @@ -36,3 +36,4 @@ text_log.rs linguist-generated=true transform3d.rs linguist-generated=true view_coordinates.rs linguist-generated=true viewport_blueprint.rs linguist-generated=true +visual_bounds.rs linguist-generated=true diff --git a/crates/re_query/src/latest_at/to_archetype/mod.rs b/crates/re_query/src/latest_at/to_archetype/mod.rs index 62d7ff7df88..4ce8223cadd 100644 --- a/crates/re_query/src/latest_at/to_archetype/mod.rs +++ b/crates/re_query/src/latest_at/to_archetype/mod.rs @@ -34,3 +34,4 @@ mod text_log; mod transform3d; mod view_coordinates; mod viewport_blueprint; +mod visual_bounds; diff --git a/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs b/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs new file mode 100644 index 00000000000..49d60ad0b78 --- /dev/null +++ b/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs @@ -0,0 +1,44 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] + +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for LatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::AABB2D; + let visual_bounds = if let Some(visual_bounds) = self.get(::name()) { + match visual_bounds.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::VisualBounds { visual_bounds }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index cdd2507c57e..ad647ab9f5f 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -31,7 +31,7 @@ pub struct View2DState { /// The visible parts of the scene, in the coordinate space of the scene. /// /// Everything within these bounds are guaranteed to be visible. - /// Some thing outside of these bounds may also be visible due to letterboxing. + /// Somethings outside of these bounds may also be visible due to letterboxing. /// /// Default: [`Rect::NAN`] (invalid). /// Invalid bound will be set to the default on the next frame. diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index a28b8c19f61..5d8717d4f60 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -30,6 +30,7 @@ include "./blueprint/archetypes/panel_blueprint.fbs"; include "./blueprint/archetypes/space_view_blueprint.fbs"; include "./blueprint/archetypes/space_view_contents.fbs"; include "./blueprint/archetypes/viewport_blueprint.fbs"; +include "./blueprint/archetypes/visual_bounds.fbs"; include "./blueprint/archetypes/plot_legend.fbs"; include "./blueprint/archetypes/scalar_axis.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs index bdb5e1546fd..eb4221620ea 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs @@ -8,8 +8,6 @@ include "rerun/attributes.fbs"; namespace rerun.blueprint.archetypes; -// --- - /// Configuration for the background of a view. table Background ( "attr.python.aliases": "datatypes.Rgba32Like, blueprint_components.BackgroundKindLike", diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs new file mode 100644 index 00000000000..aa0b4b26727 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs @@ -0,0 +1,23 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.archetypes; + + +/// Controls the visual bounds of a 2D space view. +table VisualBounds ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "Copy" +) { + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + visual_bounds: rerun.components.AABB2D ("attr.rerun.component_optional", nullable, order: 1000); + + // Here we'll add things like locking the visual bounds of one space view to another +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs index e133d2c41e7..86063fc7d09 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs @@ -8,4 +8,10 @@ table Spatial2DView ( ) { /// Configuration for the background of the space view. background: rerun.blueprint.archetypes.Background (order: 1000); + + /// The visible parts of the scene, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + visual_bounds: rerun.blueprint.archetypes.VisualBounds (order: 2000); } diff --git a/crates/re_types/definitions/rerun/components.fbs b/crates/re_types/definitions/rerun/components.fbs index 251b7f943b5..8ee16c67e9b 100644 --- a/crates/re_types/definitions/rerun/components.fbs +++ b/crates/re_types/definitions/rerun/components.fbs @@ -1,3 +1,4 @@ +include "./components/aabb2d.fbs"; include "./components/annotation_context.fbs"; include "./components/blob.fbs"; include "./components/class_id.fbs"; diff --git a/crates/re_types/definitions/rerun/components/aabb2d.fbs b/crates/re_types/definitions/rerun/components/aabb2d.fbs new file mode 100644 index 00000000000..b2264019b7e --- /dev/null +++ b/crates/re_types/definitions/rerun/components/aabb2d.fbs @@ -0,0 +1,18 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "fbs/attributes.fbs"; +include "rust/attributes.fbs"; + +include "../datatypes/aabb2d.fbs"; + +namespace rerun.components; + +// --- + +/// An Axis-Aligned Bounding Box in 2D space. +struct AABB2D ( + "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.repr": "transparent" +) { + vector: rerun.datatypes.AABB2D (order: 100); +} diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index d1c52a2f654..23df51535ab 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -1,3 +1,4 @@ +include "./datatypes/aabb2d.fbs"; include "./datatypes/angle.fbs"; include "./datatypes/annotation_info.fbs"; include "./datatypes/bool.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs new file mode 100644 index 00000000000..de3a738a23d --- /dev/null +++ b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs @@ -0,0 +1,21 @@ +include "arrow/attributes.fbs"; +include "cpp/attributes.fbs"; +include "fbs/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +namespace rerun.datatypes; + +// --- + +/// An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. +struct AABB2D ( + "attr.rust.derive": "Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.repr": "C" +) { + /// The minimum bounds; usually left-top corner. + min_xy: [double: 2] (order: 100); + + /// The maximum bounds; usually right-bottom corner. + max_xy: [double: 2] (order: 200); +} diff --git a/crates/re_types/src/blueprint/archetypes/.gitattributes b/crates/re_types/src/blueprint/archetypes/.gitattributes index 003fc96d78d..99631b4ea01 100644 --- a/crates/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/re_types/src/blueprint/archetypes/.gitattributes @@ -7,3 +7,4 @@ plot_legend.rs linguist-generated=true scalar_axis.rs linguist-generated=true space_view_blueprint.rs linguist-generated=true space_view_contents.rs linguist-generated=true +visual_bounds.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/archetypes/mod.rs b/crates/re_types/src/blueprint/archetypes/mod.rs index 6fcc74f24ee..bca93c2d48e 100644 --- a/crates/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/re_types/src/blueprint/archetypes/mod.rs @@ -6,9 +6,11 @@ mod plot_legend; mod scalar_axis; mod space_view_blueprint; mod space_view_contents; +mod visual_bounds; pub use self::background::Background; pub use self::plot_legend::PlotLegend; pub use self::scalar_axis::ScalarAxis; pub use self::space_view_blueprint::SpaceViewBlueprint; pub use self::space_view_contents::SpaceViewContents; +pub use self::visual_bounds::VisualBounds; diff --git a/crates/re_types/src/blueprint/archetypes/visual_bounds.rs b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs new file mode 100644 index 00000000000..f6e3a0c1fc1 --- /dev/null +++ b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs @@ -0,0 +1,159 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Controls the visual bounds of a 2D space view. +#[derive(Clone, Debug, Copy)] +pub struct VisualBounds { + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + pub visual_bounds: Option, +} + +impl ::re_types_core::SizeBytes for VisualBounds { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.visual_bounds.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.VisualBoundsIndicator".into()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.AABB2D".into()]); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.VisualBoundsIndicator".into(), + "rerun.components.AABB2D".into(), + ] + }); + +impl VisualBounds { + pub const NUM_COMPONENTS: usize = 2usize; +} + +/// Indicator component for the [`VisualBounds`] [`::re_types_core::Archetype`] +pub type VisualBoundsIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for VisualBounds { + type Indicator = VisualBoundsIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.VisualBounds".into() + } + + #[inline] + fn indicator() -> MaybeOwnedComponentBatch<'static> { + static INDICATOR: VisualBoundsIndicator = VisualBoundsIndicator::DEFAULT; + MaybeOwnedComponentBatch::Ref(&INDICATOR) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let visual_bounds = if let Some(array) = arrays_by_name.get("rerun.components.AABB2D") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.VisualBounds#visual_bounds")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { visual_bounds }) + } +} + +impl ::re_types_core::AsComponents for VisualBounds { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.visual_bounds + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl VisualBounds { + pub fn new() -> Self { + Self { + visual_bounds: None, + } + } + + #[inline] + pub fn with_visual_bounds( + mut self, + visual_bounds: impl Into, + ) -> Self { + self.visual_bounds = Some(visual_bounds.into()); + self + } +} diff --git a/crates/re_types/src/components/.gitattributes b/crates/re_types/src/components/.gitattributes index 503b4ae31cc..287ee7843db 100644 --- a/crates/re_types/src/components/.gitattributes +++ b/crates/re_types/src/components/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.rs linguist-generated=true annotation_context.rs linguist-generated=true blob.rs linguist-generated=true class_id.rs linguist-generated=true diff --git a/crates/re_types/src/components/aabb2d.rs b/crates/re_types/src/components/aabb2d.rs new file mode 100644 index 00000000000..51bc91ac551 --- /dev/null +++ b/crates/re_types/src/components/aabb2d.rs @@ -0,0 +1,148 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: An Axis-Aligned Bounding Box in 2D space. +#[derive(Clone, Debug, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(transparent)] +pub struct AABB2D(pub crate::datatypes::AABB2D); + +impl ::re_types_core::SizeBytes for AABB2D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for AABB2D { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for AABB2D { + #[inline] + fn borrow(&self) -> &crate::datatypes::AABB2D { + &self.0 + } +} + +impl std::ops::Deref for AABB2D { + type Target = crate::datatypes::AABB2D; + + #[inline] + fn deref(&self) -> &crate::datatypes::AABB2D { + &self.0 + } +} + +::re_types_core::macros::impl_into_cow!(AABB2D); + +impl ::re_types_core::Loggable for AABB2D { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.components.AABB2D".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "min_xy", + DataType::FixedSizeList( + std::sync::Arc::new(Field::new("item", DataType::Float64, false)), + 2usize, + ), + false, + ), + Field::new( + "max_xy", + DataType::FixedSizeList( + std::sync::Arc::new(Field::new("item", DataType::Float64, false)), + 2usize, + ), + false, + ), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = data0_bitmap; + crate::datatypes::AABB2D::to_arrow_opt(data0)? + } + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok(crate::datatypes::AABB2D::from_arrow_opt(arrow_data) + .with_context("rerun.components.AABB2D#vector")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.components.AABB2D#vector") + .with_context("rerun.components.AABB2D")?) + } +} diff --git a/crates/re_types/src/components/mod.rs b/crates/re_types/src/components/mod.rs index 0a5d32a77b5..ebc66e53b93 100644 --- a/crates/re_types/src/components/mod.rs +++ b/crates/re_types/src/components/mod.rs @@ -1,5 +1,6 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +mod aabb2d; mod annotation_context; mod blob; mod blob_ext; @@ -68,6 +69,7 @@ mod vector3d_ext; mod view_coordinates; mod view_coordinates_ext; +pub use self::aabb2d::AABB2D; pub use self::annotation_context::AnnotationContext; pub use self::blob::Blob; pub use self::class_id::ClassId; diff --git a/crates/re_types/src/datatypes/.gitattributes b/crates/re_types/src/datatypes/.gitattributes index bb3603b3cdd..f14598e3fbb 100644 --- a/crates/re_types/src/datatypes/.gitattributes +++ b/crates/re_types/src/datatypes/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.rs linguist-generated=true angle.rs linguist-generated=true annotation_info.rs linguist-generated=true bool.rs linguist-generated=true diff --git a/crates/re_types/src/datatypes/aabb2d.rs b/crates/re_types/src/datatypes/aabb2d.rs new file mode 100644 index 00000000000..a4d96a8ed33 --- /dev/null +++ b/crates/re_types/src/datatypes/aabb2d.rs @@ -0,0 +1,434 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. +#[derive(Clone, Debug, Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(C)] +pub struct AABB2D { + /// The minimum bounds; usually left-top corner. + pub min_xy: [f64; 2usize], + + /// The maximum bounds; usually right-bottom corner. + pub max_xy: [f64; 2usize], +} + +impl ::re_types_core::SizeBytes for AABB2D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.min_xy.heap_size_bytes() + self.max_xy.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + <[f64; 2usize]>::is_pod() && <[f64; 2usize]>::is_pod() + } +} + +::re_types_core::macros::impl_into_cow!(AABB2D); + +impl ::re_types_core::Loggable for AABB2D { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.datatypes.AABB2D".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "min_xy", + DataType::FixedSizeList( + std::sync::Arc::new(Field::new("item", DataType::Float64, false)), + 2usize, + ), + false, + ), + Field::new( + "max_xy", + DataType::FixedSizeList( + std::sync::Arc::new(Field::new("item", DataType::Float64, false)), + 2usize, + ), + false, + ), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + (datum.is_some(), datum) + }) + .unzip(); + let bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + StructArray::new( + ::arrow_datatype(), + vec![ + { + let (somes, min_xy): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { min_xy, .. } = &**datum; + min_xy.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let min_xy_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; + let min_xy_inner_data: Vec<_> = min_xy + .iter() + .flat_map(|v| match v { + Some(v) => itertools::Either::Left(v.iter().cloned()), + None => itertools::Either::Right( + std::iter::repeat(Default::default()).take(2usize), + ), + }) + .map(Some) + .collect(); + let min_xy_inner_bitmap: Option = + min_xy_bitmap.as_ref().map(|bitmap| { + bitmap + .iter() + .map(|i| std::iter::repeat(i).take(2usize)) + .flatten() + .collect::>() + .into() + }); + FixedSizeListArray::new( + DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float64, + false, + )), + 2usize, + ), + PrimitiveArray::new( + DataType::Float64, + min_xy_inner_data + .into_iter() + .map(|v| v.unwrap_or_default()) + .collect(), + min_xy_inner_bitmap, + ) + .boxed(), + min_xy_bitmap, + ) + .boxed() + } + }, + { + let (somes, max_xy): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { max_xy, .. } = &**datum; + max_xy.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let max_xy_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; + let max_xy_inner_data: Vec<_> = max_xy + .iter() + .flat_map(|v| match v { + Some(v) => itertools::Either::Left(v.iter().cloned()), + None => itertools::Either::Right( + std::iter::repeat(Default::default()).take(2usize), + ), + }) + .map(Some) + .collect(); + let max_xy_inner_bitmap: Option = + max_xy_bitmap.as_ref().map(|bitmap| { + bitmap + .iter() + .map(|i| std::iter::repeat(i).take(2usize)) + .flatten() + .collect::>() + .into() + }); + FixedSizeListArray::new( + DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float64, + false, + )), + 2usize, + ), + PrimitiveArray::new( + DataType::Float64, + max_xy_inner_data + .into_iter() + .map(|v| v.unwrap_or_default()) + .collect(), + max_xy_inner_bitmap, + ) + .boxed(), + max_xy_bitmap, + ) + .boxed() + } + }, + ], + bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok({ + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let (arrow_data_fields, arrow_data_arrays) = + (arrow_data.fields(), arrow_data.values()); + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data_fields + .iter() + .map(|field| field.name.as_str()) + .zip(arrow_data_arrays) + .collect(); + let min_xy = { + if !arrays_by_name.contains_key("min_xy") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "min_xy", + )) + .with_context("rerun.datatypes.AABB2D"); + } + let arrow_data = &**arrays_by_name["min_xy"]; + { + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float64, + false, + )), + 2usize, + ); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#min_xy")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let offsets = (0..) + .step_by(2usize) + .zip((2usize..).step_by(2usize).take(arrow_data.len())); + let arrow_data_inner = { + let arrow_data_inner = &**arrow_data.values(); + arrow_data_inner + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::Float64; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#min_xy")? + .into_iter() + .map(|opt| opt.copied()) + .collect::>() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets, + arrow_data.validity(), + ) + .map(|elem| { + elem.map(|(start, end)| { + debug_assert!(end - start == 2usize); + if end as usize > arrow_data_inner.len() { + return Err(DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner.len(), + )); + } + + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let data = unsafe { + arrow_data_inner.get_unchecked(start as usize..end as usize) + }; + let data = data.iter().cloned().map(Option::unwrap_or_default); + let arr = array_init::from_iter(data).unwrap(); + Ok(arr) + }) + .transpose() + }) + .collect::>>>()? + } + .into_iter() + } + }; + let max_xy = { + if !arrays_by_name.contains_key("max_xy") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "max_xy", + )) + .with_context("rerun.datatypes.AABB2D"); + } + let arrow_data = &**arrays_by_name["max_xy"]; + { + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float64, + false, + )), + 2usize, + ); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#max_xy")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let offsets = (0..) + .step_by(2usize) + .zip((2usize..).step_by(2usize).take(arrow_data.len())); + let arrow_data_inner = { + let arrow_data_inner = &**arrow_data.values(); + arrow_data_inner + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::Float64; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#max_xy")? + .into_iter() + .map(|opt| opt.copied()) + .collect::>() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets, + arrow_data.validity(), + ) + .map(|elem| { + elem.map(|(start, end)| { + debug_assert!(end - start == 2usize); + if end as usize > arrow_data_inner.len() { + return Err(DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner.len(), + )); + } + + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let data = unsafe { + arrow_data_inner.get_unchecked(start as usize..end as usize) + }; + let data = data.iter().cloned().map(Option::unwrap_or_default); + let arr = array_init::from_iter(data).unwrap(); + Ok(arr) + }) + .transpose() + }) + .collect::>>>()? + } + .into_iter() + } + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + ::itertools::izip!(min_xy, max_xy), + arrow_data.validity(), + ) + .map(|opt| { + opt.map(|(min_xy, max_xy)| { + Ok(Self { + min_xy: min_xy + .ok_or_else(DeserializationError::missing_data) + .with_context("rerun.datatypes.AABB2D#min_xy")?, + max_xy: max_xy + .ok_or_else(DeserializationError::missing_data) + .with_context("rerun.datatypes.AABB2D#max_xy")?, + }) + }) + .transpose() + }) + .collect::>>() + .with_context("rerun.datatypes.AABB2D")? + } + }) + } +} diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index 02fdfd040b3..43116858990 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -1,5 +1,6 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +mod aabb2d; mod angle; mod angle_ext; mod annotation_info; @@ -61,6 +62,7 @@ mod vec3d_ext; mod vec4d; mod vec4d_ext; +pub use self::aabb2d::AABB2D; pub use self::angle::Angle; pub use self::annotation_info::AnnotationInfo; pub use self::bool::Bool; diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md index 2acb3837ee1..554e9e4cb07 100644 --- a/docs/content/reference/types/components.md +++ b/docs/content/reference/types/components.md @@ -14,6 +14,7 @@ For more information on the relationship between **archetypes** and **components on [Entities and Components](../../concepts/entity-component.md). +* [`AABB2D`](components/aabb2d.md): An Axis-Aligned Bounding Box in 2D space. * [`AnnotationContext`](components/annotation_context.md): The `AnnotationContext` provides additional information on how to display entities. * [`Blob`](components/blob.md): A binary blob of data. * [`ClassId`](components/class_id.md): A 16-bit ID representing a type of semantic class. diff --git a/docs/content/reference/types/components/.gitattributes b/docs/content/reference/types/components/.gitattributes index 463f9186673..6522ac09f2f 100644 --- a/docs/content/reference/types/components/.gitattributes +++ b/docs/content/reference/types/components/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.md linguist-generated=true annotation_context.md linguist-generated=true blob.md linguist-generated=true class_id.md linguist-generated=true diff --git a/docs/content/reference/types/components/aabb2d.md b/docs/content/reference/types/components/aabb2d.md new file mode 100644 index 00000000000..6ca71b7056c --- /dev/null +++ b/docs/content/reference/types/components/aabb2d.md @@ -0,0 +1,16 @@ +--- +title: "AABB2D" +--- + +An Axis-Aligned Bounding Box in 2D space. + +## Fields + +* vector: [`AABB2D`](../datatypes/aabb2d.md) + +## Links + * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AABB2D.html) + * 🐍 [Python API docs for `AABB2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AABB2D) + * 🦀 [Rust API docs for `AABB2D`](https://docs.rs/rerun/latest/rerun/components/struct.AABB2D.html) + + diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 8b94d62c025..e56bfd384f0 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -8,6 +8,7 @@ order: 3 Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components. +* [`AABB2D`](datatypes/aabb2d.md): An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. * [`Angle`](datatypes/angle.md): Angle in either radians or degrees. * [`AnnotationInfo`](datatypes/annotation_info.md): Annotation info annotating a class id or key-point id. * [`Bool`](datatypes/bool.md): A single boolean. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index e4b7aacfd94..cd80d78a173 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.md linguist-generated=true angle.md linguist-generated=true annotation_info.md linguist-generated=true bool.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/aabb2d.md b/docs/content/reference/types/datatypes/aabb2d.md new file mode 100644 index 00000000000..6a41f414c95 --- /dev/null +++ b/docs/content/reference/types/datatypes/aabb2d.md @@ -0,0 +1,20 @@ +--- +title: "AABB2D" +--- + +An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. + +## Fields + +* min_xy: 2x `f64` +* max_xy: 2x `f64` + +## Links + * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1AABB2D.html) + * 🐍 [Python API docs for `AABB2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.AABB2D) + * 🦀 [Rust API docs for `AABB2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.AABB2D.html) + + +## Used by + +* [`AABB2D`](../components/aabb2d.md) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index 52de82f4046..b9d8de9e0b2 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -10,3 +10,4 @@ #include "blueprint/archetypes/space_view_blueprint.hpp" #include "blueprint/archetypes/space_view_contents.hpp" #include "blueprint/archetypes/viewport_blueprint.hpp" +#include "blueprint/archetypes/visual_bounds.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 70303c75a9e..5b5e203daea 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -17,3 +17,5 @@ space_view_contents.cpp linguist-generated=true space_view_contents.hpp linguist-generated=true viewport_blueprint.cpp linguist-generated=true viewport_blueprint.hpp linguist-generated=true +visual_bounds.cpp linguist-generated=true +visual_bounds.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp new file mode 100644 index 00000000000..575ab5c1119 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp @@ -0,0 +1,33 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +#include "visual_bounds.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::VisualBounds& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(2); + + if (archetype.visual_bounds.has_value()) { + auto result = DataCell::from_loggable(archetype.visual_bounds.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = VisualBounds::IndicatorComponent(); + auto result = DataCell::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp new file mode 100644 index 00000000000..c9c88725f05 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp @@ -0,0 +1,64 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +#pragma once + +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../components/aabb2d.hpp" +#include "../../data_cell.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Controls the visual bounds of a 2D space view. + struct VisualBounds { + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + std::optional visual_bounds; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.VisualBoundsIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + VisualBounds() = default; + VisualBounds(VisualBounds&& other) = default; + + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + VisualBounds with_visual_bounds(rerun::components::AABB2D _visual_bounds) && { + visual_bounds = std::move(_visual_bounds); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::VisualBounds& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/components.hpp b/rerun_cpp/src/rerun/components.hpp index 02dcde49398..4e818c0b9b7 100644 --- a/rerun_cpp/src/rerun/components.hpp +++ b/rerun_cpp/src/rerun/components.hpp @@ -2,6 +2,7 @@ #pragma once +#include "components/aabb2d.hpp" #include "components/annotation_context.hpp" #include "components/blob.hpp" #include "components/class_id.hpp" diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index 275437bb55f..1bfb2e51134 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.hpp linguist-generated=true annotation_context.cpp linguist-generated=true annotation_context.hpp linguist-generated=true blob.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/aabb2d.hpp b/rerun_cpp/src/rerun/components/aabb2d.hpp new file mode 100644 index 00000000000..c31753d4909 --- /dev/null +++ b/rerun_cpp/src/rerun/components/aabb2d.hpp @@ -0,0 +1,54 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". + +#pragma once + +#include "../datatypes/aabb2d.hpp" +#include "../result.hpp" + +#include +#include + +namespace rerun::components { + /// **Component**: An Axis-Aligned Bounding Box in 2D space. + struct AABB2D { + rerun::datatypes::AABB2D vector; + + public: + AABB2D() = default; + + AABB2D(rerun::datatypes::AABB2D vector_) : vector(vector_) {} + + AABB2D& operator=(rerun::datatypes::AABB2D vector_) { + vector = vector_; + return *this; + } + + /// Cast to the underlying AABB2D datatype + operator rerun::datatypes::AABB2D() const { + return vector; + } + }; +} // namespace rerun::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::AABB2D) == sizeof(components::AABB2D)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.components.AABB2D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::components::AABB2D` into an arrow array. + static Result> to_arrow( + const components::AABB2D* instances, size_t num_instances + ) { + return Loggable::to_arrow(&instances->vector, num_instances); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 6c5f01a1c54..7b47facd6c3 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -2,6 +2,7 @@ #pragma once +#include "datatypes/aabb2d.hpp" #include "datatypes/angle.hpp" #include "datatypes/annotation_info.hpp" #include "datatypes/bool.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 108c39703f4..34f722d5efa 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -1,6 +1,8 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.cpp linguist-generated=true +aabb2d.hpp linguist-generated=true angle.cpp linguist-generated=true angle.hpp linguist-generated=true annotation_info.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp new file mode 100644 index 00000000000..0fa2c12c96f --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp @@ -0,0 +1,91 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +#include "aabb2d.hpp" + +#include +#include + +namespace rerun::datatypes {} + +namespace rerun { + const std::shared_ptr& Loggable::arrow_datatype() { + static const auto datatype = arrow::struct_({ + arrow::field( + "min_xy", + arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2), + false + ), + arrow::field( + "max_xy", + arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2), + false + ), + }); + return datatype; + } + + Result> Loggable::to_arrow( + const datatypes::AABB2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::AABB2D* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + { + auto field_builder = + static_cast(builder->field_builder(0)); + auto value_builder = static_cast(field_builder->value_builder()); + + ARROW_RETURN_NOT_OK(field_builder->AppendValues(static_cast(num_elements))); + static_assert(sizeof(elements[0].min_xy) == sizeof(elements[0])); + ARROW_RETURN_NOT_OK(value_builder->AppendValues( + elements[0].min_xy.data(), + static_cast(num_elements * 2), + nullptr + )); + } + { + auto field_builder = + static_cast(builder->field_builder(1)); + auto value_builder = static_cast(field_builder->value_builder()); + + ARROW_RETURN_NOT_OK(field_builder->AppendValues(static_cast(num_elements))); + static_assert(sizeof(elements[0].max_xy) == sizeof(elements[0])); + ARROW_RETURN_NOT_OK(value_builder->AppendValues( + elements[0].max_xy.data(), + static_cast(num_elements * 2), + nullptr + )); + } + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp new file mode 100644 index 00000000000..6e1952ddbfe --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp @@ -0,0 +1,54 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +#pragma once + +#include "../result.hpp" + +#include +#include +#include + +namespace arrow { + class Array; + class DataType; + class StructBuilder; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. + struct AABB2D { + /// The minimum bounds; usually left-top corner. + std::array min_xy; + + /// The maximum bounds; usually right-bottom corner. + std::array max_xy; + + public: + AABB2D() = default; + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.AABB2D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::datatypes::AABB2D` into an arrow array. + static Result> to_arrow( + const datatypes::AABB2D* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::AABB2D* elements, size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index e7b8aeea825..4b50b7734d1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -10,3 +10,4 @@ scalar_axis.py linguist-generated=true space_view_blueprint.py linguist-generated=true space_view_contents.py linguist-generated=true viewport_blueprint.py linguist-generated=true +visual_bounds.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 79504acb357..45f5321955a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -10,6 +10,7 @@ from .space_view_blueprint import SpaceViewBlueprint from .space_view_contents import SpaceViewContents from .viewport_blueprint import ViewportBlueprint +from .visual_bounds import VisualBounds __all__ = [ "Background", @@ -20,4 +21,5 @@ "SpaceViewBlueprint", "SpaceViewContents", "ViewportBlueprint", + "VisualBounds", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py new file mode 100644 index 00000000000..f9037ec6a12 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py @@ -0,0 +1,69 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +# You can extend this class by creating a "VisualBoundsExt" class in "visual_bounds_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import components, datatypes +from ..._baseclasses import Archetype +from ...error_utils import catch_and_log_exceptions + +__all__ = ["VisualBounds"] + + +@define(str=False, repr=False, init=False) +class VisualBounds(Archetype): + """**Archetype**: Controls the visual bounds of a 2D space view.""" + + def __init__(self: Any, *, visual_bounds: datatypes.AABB2DLike | None = None): + """ + Create a new instance of the VisualBounds archetype. + + Parameters + ---------- + visual_bounds: + The visible parts of a 2D space view, in the coordinate space of the scene. + + Everything within these bounds are guaranteed to be visible. + Somethings outside of these bounds may also be visible due to letterboxing. + + """ + + # You can define your own __init__ function as a member of VisualBoundsExt in visual_bounds_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(visual_bounds=visual_bounds) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + visual_bounds=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> VisualBounds: + """Produce an empty VisualBounds, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + visual_bounds: components.AABB2DBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.AABB2DBatch._optional, # type: ignore[misc] + ) + # The visible parts of a 2D space view, in the coordinate space of the scene. + # + # Everything within these bounds are guaranteed to be visible. + # Somethings outside of these bounds may also be visible due to letterboxing. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py index ae31233af77..fa065d25be7 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py @@ -28,6 +28,7 @@ def __init__( | datatypes.Rgba32Like | blueprint_components.BackgroundKindLike | None = None, + visual_bounds: blueprint_archetypes.VisualBounds | None = None, ) -> None: """ Construct a blueprint for a new Spatial2DView view. @@ -49,6 +50,11 @@ def __init__( Defaults to true if not specified. background: Configuration for the background of the space view. + visual_bounds: + The visible parts of the scene, in the coordinate space of the scene. + + Everything within these bounds are guaranteed to be visible. + Somethings outside of these bounds may also be visible due to letterboxing. """ @@ -58,6 +64,11 @@ def __init__( background = blueprint_archetypes.Background(background) properties["Background"] = background + if visual_bounds is not None: + if not isinstance(visual_bounds, blueprint_archetypes.VisualBounds): + visual_bounds = blueprint_archetypes.VisualBounds(visual_bounds) + properties["VisualBounds"] = visual_bounds + super().__init__( class_identifier="2D", origin=origin, contents=contents, name=name, visible=visible, properties=properties ) diff --git a/rerun_py/rerun_sdk/rerun/components/.gitattributes b/rerun_py/rerun_sdk/rerun/components/.gitattributes index 12b4a9826e3..f7f22c69997 100644 --- a/rerun_py/rerun_sdk/rerun/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/components/.gitattributes @@ -2,6 +2,7 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true +aabb2d.py linguist-generated=true annotation_context.py linguist-generated=true blob.py linguist-generated=true class_id.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 2710c971bed..0c7615bd6e3 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .aabb2d import AABB2D, AABB2DBatch, AABB2DType from .annotation_context import ( AnnotationContext, AnnotationContextArrayLike, @@ -79,6 +80,9 @@ ) __all__ = [ + "AABB2D", + "AABB2DBatch", + "AABB2DType", "AnnotationContext", "AnnotationContextArrayLike", "AnnotationContextBatch", diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d.py b/rerun_py/rerun_sdk/rerun/components/aabb2d.py new file mode 100644 index 00000000000..c6ad6c4d6c8 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/aabb2d.py @@ -0,0 +1,28 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". + +# You can extend this class by creating a "AABB2DExt" class in "aabb2d_ext.py". + +from __future__ import annotations + +from .. import datatypes +from .._baseclasses import ComponentBatchMixin + +__all__ = ["AABB2D", "AABB2DBatch", "AABB2DType"] + + +class AABB2D(datatypes.AABB2D): + """**Component**: An Axis-Aligned Bounding Box in 2D space.""" + + # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py + + # Note: there are no fields here because AABB2D delegates to datatypes.AABB2D + pass + + +class AABB2DType(datatypes.AABB2DType): + _TYPE_NAME: str = "rerun.components.AABB2D" + + +class AABB2DBatch(datatypes.AABB2DBatch, ComponentBatchMixin): + _ARROW_TYPE = AABB2DType() diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index d5a5eadf37f..9a04afcec6f 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -2,6 +2,7 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true +aabb2d.py linguist-generated=true angle.py linguist-generated=true annotation_info.py linguist-generated=true bool.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 58f639584e8..717aac102f4 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .aabb2d import AABB2D, AABB2DArrayLike, AABB2DBatch, AABB2DLike, AABB2DType from .angle import Angle, AngleArrayLike, AngleBatch, AngleLike, AngleType from .annotation_info import ( AnnotationInfo, @@ -89,6 +90,11 @@ from .vec4d import Vec4D, Vec4DArrayLike, Vec4DBatch, Vec4DLike, Vec4DType __all__ = [ + "AABB2D", + "AABB2DArrayLike", + "AABB2DBatch", + "AABB2DLike", + "AABB2DType", "Angle", "AngleArrayLike", "AngleBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py new file mode 100644 index 00000000000..3237db6fbed --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py @@ -0,0 +1,90 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +# You can extend this class by creating a "AABB2DExt" class in "aabb2d_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import numpy as np +import numpy.typing as npt +import pyarrow as pa +from attrs import define, field + +from .._baseclasses import BaseBatch, BaseExtensionType +from .._converters import ( + to_np_float64, +) + +__all__ = ["AABB2D", "AABB2DArrayLike", "AABB2DBatch", "AABB2DLike", "AABB2DType"] + + +@define(init=False) +class AABB2D: + """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" + + def __init__(self: Any, min_xy: npt.ArrayLike, max_xy: npt.ArrayLike): + """ + Create a new instance of the AABB2D datatype. + + Parameters + ---------- + min_xy: + The minimum bounds; usually left-top corner. + max_xy: + The maximum bounds; usually right-bottom corner. + + """ + + # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py + self.__attrs_init__(min_xy=min_xy, max_xy=max_xy) + + min_xy: npt.NDArray[np.float64] = field(converter=to_np_float64) + # The minimum bounds; usually left-top corner. + # + # (Docstring intentionally commented out to hide this field from the docs) + + max_xy: npt.NDArray[np.float64] = field(converter=to_np_float64) + # The maximum bounds; usually right-bottom corner. + # + # (Docstring intentionally commented out to hide this field from the docs) + + +AABB2DLike = AABB2D +AABB2DArrayLike = Union[ + AABB2D, + Sequence[AABB2DLike], +] + + +class AABB2DType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.AABB2D" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct([ + pa.field( + "min_xy", + pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), + nullable=False, + metadata={}, + ), + pa.field( + "max_xy", + pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), + nullable=False, + metadata={}, + ), + ]), + self._TYPE_NAME, + ) + + +class AABB2DBatch(BaseBatch[AABB2DArrayLike]): + _ARROW_TYPE = AABB2DType() + + @staticmethod + def _native_to_pa_array(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in aabb2d_ext.py From 85f8b2762cac18a4c565b6f835ddfb1d89ddd3b8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 26 Apr 2024 10:09:38 +0200 Subject: [PATCH 02/20] Move VisualBounds to the blueprint store --- Cargo.lock | 1 + crates/re_space_view/src/lib.rs | 5 +- crates/re_space_view/src/sub_archetypes.rs | 37 +++- .../src/space_view_2d.rs | 48 +++-- crates/re_space_view_spatial/src/ui.rs | 3 +- crates/re_space_view_spatial/src/ui_2d.rs | 202 +++++++++--------- crates/re_types/Cargo.toml | 1 + crates/re_types/src/components/aabb2d_ext.rs | 11 + crates/re_types/src/components/mod.rs | 1 + crates/re_types/src/datatypes/aabb2d_ext.rs | 21 ++ crates/re_types/src/datatypes/mod.rs | 1 + 11 files changed, 207 insertions(+), 124 deletions(-) create mode 100644 crates/re_types/src/components/aabb2d_ext.rs create mode 100644 crates/re_types/src/datatypes/aabb2d_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 017c403cf71..2ce17459364 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4858,6 +4858,7 @@ dependencies = [ "document-features", "ecolor", "egui_plot", + "emath", "glam", "half 2.3.1", "image", diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 25255c2a835..52b0dcc97b1 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -18,8 +18,9 @@ pub use screenshot::ScreenshotMode; pub use space_view::SpaceViewBlueprint; pub use space_view_contents::SpaceViewContents; pub use sub_archetypes::{ - entity_path_for_space_view_sub_archetype, query_space_view_sub_archetype, - query_space_view_sub_archetype_or_default, space_view_sub_archetype, + edit_blueprint_component, entity_path_for_space_view_sub_archetype, get_blueprint_component, + query_space_view_sub_archetype, query_space_view_sub_archetype_or_default, + space_view_sub_archetype, }; pub use visual_time_range::{ query_visual_history, time_range_boundary_to_visible_history_boundary, diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 8318470268e..1defe4c291f 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -5,7 +5,7 @@ use re_entity_db::{ }; use re_log_types::EntityPath; use re_types::Archetype; -use re_viewer_context::{external::re_entity_db::EntityTree, SpaceViewId}; +use re_viewer_context::{external::re_entity_db::EntityTree, SpaceViewId, ViewerContext}; pub fn entity_path_for_space_view_sub_archetype( space_view_id: SpaceViewId, @@ -69,3 +69,38 @@ where let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); (arch.ok().flatten().unwrap_or_default(), path) } + +/// Read a single component of a blueprint archetype in a space view. +pub fn get_blueprint_component( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, +) -> Option { + let blueprint_db = ctx.store_context.blueprint; + let query = ctx.blueprint_query; + let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + blueprint_db + .latest_at_component::(&path, query) + .map(|x| x.value) +} + +/// Edit a single component of a blueprint archetype in a space view. +pub fn edit_blueprint_component( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, + edit_component: impl FnOnce(&mut Option) -> R, +) -> R { + let blueprint_db = ctx.store_context.blueprint; + let query = ctx.blueprint_query; + let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + let original = blueprint_db.latest_at_component::(&path, query); + let original: Option = original.map(|x| x.value); + + let mut edited = original.clone(); + let ret = edit_component(&mut edited); + + if edited != original { + ctx.save_blueprint_component(&path, &edited); + } + + ret +} diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 62d07852501..71613bbf8c0 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -6,7 +6,7 @@ use re_format::format_f32; use re_log_types::EntityPath; use re_types::{ archetypes::{DepthImage, Image}, - blueprint::archetypes::Background, + blueprint::archetypes::{Background, VisualBounds}, Archetype, ComponentName, }; use re_viewer_context::{ @@ -254,22 +254,7 @@ impl SpaceViewClass for SpatialSpaceView2D { state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::TwoD); - { - let visual_bounds = &mut state.state_2d.visual_bounds; - ctx.re_ui - .grid_left_hand_label(ui, "Bounds") - .on_hover_text("The area guaranteed to be visible.\nDepending on the view's current aspect ratio the actually visible area might be larger either horizontally or vertically."); - ui.vertical(|ui| { - ui.style_mut().wrap = Some(false); - let (min, max) = (visual_bounds.min, visual_bounds.max); - ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); - ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); - if ui.button("Reset bounds").clicked() { - *visual_bounds = egui::Rect::NAN; - } - }); - ui.end_row(); - } + visual_bounds_ui(ctx, space_view_id, ui); }); Ok(()) } @@ -297,6 +282,35 @@ impl SpaceViewClass for SpatialSpaceView2D { } } +fn visual_bounds_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut egui::Ui) { + let tooltip = "The area guaranteed to be visible.\n\ + Depending on the view's current aspect ratio the actually visible area might be larger either horizontally or vertically."; + re_space_view::edit_blueprint_component::( + ctx, + space_view_id, + |aabb: &mut Option| { + ctx.re_ui + .grid_left_hand_label(ui, "Bounds") + .on_hover_text(tooltip); + ui.vertical(|ui| { + ui.style_mut().wrap = Some(false); + + if let Some(aabb) = aabb { + let rect = egui::Rect::from(*aabb); + let (min, max) = (rect.min, rect.max); + ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); + ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); + } + + if ui.button("Reset bounds").clicked() { + *aabb = None; + } + }); + ui.end_row(); + }, + ); +} + // Count the number of image entities with the given component exist that aren't // children of other entities in the bucket. fn count_non_nested_images_with_component( diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 7099ccdf264..958d6714490 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -27,7 +27,7 @@ use crate::{ }; use crate::{eye::EyeMode, heuristics::auto_size_world_heuristic}; -use super::{eye::Eye, ui_2d::View2DState, ui_3d::View3DState}; +use super::{eye::Eye, ui_3d::View3DState}; /// Default auto point radius in UI points. const AUTO_POINT_RADIUS: f32 = 1.5; @@ -63,7 +63,6 @@ pub struct SpatialSpaceViewState { /// Last frame's picking result. pub previous_picking_result: Option, - pub(super) state_2d: View2DState, pub(super) state_3d: View3DState, /// Size of automatically sized objects. None if it wasn't configured. diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index ad647ab9f5f..960c5a5428e 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -5,11 +5,12 @@ use re_entity_db::EntityPath; use re_renderer::view_builder::{TargetConfiguration, ViewBuilder}; use re_space_view::controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}; use re_types::{ - archetypes::Pinhole, blueprint::archetypes::Background, components::ViewCoordinates, + archetypes::Pinhole, blueprint::archetypes::Background, blueprint::archetypes::VisualBounds, + components::ViewCoordinates, }; use re_viewer_context::{ - gpu_bridge, ItemSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, - ViewerContext, + gpu_bridge, ItemSpaceContext, SpaceViewId, SpaceViewSystemExecutionError, + SystemExecutionOutput, ViewQuery, ViewerContext, }; use super::{ @@ -25,118 +26,115 @@ use crate::{ // --- -#[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)] -#[serde(default)] -pub struct View2DState { - /// The visible parts of the scene, in the coordinate space of the scene. - /// - /// Everything within these bounds are guaranteed to be visible. - /// Somethings outside of these bounds may also be visible due to letterboxing. - /// - /// Default: [`Rect::NAN`] (invalid). - /// Invalid bound will be set to the default on the next frame. - /// The default is usually the scene bounding box. - pub visual_bounds: Rect, -} +/// Pan and zoom, and return the current transform. +fn update_ui_from_scene_impl( + visual_bounds: &mut Rect, + response: &egui::Response, + default_scene_rect: Rect, +) -> RectTransform { + fn valid_bound(rect: &Rect) -> bool { + rect.is_finite() && rect.is_positive() + } -impl Default for View2DState { - fn default() -> Self { - Self { - visual_bounds: Rect::NAN, - } + if response.double_clicked() { + *visual_bounds = default_scene_rect; // double-click to reset } -} -impl View2DState { - /// Pan and zoom, and return the current transform. - fn ui_from_scene( - &mut self, - response: &egui::Response, - default_scene_rect: Rect, - ) -> RectTransform { - fn valid_bound(rect: &Rect) -> bool { - rect.is_finite() && rect.is_positive() - } + if !valid_bound(visual_bounds) { + *visual_bounds = default_scene_rect; + } + if !valid_bound(visual_bounds) { + // Nothing in scene, probably. + // Just return something that isn't NaN. + let fake_bounds = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1.0)); + return RectTransform::from_to(fake_bounds, response.rect); + } - if response.double_clicked() { - self.visual_bounds = default_scene_rect; // double-click to reset - } + // -------------------------------------------------------------------------- + // Expand bounds for uniform scaling (letterboxing): - let bounds = &mut self.visual_bounds; - if !valid_bound(bounds) { - *bounds = default_scene_rect; - } - if !valid_bound(bounds) { - // Nothing in scene, probably. - // Just return something that isn't NaN. - let fake_bounds = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1.0)); - return RectTransform::from_to(fake_bounds, response.rect); - } + let mut letterboxed_bounds = *visual_bounds; - // -------------------------------------------------------------------------- - // Expand bounds for uniform scaling (letterboxing): - - let mut letterboxed_bounds = *bounds; - - // Temporary before applying letterboxing: - let ui_from_scene = RectTransform::from_to(*bounds, response.rect); - - let scale_aspect = ui_from_scene.scale().x / ui_from_scene.scale().y; - if scale_aspect < 1.0 { - // Letterbox top/bottom: - let add = bounds.height() * (1.0 / scale_aspect - 1.0); - letterboxed_bounds.min.y -= 0.5 * add; - letterboxed_bounds.max.y += 0.5 * add; - } else { - // Letterbox sides: - let add = bounds.width() * (scale_aspect - 1.0); - letterboxed_bounds.min.x -= 0.5 * add; - letterboxed_bounds.max.x += 0.5 * add; - } + // Temporary before applying letterboxing: + let ui_from_scene = RectTransform::from_to(*visual_bounds, response.rect); + + let scale_aspect = ui_from_scene.scale().x / ui_from_scene.scale().y; + if scale_aspect < 1.0 { + // Letterbox top/bottom: + let add = visual_bounds.height() * (1.0 / scale_aspect - 1.0); + letterboxed_bounds.min.y -= 0.5 * add; + letterboxed_bounds.max.y += 0.5 * add; + } else { + // Letterbox sides: + let add = visual_bounds.width() * (scale_aspect - 1.0); + letterboxed_bounds.min.x -= 0.5 * add; + letterboxed_bounds.max.x += 0.5 * add; + } - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - // Temporary before applying panning/zooming delta: - let ui_from_scene = RectTransform::from_to(letterboxed_bounds, response.rect); + // Temporary before applying panning/zooming delta: + let ui_from_scene = RectTransform::from_to(letterboxed_bounds, response.rect); - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - let mut pan_delta_in_ui = response.drag_delta(); - if response.hovered() { - // NOTE: we use `raw_scroll` instead of `smooth_scroll_delta` to avoid the - // added latency of smoothing, which is really annoying on Mac trackpads. - // The smoothing is only useful for users with discreet scroll wheels, - // and they are likely to pan with dragging instead. - // TODO(egui#4401): https://github.com/emilk/egui/issues/4401 - pan_delta_in_ui += response.ctx.input(|i| i.raw_scroll_delta); - } - if pan_delta_in_ui != Vec2::ZERO { - *bounds = bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); - } + let mut pan_delta_in_ui = response.drag_delta(); + if response.hovered() { + // NOTE: we use `raw_scroll` instead of `smooth_scroll_delta` to avoid the + // added latency of smoothing, which is really annoying on Mac trackpads. + // The smoothing is only useful for users with discreet scroll wheels, + // and they are likely to pan with dragging instead. + // TODO(egui#4401): https://github.com/emilk/egui/issues/4401 + pan_delta_in_ui += response.ctx.input(|i| i.raw_scroll_delta); + } + if pan_delta_in_ui != Vec2::ZERO { + *visual_bounds = visual_bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); + } - if response.hovered() { - let zoom_delta = response.ctx.input(|i| i.zoom_delta_2d()); - - if zoom_delta != Vec2::splat(1.0) { - let zoom_center_in_ui = response - .hover_pos() - .unwrap_or_else(|| response.rect.center()); - let zoom_center_in_scene = ui_from_scene - .inverse() - .transform_pos(zoom_center_in_ui) - .to_vec2(); - *bounds = scale_rect( - bounds.translate(-zoom_center_in_scene), - Vec2::splat(1.0) / zoom_delta, - ) - .translate(zoom_center_in_scene); - } + if response.hovered() { + let zoom_delta = response.ctx.input(|i| i.zoom_delta_2d()); + + if zoom_delta != Vec2::splat(1.0) { + let zoom_center_in_ui = response + .hover_pos() + .unwrap_or_else(|| response.rect.center()); + let zoom_center_in_scene = ui_from_scene + .inverse() + .transform_pos(zoom_center_in_ui) + .to_vec2(); + *visual_bounds = scale_rect( + visual_bounds.translate(-zoom_center_in_scene), + Vec2::splat(1.0) / zoom_delta, + ) + .translate(zoom_center_in_scene); } + } - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - RectTransform::from_to(letterboxed_bounds, response.rect) - } + RectTransform::from_to(letterboxed_bounds, response.rect) +} + +fn ui_from_scene( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, + response: &egui::Response, + default_scene_rect: Rect, +) -> RectTransform { + re_space_view::edit_blueprint_component::< + VisualBounds, + re_types::components::AABB2D, + RectTransform, + >( + ctx, + space_view_id, + |aabb: &mut Option| { + let mut rect: Rect = aabb.map_or(default_scene_rect, Rect::from); + let ui_from_scene = update_ui_from_scene_impl(&mut rect, response, default_scene_rect); + *aabb = Some(rect.into()); + ui_from_scene + }, + ) } fn scale_rect(rect: Rect, factor: Vec2) -> Rect { @@ -212,7 +210,7 @@ pub fn view_2d( ui.allocate_painter(ui.available_size(), egui::Sense::click_and_drag()); // Convert ui coordinates to/from scene coordinates. - let ui_from_scene = state.state_2d.ui_from_scene(&response, default_scene_rect); + let ui_from_scene = ui_from_scene(ctx, query.space_view_id, &response, default_scene_rect); let scene_from_ui = ui_from_scene.inverse(); // TODO(andreas): Use the same eye & transformations as in `setup_target_config`. diff --git a/crates/re_types/Cargo.toml b/crates/re_types/Cargo.toml index 36acbbbb195..ab360bae3b0 100644 --- a/crates/re_types/Cargo.toml +++ b/crates/re_types/Cargo.toml @@ -68,6 +68,7 @@ arrow2 = { workspace = true, features = [ ] } bytemuck = { workspace = true, features = ["derive", "extern_crate_alloc"] } document-features.workspace = true +emath.workspace = true half = { workspace = true, features = ["bytemuck"] } infer.workspace = true itertools.workspace = true diff --git a/crates/re_types/src/components/aabb2d_ext.rs b/crates/re_types/src/components/aabb2d_ext.rs new file mode 100644 index 00000000000..7abbf4dffa0 --- /dev/null +++ b/crates/re_types/src/components/aabb2d_ext.rs @@ -0,0 +1,11 @@ +use super::AABB2D; + +impl From for emath::Rect { + #[inline] + fn from(v: AABB2D) -> Self { + Self { + min: emath::pos2(v.min_xy[0] as f32, v.min_xy[1] as f32), + max: emath::pos2(v.max_xy[0] as f32, v.max_xy[1] as f32), + } + } +} diff --git a/crates/re_types/src/components/mod.rs b/crates/re_types/src/components/mod.rs index ebc66e53b93..6bbc7bfca39 100644 --- a/crates/re_types/src/components/mod.rs +++ b/crates/re_types/src/components/mod.rs @@ -1,6 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs mod aabb2d; +mod aabb2d_ext; mod annotation_context; mod blob; mod blob_ext; diff --git a/crates/re_types/src/datatypes/aabb2d_ext.rs b/crates/re_types/src/datatypes/aabb2d_ext.rs new file mode 100644 index 00000000000..a134b154a36 --- /dev/null +++ b/crates/re_types/src/datatypes/aabb2d_ext.rs @@ -0,0 +1,21 @@ +use super::AABB2D; + +impl From for AABB2D { + #[inline] + fn from(v: emath::Rect) -> Self { + Self { + min_xy: [v.min.x as f64, v.min.y as f64], + max_xy: [v.max.x as f64, v.max.y as f64], + } + } +} + +impl From for emath::Rect { + #[inline] + fn from(v: AABB2D) -> Self { + Self { + min: emath::pos2(v.min_xy[0] as f32, v.min_xy[1] as f32), + max: emath::pos2(v.max_xy[0] as f32, v.max_xy[1] as f32), + } + } +} diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index 43116858990..6337fb92fb9 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -1,6 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs mod aabb2d; +mod aabb2d_ext; mod angle; mod angle_ext; mod annotation_info; From 1a286458265cd3ed139d052942102dd35596b18a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 26 Apr 2024 10:48:12 +0200 Subject: [PATCH 03/20] Add constructors for Python, that don't work --- docs/snippets/all/annotation_context_rects.py | 7 ++-- .../rerun_sdk/rerun/blueprint/__init__.py | 1 + .../blueprint/archetypes/visual_bounds.py | 28 +++------------ .../blueprint/archetypes/visual_bounds_ext.py | 35 +++++++++++++++++++ rerun_py/rerun_sdk/rerun/components/aabb2d.py | 5 +-- .../rerun_sdk/rerun/components/aabb2d_ext.py | 31 ++++++++++++++++ 6 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py create mode 100644 rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py diff --git a/docs/snippets/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py index 1c430116d22..1a857cc741b 100644 --- a/docs/snippets/all/annotation_context_rects.py +++ b/docs/snippets/all/annotation_context_rects.py @@ -1,12 +1,11 @@ import rerun as rr +import rerun.blueprint as rrb -rr.init("rerun_example_annotation_context_rects", spawn=True) +blueprint = rrb.Spatial2DView(background=[128, 0, 0], visual_bounds=rrb.VisualBounds(min=[-4.5, -2.5], max=[2.5, 2.5])) +rr.init("rerun_example_annotation_context_rects", spawn=True, default_blueprint=blueprint) # Log an annotation context to assign a label and color to each class rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) - -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[2.5, 2.5])) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 507e7b007d0..8a2e7f0e2db 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -16,6 +16,7 @@ Background, PlotLegend, ScalarAxis, + VisualBounds, ) from .components import ( BackgroundKind, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py index f9037ec6a12..c611cd889a5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py @@ -5,40 +5,20 @@ from __future__ import annotations -from typing import Any - from attrs import define, field -from ... import components, datatypes +from ... import components from ..._baseclasses import Archetype -from ...error_utils import catch_and_log_exceptions +from .visual_bounds_ext import VisualBoundsExt __all__ = ["VisualBounds"] @define(str=False, repr=False, init=False) -class VisualBounds(Archetype): +class VisualBounds(VisualBoundsExt, Archetype): """**Archetype**: Controls the visual bounds of a 2D space view.""" - def __init__(self: Any, *, visual_bounds: datatypes.AABB2DLike | None = None): - """ - Create a new instance of the VisualBounds archetype. - - Parameters - ---------- - visual_bounds: - The visible parts of a 2D space view, in the coordinate space of the scene. - - Everything within these bounds are guaranteed to be visible. - Somethings outside of these bounds may also be visible due to letterboxing. - - """ - - # You can define your own __init__ function as a member of VisualBoundsExt in visual_bounds_ext.py - with catch_and_log_exceptions(context=self.__class__.__name__): - self.__attrs_init__(visual_bounds=visual_bounds) - return - self.__attrs_clear__() + # __init__ can be found in visual_bounds_ext.py def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py new file mode 100644 index 00000000000..9124871c061 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from typing import Any + +from ... import components, datatypes +from ...error_utils import catch_and_log_exceptions + + +class VisualBoundsExt: + """Extension for [VisualBounds][rerun.blueprint.archetypes.VisualBounds].""" + + def __init__( + self: Any, + *, + min: datatypes.Vec2DLike, + max: datatypes.Vec2DLike, + ): + """ + Create a new instance of the VisualBounds archetype. + + Parameters + ---------- + min: + The minimum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the left-top corner. + max: + The maximum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the right-bottom corner. + + """ + + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(visual_bounds=components.AABB2D(min=min, max=max)) + return + self.__attrs_clear__() diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d.py b/rerun_py/rerun_sdk/rerun/components/aabb2d.py index c6ad6c4d6c8..16419767704 100644 --- a/rerun_py/rerun_sdk/rerun/components/aabb2d.py +++ b/rerun_py/rerun_sdk/rerun/components/aabb2d.py @@ -7,14 +7,15 @@ from .. import datatypes from .._baseclasses import ComponentBatchMixin +from .aabb2d_ext import AABB2DExt __all__ = ["AABB2D", "AABB2DBatch", "AABB2DType"] -class AABB2D(datatypes.AABB2D): +class AABB2D(AABB2DExt, datatypes.AABB2D): """**Component**: An Axis-Aligned Bounding Box in 2D space.""" - # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py + # __init__ can be found in aabb2d_ext.py # Note: there are no fields here because AABB2D delegates to datatypes.AABB2D pass diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py new file mode 100644 index 00000000000..df15adef97d --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from typing import Any + +from ..datatypes import AABB2D, Vec2DLike + + +class AABB2DExt: + """Extension for [AABB2D][rerun.components.AABB2D].""" + + def __init__( + self: Any, + *, + min: Vec2DLike, + max: Vec2DLike, + ): + """ + Create a new instance of the AABB2D component. + + Parameters + ---------- + min: + The minimum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the left-top corner. + max: + The maximum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the right-bottom corner. + + """ + + self.__attrs_init__(AABB2D(min=min, max=max)) From 1d80315d9e864d3d539a2a9725dcef033b0a4eac Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 26 Apr 2024 11:56:40 +0200 Subject: [PATCH 04/20] Remove the _xy suffix --- .../definitions/rerun/datatypes/aabb2d.fbs | 4 +- crates/re_types/src/components/aabb2d.rs | 4 +- crates/re_types/src/components/aabb2d_ext.rs | 4 +- crates/re_types/src/datatypes/aabb2d.rs | 86 +++++++++---------- crates/re_types/src/datatypes/aabb2d_ext.rs | 8 +- .../reference/types/datatypes/aabb2d.md | 4 +- rerun_cpp/src/rerun/datatypes/aabb2d.cpp | 12 +-- rerun_cpp/src/rerun/datatypes/aabb2d.hpp | 4 +- rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py | 16 ++-- 9 files changed, 71 insertions(+), 71 deletions(-) diff --git a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs index de3a738a23d..c597adcb349 100644 --- a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs +++ b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs @@ -14,8 +14,8 @@ struct AABB2D ( "attr.rust.repr": "C" ) { /// The minimum bounds; usually left-top corner. - min_xy: [double: 2] (order: 100); + min: [double: 2] (order: 100); /// The maximum bounds; usually right-bottom corner. - max_xy: [double: 2] (order: 200); + max: [double: 2] (order: 200); } diff --git a/crates/re_types/src/components/aabb2d.rs b/crates/re_types/src/components/aabb2d.rs index 51bc91ac551..9e782095992 100644 --- a/crates/re_types/src/components/aabb2d.rs +++ b/crates/re_types/src/components/aabb2d.rs @@ -77,7 +77,7 @@ impl ::re_types_core::Loggable for AABB2D { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ Field::new( - "min_xy", + "min", DataType::FixedSizeList( std::sync::Arc::new(Field::new("item", DataType::Float64, false)), 2usize, @@ -85,7 +85,7 @@ impl ::re_types_core::Loggable for AABB2D { false, ), Field::new( - "max_xy", + "max", DataType::FixedSizeList( std::sync::Arc::new(Field::new("item", DataType::Float64, false)), 2usize, diff --git a/crates/re_types/src/components/aabb2d_ext.rs b/crates/re_types/src/components/aabb2d_ext.rs index 7abbf4dffa0..9f93dd2b242 100644 --- a/crates/re_types/src/components/aabb2d_ext.rs +++ b/crates/re_types/src/components/aabb2d_ext.rs @@ -4,8 +4,8 @@ impl From for emath::Rect { #[inline] fn from(v: AABB2D) -> Self { Self { - min: emath::pos2(v.min_xy[0] as f32, v.min_xy[1] as f32), - max: emath::pos2(v.max_xy[0] as f32, v.max_xy[1] as f32), + min: emath::pos2(v.min[0] as f32, v.min[1] as f32), + max: emath::pos2(v.max[0] as f32, v.max[1] as f32), } } } diff --git a/crates/re_types/src/datatypes/aabb2d.rs b/crates/re_types/src/datatypes/aabb2d.rs index a4d96a8ed33..919ad7190b4 100644 --- a/crates/re_types/src/datatypes/aabb2d.rs +++ b/crates/re_types/src/datatypes/aabb2d.rs @@ -27,16 +27,16 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[repr(C)] pub struct AABB2D { /// The minimum bounds; usually left-top corner. - pub min_xy: [f64; 2usize], + pub min: [f64; 2usize], /// The maximum bounds; usually right-bottom corner. - pub max_xy: [f64; 2usize], + pub max: [f64; 2usize], } impl ::re_types_core::SizeBytes for AABB2D { #[inline] fn heap_size_bytes(&self) -> u64 { - self.min_xy.heap_size_bytes() + self.max_xy.heap_size_bytes() + self.min.heap_size_bytes() + self.max.heap_size_bytes() } #[inline] @@ -61,7 +61,7 @@ impl ::re_types_core::Loggable for AABB2D { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ Field::new( - "min_xy", + "min", DataType::FixedSizeList( std::sync::Arc::new(Field::new("item", DataType::Float64, false)), 2usize, @@ -69,7 +69,7 @@ impl ::re_types_core::Loggable for AABB2D { false, ), Field::new( - "max_xy", + "max", DataType::FixedSizeList( std::sync::Arc::new(Field::new("item", DataType::Float64, false)), 2usize, @@ -104,23 +104,23 @@ impl ::re_types_core::Loggable for AABB2D { ::arrow_datatype(), vec![ { - let (somes, min_xy): (Vec<_>, Vec<_>) = data + let (somes, min): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { min_xy, .. } = &**datum; - min_xy.clone() + let Self { min, .. } = &**datum; + min.clone() }); (datum.is_some(), datum) }) .unzip(); - let min_xy_bitmap: Option = { + let min_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; - let min_xy_inner_data: Vec<_> = min_xy + let min_inner_data: Vec<_> = min .iter() .flat_map(|v| match v { Some(v) => itertools::Either::Left(v.iter().cloned()), @@ -130,8 +130,8 @@ impl ::re_types_core::Loggable for AABB2D { }) .map(Some) .collect(); - let min_xy_inner_bitmap: Option = - min_xy_bitmap.as_ref().map(|bitmap| { + let min_inner_bitmap: Option = + min_bitmap.as_ref().map(|bitmap| { bitmap .iter() .map(|i| std::iter::repeat(i).take(2usize)) @@ -150,36 +150,36 @@ impl ::re_types_core::Loggable for AABB2D { ), PrimitiveArray::new( DataType::Float64, - min_xy_inner_data + min_inner_data .into_iter() .map(|v| v.unwrap_or_default()) .collect(), - min_xy_inner_bitmap, + min_inner_bitmap, ) .boxed(), - min_xy_bitmap, + min_bitmap, ) .boxed() } }, { - let (somes, max_xy): (Vec<_>, Vec<_>) = data + let (somes, max): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { max_xy, .. } = &**datum; - max_xy.clone() + let Self { max, .. } = &**datum; + max.clone() }); (datum.is_some(), datum) }) .unzip(); - let max_xy_bitmap: Option = { + let max_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; - let max_xy_inner_data: Vec<_> = max_xy + let max_inner_data: Vec<_> = max .iter() .flat_map(|v| match v { Some(v) => itertools::Either::Left(v.iter().cloned()), @@ -189,8 +189,8 @@ impl ::re_types_core::Loggable for AABB2D { }) .map(Some) .collect(); - let max_xy_inner_bitmap: Option = - max_xy_bitmap.as_ref().map(|bitmap| { + let max_inner_bitmap: Option = + max_bitmap.as_ref().map(|bitmap| { bitmap .iter() .map(|i| std::iter::repeat(i).take(2usize)) @@ -209,14 +209,14 @@ impl ::re_types_core::Loggable for AABB2D { ), PrimitiveArray::new( DataType::Float64, - max_xy_inner_data + max_inner_data .into_iter() .map(|v| v.unwrap_or_default()) .collect(), - max_xy_inner_bitmap, + max_inner_bitmap, ) .boxed(), - max_xy_bitmap, + max_bitmap, ) .boxed() } @@ -257,15 +257,15 @@ impl ::re_types_core::Loggable for AABB2D { .map(|field| field.name.as_str()) .zip(arrow_data_arrays) .collect(); - let min_xy = { - if !arrays_by_name.contains_key("min_xy") { + let min = { + if !arrays_by_name.contains_key("min") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "min_xy", + "min", )) .with_context("rerun.datatypes.AABB2D"); } - let arrow_data = &**arrays_by_name["min_xy"]; + let arrow_data = &**arrays_by_name["min"]; { let arrow_data = arrow_data .as_any() @@ -282,7 +282,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#min_xy")?; + .with_context("rerun.datatypes.AABB2D#min")?; if arrow_data.is_empty() { Vec::new() } else { @@ -299,7 +299,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data_inner.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#min_xy")? + .with_context("rerun.datatypes.AABB2D#min")? .into_iter() .map(|opt| opt.copied()) .collect::>() @@ -333,15 +333,15 @@ impl ::re_types_core::Loggable for AABB2D { .into_iter() } }; - let max_xy = { - if !arrays_by_name.contains_key("max_xy") { + let max = { + if !arrays_by_name.contains_key("max") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "max_xy", + "max", )) .with_context("rerun.datatypes.AABB2D"); } - let arrow_data = &**arrays_by_name["max_xy"]; + let arrow_data = &**arrays_by_name["max"]; { let arrow_data = arrow_data .as_any() @@ -358,7 +358,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#max_xy")?; + .with_context("rerun.datatypes.AABB2D#max")?; if arrow_data.is_empty() { Vec::new() } else { @@ -375,7 +375,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data_inner.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#max_xy")? + .with_context("rerun.datatypes.AABB2D#max")? .into_iter() .map(|opt| opt.copied()) .collect::>() @@ -410,18 +410,18 @@ impl ::re_types_core::Loggable for AABB2D { } }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(min_xy, max_xy), + ::itertools::izip!(min, max), arrow_data.validity(), ) .map(|opt| { - opt.map(|(min_xy, max_xy)| { + opt.map(|(min, max)| { Ok(Self { - min_xy: min_xy + min: min .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.datatypes.AABB2D#min_xy")?, - max_xy: max_xy + .with_context("rerun.datatypes.AABB2D#min")?, + max: max .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.datatypes.AABB2D#max_xy")?, + .with_context("rerun.datatypes.AABB2D#max")?, }) }) .transpose() diff --git a/crates/re_types/src/datatypes/aabb2d_ext.rs b/crates/re_types/src/datatypes/aabb2d_ext.rs index a134b154a36..0be22003bb5 100644 --- a/crates/re_types/src/datatypes/aabb2d_ext.rs +++ b/crates/re_types/src/datatypes/aabb2d_ext.rs @@ -4,8 +4,8 @@ impl From for AABB2D { #[inline] fn from(v: emath::Rect) -> Self { Self { - min_xy: [v.min.x as f64, v.min.y as f64], - max_xy: [v.max.x as f64, v.max.y as f64], + min: [v.min.x as f64, v.min.y as f64], + max: [v.max.x as f64, v.max.y as f64], } } } @@ -14,8 +14,8 @@ impl From for emath::Rect { #[inline] fn from(v: AABB2D) -> Self { Self { - min: emath::pos2(v.min_xy[0] as f32, v.min_xy[1] as f32), - max: emath::pos2(v.max_xy[0] as f32, v.max_xy[1] as f32), + min: emath::pos2(v.min[0] as f32, v.min[1] as f32), + max: emath::pos2(v.max[0] as f32, v.max[1] as f32), } } } diff --git a/docs/content/reference/types/datatypes/aabb2d.md b/docs/content/reference/types/datatypes/aabb2d.md index 6a41f414c95..385fc300eb3 100644 --- a/docs/content/reference/types/datatypes/aabb2d.md +++ b/docs/content/reference/types/datatypes/aabb2d.md @@ -6,8 +6,8 @@ An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum ## Fields -* min_xy: 2x `f64` -* max_xy: 2x `f64` +* min: 2x `f64` +* max: 2x `f64` ## Links * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1AABB2D.html) diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp index 0fa2c12c96f..cedd679f956 100644 --- a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp @@ -12,12 +12,12 @@ namespace rerun { const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::struct_({ arrow::field( - "min_xy", + "min", arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2), false ), arrow::field( - "max_xy", + "max", arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2), false ), @@ -64,9 +64,9 @@ namespace rerun { auto value_builder = static_cast(field_builder->value_builder()); ARROW_RETURN_NOT_OK(field_builder->AppendValues(static_cast(num_elements))); - static_assert(sizeof(elements[0].min_xy) == sizeof(elements[0])); + static_assert(sizeof(elements[0].min) == sizeof(elements[0])); ARROW_RETURN_NOT_OK(value_builder->AppendValues( - elements[0].min_xy.data(), + elements[0].min.data(), static_cast(num_elements * 2), nullptr )); @@ -77,9 +77,9 @@ namespace rerun { auto value_builder = static_cast(field_builder->value_builder()); ARROW_RETURN_NOT_OK(field_builder->AppendValues(static_cast(num_elements))); - static_assert(sizeof(elements[0].max_xy) == sizeof(elements[0])); + static_assert(sizeof(elements[0].max) == sizeof(elements[0])); ARROW_RETURN_NOT_OK(value_builder->AppendValues( - elements[0].max_xy.data(), + elements[0].max.data(), static_cast(num_elements * 2), nullptr )); diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp index 6e1952ddbfe..c5628deed8c 100644 --- a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp @@ -19,10 +19,10 @@ namespace rerun::datatypes { /// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. struct AABB2D { /// The minimum bounds; usually left-top corner. - std::array min_xy; + std::array min; /// The maximum bounds; usually right-bottom corner. - std::array max_xy; + std::array max; public: AABB2D() = default; diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py index 3237db6fbed..66c7180c709 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py @@ -24,28 +24,28 @@ class AABB2D: """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" - def __init__(self: Any, min_xy: npt.ArrayLike, max_xy: npt.ArrayLike): + def __init__(self: Any, min: npt.ArrayLike, max: npt.ArrayLike): """ Create a new instance of the AABB2D datatype. Parameters ---------- - min_xy: + min: The minimum bounds; usually left-top corner. - max_xy: + max: The maximum bounds; usually right-bottom corner. """ # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py - self.__attrs_init__(min_xy=min_xy, max_xy=max_xy) + self.__attrs_init__(min=min, max=max) - min_xy: npt.NDArray[np.float64] = field(converter=to_np_float64) + min: npt.NDArray[np.float64] = field(converter=to_np_float64) # The minimum bounds; usually left-top corner. # # (Docstring intentionally commented out to hide this field from the docs) - max_xy: npt.NDArray[np.float64] = field(converter=to_np_float64) + max: npt.NDArray[np.float64] = field(converter=to_np_float64) # The maximum bounds; usually right-bottom corner. # # (Docstring intentionally commented out to hide this field from the docs) @@ -66,13 +66,13 @@ def __init__(self) -> None: self, pa.struct([ pa.field( - "min_xy", + "min", pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), nullable=False, metadata={}, ), pa.field( - "max_xy", + "max", pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), nullable=False, metadata={}, From d0b47779a7402740c3a0706c14468dcf2db32188 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 27 Apr 2024 09:05:41 +0200 Subject: [PATCH 05/20] Make the example work with _RERUN_TEST_FORCE_SAVE --- docs/snippets/all/annotation_context_rects.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/snippets/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py index 1a857cc741b..e5d77f4abcf 100644 --- a/docs/snippets/all/annotation_context_rects.py +++ b/docs/snippets/all/annotation_context_rects.py @@ -1,11 +1,20 @@ import rerun as rr import rerun.blueprint as rrb -blueprint = rrb.Spatial2DView(background=[128, 0, 0], visual_bounds=rrb.VisualBounds(min=[-4.5, -2.5], max=[2.5, 2.5])) -rr.init("rerun_example_annotation_context_rects", spawn=True, default_blueprint=blueprint) +rr.init("rerun_example_annotation_context_rects", spawn=True) # Log an annotation context to assign a label and color to each class rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) + +# Create a Spatial3D View +blueprint = rrb.Blueprint( + rrb.Spatial3DView( + origin="/points", + background=[80, 80, 80], + ) +) + +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4.5, -2.5], max=[2.5, 2.5]))) From 3df5b973a97c1fd59c08f8d83a29777732b336d4 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 29 Apr 2024 11:14:46 +0200 Subject: [PATCH 06/20] fix up aabb2d python serialization --- .../definitions/rerun/datatypes/aabb2d.fbs | 6 +- crates/re_types/src/components/aabb2d.rs | 18 +---- crates/re_types/src/datatypes/aabb2d.rs | 80 ++++++++++--------- crates/re_types/src/datatypes/aabb2d_ext.rs | 4 +- .../reference/types/datatypes/aabb2d.md | 4 +- .../reference/types/datatypes/vec2d.md | 2 + .../reference/types/views/spatial2d_view.md | 4 + rerun_cpp/src/rerun/datatypes/aabb2d.cpp | 48 +++++------ rerun_cpp/src/rerun/datatypes/aabb2d.hpp | 6 +- .../rerun_sdk/rerun/components/aabb2d_ext.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py | 35 +++++--- .../rerun_sdk/rerun/datatypes/aabb2d_ext.py | 27 +++++++ 12 files changed, 132 insertions(+), 106 deletions(-) create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py diff --git a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs index c597adcb349..2ea946feab5 100644 --- a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs +++ b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs @@ -4,6 +4,8 @@ include "fbs/attributes.fbs"; include "python/attributes.fbs"; include "rust/attributes.fbs"; +include "./vec2d.fbs"; + namespace rerun.datatypes; // --- @@ -14,8 +16,8 @@ struct AABB2D ( "attr.rust.repr": "C" ) { /// The minimum bounds; usually left-top corner. - min: [double: 2] (order: 100); + min: rerun.datatypes.Vec2D (order: 100); /// The maximum bounds; usually right-bottom corner. - max: [double: 2] (order: 200); + max: rerun.datatypes.Vec2D (order: 200); } diff --git a/crates/re_types/src/components/aabb2d.rs b/crates/re_types/src/components/aabb2d.rs index 9e782095992..36d15afb45d 100644 --- a/crates/re_types/src/components/aabb2d.rs +++ b/crates/re_types/src/components/aabb2d.rs @@ -76,22 +76,8 @@ impl ::re_types_core::Loggable for AABB2D { fn arrow_datatype() -> arrow2::datatypes::DataType { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ - Field::new( - "min", - DataType::FixedSizeList( - std::sync::Arc::new(Field::new("item", DataType::Float64, false)), - 2usize, - ), - false, - ), - Field::new( - "max", - DataType::FixedSizeList( - std::sync::Arc::new(Field::new("item", DataType::Float64, false)), - 2usize, - ), - false, - ), + Field::new("min", ::arrow_datatype(), false), + Field::new("max", ::arrow_datatype(), false), ])) } diff --git a/crates/re_types/src/datatypes/aabb2d.rs b/crates/re_types/src/datatypes/aabb2d.rs index 919ad7190b4..32551e4f92e 100644 --- a/crates/re_types/src/datatypes/aabb2d.rs +++ b/crates/re_types/src/datatypes/aabb2d.rs @@ -27,10 +27,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[repr(C)] pub struct AABB2D { /// The minimum bounds; usually left-top corner. - pub min: [f64; 2usize], + pub min: crate::datatypes::Vec2D, /// The maximum bounds; usually right-bottom corner. - pub max: [f64; 2usize], + pub max: crate::datatypes::Vec2D, } impl ::re_types_core::SizeBytes for AABB2D { @@ -41,7 +41,7 @@ impl ::re_types_core::SizeBytes for AABB2D { #[inline] fn is_pod() -> bool { - <[f64; 2usize]>::is_pod() && <[f64; 2usize]>::is_pod() + ::is_pod() && ::is_pod() } } @@ -60,22 +60,8 @@ impl ::re_types_core::Loggable for AABB2D { fn arrow_datatype() -> arrow2::datatypes::DataType { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ - Field::new( - "min", - DataType::FixedSizeList( - std::sync::Arc::new(Field::new("item", DataType::Float64, false)), - 2usize, - ), - false, - ), - Field::new( - "max", - DataType::FixedSizeList( - std::sync::Arc::new(Field::new("item", DataType::Float64, false)), - 2usize, - ), - false, - ), + Field::new("min", ::arrow_datatype(), false), + Field::new("max", ::arrow_datatype(), false), ])) } @@ -122,12 +108,15 @@ impl ::re_types_core::Loggable for AABB2D { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; let min_inner_data: Vec<_> = min .iter() - .flat_map(|v| match v { - Some(v) => itertools::Either::Left(v.iter().cloned()), - None => itertools::Either::Right( - std::iter::repeat(Default::default()).take(2usize), - ), + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Vec2D(data0) = datum; + data0 + }) + .unwrap_or_default() }) + .flatten() .map(Some) .collect(); let min_inner_bitmap: Option = @@ -143,13 +132,13 @@ impl ::re_types_core::Loggable for AABB2D { DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float64, + DataType::Float32, false, )), 2usize, ), PrimitiveArray::new( - DataType::Float64, + DataType::Float32, min_inner_data .into_iter() .map(|v| v.unwrap_or_default()) @@ -181,12 +170,15 @@ impl ::re_types_core::Loggable for AABB2D { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; let max_inner_data: Vec<_> = max .iter() - .flat_map(|v| match v { - Some(v) => itertools::Either::Left(v.iter().cloned()), - None => itertools::Either::Right( - std::iter::repeat(Default::default()).take(2usize), - ), + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Vec2D(data0) = datum; + data0 + }) + .unwrap_or_default() }) + .flatten() .map(Some) .collect(); let max_inner_bitmap: Option = @@ -202,13 +194,13 @@ impl ::re_types_core::Loggable for AABB2D { DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float64, + DataType::Float32, false, )), 2usize, ), PrimitiveArray::new( - DataType::Float64, + DataType::Float32, max_inner_data .into_iter() .map(|v| v.unwrap_or_default()) @@ -274,7 +266,7 @@ impl ::re_types_core::Loggable for AABB2D { let expected = DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float64, + DataType::Float32, false, )), 2usize, @@ -293,9 +285,9 @@ impl ::re_types_core::Loggable for AABB2D { let arrow_data_inner = &**arrow_data.values(); arrow_data_inner .as_any() - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| { - let expected = DataType::Float64; + let expected = DataType::Float32; let actual = arrow_data_inner.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) @@ -328,6 +320,11 @@ impl ::re_types_core::Loggable for AABB2D { }) .transpose() }) + .map(|res_or_opt| { + res_or_opt.map(|res_or_opt| { + res_or_opt.map(|v| crate::datatypes::Vec2D(v)) + }) + }) .collect::>>>()? } .into_iter() @@ -350,7 +347,7 @@ impl ::re_types_core::Loggable for AABB2D { let expected = DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float64, + DataType::Float32, false, )), 2usize, @@ -369,9 +366,9 @@ impl ::re_types_core::Loggable for AABB2D { let arrow_data_inner = &**arrow_data.values(); arrow_data_inner .as_any() - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| { - let expected = DataType::Float64; + let expected = DataType::Float32; let actual = arrow_data_inner.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) @@ -404,6 +401,11 @@ impl ::re_types_core::Loggable for AABB2D { }) .transpose() }) + .map(|res_or_opt| { + res_or_opt.map(|res_or_opt| { + res_or_opt.map(|v| crate::datatypes::Vec2D(v)) + }) + }) .collect::>>>()? } .into_iter() diff --git a/crates/re_types/src/datatypes/aabb2d_ext.rs b/crates/re_types/src/datatypes/aabb2d_ext.rs index 0be22003bb5..2059fe322ea 100644 --- a/crates/re_types/src/datatypes/aabb2d_ext.rs +++ b/crates/re_types/src/datatypes/aabb2d_ext.rs @@ -4,8 +4,8 @@ impl From for AABB2D { #[inline] fn from(v: emath::Rect) -> Self { Self { - min: [v.min.x as f64, v.min.y as f64], - max: [v.max.x as f64, v.max.y as f64], + min: [v.min.x, v.min.y].into(), + max: [v.max.x, v.max.y].into(), } } } diff --git a/docs/content/reference/types/datatypes/aabb2d.md b/docs/content/reference/types/datatypes/aabb2d.md index 385fc300eb3..dec7dbd2940 100644 --- a/docs/content/reference/types/datatypes/aabb2d.md +++ b/docs/content/reference/types/datatypes/aabb2d.md @@ -6,8 +6,8 @@ An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum ## Fields -* min: 2x `f64` -* max: 2x `f64` +* min: [`Vec2D`](../datatypes/vec2d.md) +* max: [`Vec2D`](../datatypes/vec2d.md) ## Links * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1AABB2D.html) diff --git a/docs/content/reference/types/datatypes/vec2d.md b/docs/content/reference/types/datatypes/vec2d.md index 68aa0b66580..86acd182e66 100644 --- a/docs/content/reference/types/datatypes/vec2d.md +++ b/docs/content/reference/types/datatypes/vec2d.md @@ -22,3 +22,5 @@ A vector in 2D space. * [`Resolution`](../components/resolution.md) * [`Texcoord2D`](../components/texcoord2d.md) * [`Vector2D`](../components/vector2d.md) +* [`AABB2D`](../datatypes/aabb2d.md) +* [`AABB2D`](../datatypes/aabb2d.md) diff --git a/docs/content/reference/types/views/spatial2d_view.md b/docs/content/reference/types/views/spatial2d_view.md index fd5050615bc..065e19d4996 100644 --- a/docs/content/reference/types/views/spatial2d_view.md +++ b/docs/content/reference/types/views/spatial2d_view.md @@ -11,6 +11,10 @@ Configuration for the background of a view. * kind: The type of the background. Defaults to BackgroundKind.GradientDark. * color: Color used for BackgroundKind.SolidColor. +### `VisualBounds` +Controls the visual bounds of a 2D space view. + +* visual_bounds: The visible parts of a 2D space view, in the coordinate space of the scene. ## Links * 🐍 [Python API docs for `Spatial2DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial2DView) diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp index cedd679f956..d960e1a1516 100644 --- a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp @@ -3,6 +3,8 @@ #include "aabb2d.hpp" +#include "vec2d.hpp" + #include #include @@ -11,16 +13,8 @@ namespace rerun::datatypes {} namespace rerun { const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::struct_({ - arrow::field( - "min", - arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2), - false - ), - arrow::field( - "max", - arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2), - false - ), + arrow::field("min", Loggable::arrow_datatype(), false), + arrow::field("max", Loggable::arrow_datatype(), false), }); return datatype; } @@ -61,28 +55,26 @@ namespace rerun { { auto field_builder = static_cast(builder->field_builder(0)); - auto value_builder = static_cast(field_builder->value_builder()); - - ARROW_RETURN_NOT_OK(field_builder->AppendValues(static_cast(num_elements))); - static_assert(sizeof(elements[0].min) == sizeof(elements[0])); - ARROW_RETURN_NOT_OK(value_builder->AppendValues( - elements[0].min.data(), - static_cast(num_elements * 2), - nullptr - )); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].min, + 1 + )); + } } { auto field_builder = static_cast(builder->field_builder(1)); - auto value_builder = static_cast(field_builder->value_builder()); - - ARROW_RETURN_NOT_OK(field_builder->AppendValues(static_cast(num_elements))); - static_assert(sizeof(elements[0].max) == sizeof(elements[0])); - ARROW_RETURN_NOT_OK(value_builder->AppendValues( - elements[0].max.data(), - static_cast(num_elements * 2), - nullptr - )); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].max, + 1 + )); + } } ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp index c5628deed8c..41a751bfed1 100644 --- a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp @@ -4,8 +4,8 @@ #pragma once #include "../result.hpp" +#include "vec2d.hpp" -#include #include #include @@ -19,10 +19,10 @@ namespace rerun::datatypes { /// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. struct AABB2D { /// The minimum bounds; usually left-top corner. - std::array min; + rerun::datatypes::Vec2D min; /// The maximum bounds; usually right-bottom corner. - std::array max; + rerun::datatypes::Vec2D max; public: AABB2D() = default; diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py index df15adef97d..0248277a326 100644 --- a/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py @@ -2,7 +2,7 @@ from typing import Any -from ..datatypes import AABB2D, Vec2DLike +from ..datatypes import Vec2DLike class AABB2DExt: @@ -28,4 +28,4 @@ def __init__( """ - self.__attrs_init__(AABB2D(min=min, max=max)) + self.__attrs_init__(min=min, max=max) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py index 66c7180c709..df63dfc4b55 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py @@ -7,24 +7,35 @@ from typing import Any, Sequence, Union -import numpy as np -import numpy.typing as npt import pyarrow as pa from attrs import define, field +from .. import datatypes from .._baseclasses import BaseBatch, BaseExtensionType -from .._converters import ( - to_np_float64, -) +from .aabb2d_ext import AABB2DExt __all__ = ["AABB2D", "AABB2DArrayLike", "AABB2DBatch", "AABB2DLike", "AABB2DType"] +def _aabb2d__min__special_field_converter_override(x: datatypes.Vec2DLike) -> datatypes.Vec2D: + if isinstance(x, datatypes.Vec2D): + return x + else: + return datatypes.Vec2D(x) + + +def _aabb2d__max__special_field_converter_override(x: datatypes.Vec2DLike) -> datatypes.Vec2D: + if isinstance(x, datatypes.Vec2D): + return x + else: + return datatypes.Vec2D(x) + + @define(init=False) -class AABB2D: +class AABB2D(AABB2DExt): """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" - def __init__(self: Any, min: npt.ArrayLike, max: npt.ArrayLike): + def __init__(self: Any, min: datatypes.Vec2DLike, max: datatypes.Vec2DLike): """ Create a new instance of the AABB2D datatype. @@ -40,12 +51,12 @@ def __init__(self: Any, min: npt.ArrayLike, max: npt.ArrayLike): # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py self.__attrs_init__(min=min, max=max) - min: npt.NDArray[np.float64] = field(converter=to_np_float64) + min: datatypes.Vec2D = field(converter=_aabb2d__min__special_field_converter_override) # The minimum bounds; usually left-top corner. # # (Docstring intentionally commented out to hide this field from the docs) - max: npt.NDArray[np.float64] = field(converter=to_np_float64) + max: datatypes.Vec2D = field(converter=_aabb2d__max__special_field_converter_override) # The maximum bounds; usually right-bottom corner. # # (Docstring intentionally commented out to hide this field from the docs) @@ -67,13 +78,13 @@ def __init__(self) -> None: pa.struct([ pa.field( "min", - pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), + pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2), nullable=False, metadata={}, ), pa.field( "max", - pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), + pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2), nullable=False, metadata={}, ), @@ -87,4 +98,4 @@ class AABB2DBatch(BaseBatch[AABB2DArrayLike]): @staticmethod def _native_to_pa_array(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in aabb2d_ext.py + return AABB2DExt.native_to_pa_array_override(data, data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py new file mode 100644 index 00000000000..0e3cc2db425 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pyarrow as pa + +if TYPE_CHECKING: + from . import AABB2DArrayLike + + +class AABB2DExt: + """Extension for [AABB2D][rerun.datatypes.AABB2D].""" + + @staticmethod + def native_to_pa_array_override(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: + from . import AABB2D, Vec2DBatch + + if isinstance(data, AABB2D): + data = [data] + + return pa.StructArray.from_arrays( + [ + Vec2DBatch._native_to_pa_array([aabb.min for aabb in data], data_type["min"].type), + Vec2DBatch._native_to_pa_array([aabb.max for aabb in data], data_type["min"].type), + ], + fields=list(data_type), + ) From 39c78b7aef358a682d42359c2bd985a4d8bbdf8e Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 29 Apr 2024 11:14:54 +0200 Subject: [PATCH 07/20] WIP: attempt fixing warning --- crates/re_space_view/src/sub_archetypes.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 1defe4c291f..2285dfe22e9 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -99,7 +99,11 @@ pub fn edit_blueprint_component(&path); + } } ret From f4987220c1156898f65047d5a3301150d71ba1a9 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 11:20:32 +0200 Subject: [PATCH 08/20] Sort and de-duplicated the "Use by" list in our docs --- crates/re_types_builder/src/codegen/docs/mod.rs | 2 ++ docs/content/reference/types/datatypes/annotation_info.md | 1 - docs/content/reference/types/datatypes/class_id.md | 2 +- docs/content/reference/types/datatypes/keypoint_id.md | 1 - docs/content/reference/types/datatypes/rgba32.md | 2 +- docs/content/reference/types/datatypes/utf8.md | 4 ++-- docs/content/reference/types/datatypes/vec2d.md | 3 +-- docs/content/reference/types/datatypes/vec3d.md | 2 +- 8 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index dd8e7b4208e..1bab905ca59 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -433,6 +433,8 @@ fn write_used_by(o: &mut String, reporter: &Reporter, object: &Object, object_ma } } } + used_by.sort(); + used_by.dedup(); // The same datatype can be used multiple times by the same component if used_by.is_empty() { // NOTE: there are some false positives here, because unions can only diff --git a/docs/content/reference/types/datatypes/annotation_info.md b/docs/content/reference/types/datatypes/annotation_info.md index 9ed573668f8..54ae74e6291 100644 --- a/docs/content/reference/types/datatypes/annotation_info.md +++ b/docs/content/reference/types/datatypes/annotation_info.md @@ -22,4 +22,3 @@ The id refers either to a class or key-point id ## Used by * [`ClassDescription`](../datatypes/class_description.md) -* [`ClassDescription`](../datatypes/class_description.md) diff --git a/docs/content/reference/types/datatypes/class_id.md b/docs/content/reference/types/datatypes/class_id.md index 02c6d1e6ef3..4a39ebf28ae 100644 --- a/docs/content/reference/types/datatypes/class_id.md +++ b/docs/content/reference/types/datatypes/class_id.md @@ -16,5 +16,5 @@ A 16-bit ID representing a type of semantic class. ## Used by -* [`ClassId`](../components/class_id.md) * [`ClassDescriptionMapElem`](../datatypes/class_description_map_elem.md) +* [`ClassId`](../components/class_id.md) diff --git a/docs/content/reference/types/datatypes/keypoint_id.md b/docs/content/reference/types/datatypes/keypoint_id.md index a22dc294f01..fd53dc3846b 100644 --- a/docs/content/reference/types/datatypes/keypoint_id.md +++ b/docs/content/reference/types/datatypes/keypoint_id.md @@ -18,4 +18,3 @@ A 16-bit ID representing a type of semantic keypoint within a class. * [`KeypointId`](../components/keypoint_id.md) * [`KeypointPair`](../datatypes/keypoint_pair.md) -* [`KeypointPair`](../datatypes/keypoint_pair.md) diff --git a/docs/content/reference/types/datatypes/rgba32.md b/docs/content/reference/types/datatypes/rgba32.md index 5ade3fd5463..6a9828df9ec 100644 --- a/docs/content/reference/types/datatypes/rgba32.md +++ b/docs/content/reference/types/datatypes/rgba32.md @@ -19,6 +19,6 @@ byte is `R` and the least significant byte is `A`. ## Used by -* [`Color`](../components/color.md) * [`AnnotationInfo`](../datatypes/annotation_info.md) +* [`Color`](../components/color.md) * [`Material`](../datatypes/material.md) diff --git a/docs/content/reference/types/datatypes/utf8.md b/docs/content/reference/types/datatypes/utf8.md index 711a41681d3..572dadde7d9 100644 --- a/docs/content/reference/types/datatypes/utf8.md +++ b/docs/content/reference/types/datatypes/utf8.md @@ -16,8 +16,8 @@ A string of text, encoded as UTF-8. ## Used by +* [`AnnotationInfo`](../datatypes/annotation_info.md) * [`MediaType`](../components/media_type.md) * [`Name`](../components/name.md) -* [`Text`](../components/text.md) * [`TextLogLevel`](../components/text_log_level.md) -* [`AnnotationInfo`](../datatypes/annotation_info.md) +* [`Text`](../components/text.md) diff --git a/docs/content/reference/types/datatypes/vec2d.md b/docs/content/reference/types/datatypes/vec2d.md index 86acd182e66..d9055170734 100644 --- a/docs/content/reference/types/datatypes/vec2d.md +++ b/docs/content/reference/types/datatypes/vec2d.md @@ -16,11 +16,10 @@ A vector in 2D space. ## Used by +* [`AABB2D`](../datatypes/aabb2d.md) * [`HalfSizes2D`](../components/half_sizes2d.md) * [`LineStrip2D`](../components/line_strip2d.md) * [`Position2D`](../components/position2d.md) * [`Resolution`](../components/resolution.md) * [`Texcoord2D`](../components/texcoord2d.md) * [`Vector2D`](../components/vector2d.md) -* [`AABB2D`](../datatypes/aabb2d.md) -* [`AABB2D`](../datatypes/aabb2d.md) diff --git a/docs/content/reference/types/datatypes/vec3d.md b/docs/content/reference/types/datatypes/vec3d.md index 4fa7ed4c0c9..d408e84903e 100644 --- a/docs/content/reference/types/datatypes/vec3d.md +++ b/docs/content/reference/types/datatypes/vec3d.md @@ -19,8 +19,8 @@ A vector in 3D space. * [`HalfSizes3D`](../components/half_sizes3d.md) * [`LineStrip3D`](../components/line_strip3d.md) * [`Position3D`](../components/position3d.md) -* [`Vector3D`](../components/vector3d.md) * [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) * [`Scale3D`](../datatypes/scale3d.md) * [`TranslationAndMat3x3`](../datatypes/translation_and_mat3x3.md) * [`TranslationRotationScale3D`](../datatypes/translation_rotation_scale3d.md) +* [`Vector3D`](../components/vector3d.md) From 9ab4840bdfd42ab9fd5bc67e3a5be891d8310fe4 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 11:21:33 +0200 Subject: [PATCH 09/20] Remove unnecessary casts --- crates/re_types/src/components/aabb2d_ext.rs | 4 ++-- crates/re_types/src/datatypes/aabb2d_ext.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/re_types/src/components/aabb2d_ext.rs b/crates/re_types/src/components/aabb2d_ext.rs index 9f93dd2b242..0367ab75bb2 100644 --- a/crates/re_types/src/components/aabb2d_ext.rs +++ b/crates/re_types/src/components/aabb2d_ext.rs @@ -4,8 +4,8 @@ impl From for emath::Rect { #[inline] fn from(v: AABB2D) -> Self { Self { - min: emath::pos2(v.min[0] as f32, v.min[1] as f32), - max: emath::pos2(v.max[0] as f32, v.max[1] as f32), + min: emath::pos2(v.min[0], v.min[1]), + max: emath::pos2(v.max[0], v.max[1]), } } } diff --git a/crates/re_types/src/datatypes/aabb2d_ext.rs b/crates/re_types/src/datatypes/aabb2d_ext.rs index 2059fe322ea..92c929d7cf5 100644 --- a/crates/re_types/src/datatypes/aabb2d_ext.rs +++ b/crates/re_types/src/datatypes/aabb2d_ext.rs @@ -14,8 +14,8 @@ impl From for emath::Rect { #[inline] fn from(v: AABB2D) -> Self { Self { - min: emath::pos2(v.min[0] as f32, v.min[1] as f32), - max: emath::pos2(v.max[0] as f32, v.max[1] as f32), + min: emath::pos2(v.min[0], v.min[1]), + max: emath::pos2(v.max[0], v.max[1]), } } } From c317d5c9ca2dd5ce65cb6795525a8bd0917ab5cd Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 11:24:23 +0200 Subject: [PATCH 10/20] Remove promise about viewport linking --- .../definitions/rerun/blueprint/archetypes/visual_bounds.fbs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs index aa0b4b26727..4317e53fbe8 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs @@ -18,6 +18,4 @@ table VisualBounds ( /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. visual_bounds: rerun.components.AABB2D ("attr.rerun.component_optional", nullable, order: 1000); - - // Here we'll add things like locking the visual bounds of one space view to another } From be4ad4b6b0956d34408b99a4a8a12b353a7cbc56 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 11:27:42 +0200 Subject: [PATCH 11/20] Better comments --- crates/re_space_view/src/sub_archetypes.rs | 7 ++----- crates/re_space_view_spatial/src/ui_2d.rs | 7 +++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 2285dfe22e9..98d14cee6a8 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -99,11 +99,8 @@ pub fn edit_blueprint_component(&path); - } + // Will store an empty list of components if `edited` is `None`. + ctx.save_blueprint_component(&path, &edited); } ret diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index 960c5a5428e..3b8e0e1aa94 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -115,6 +115,7 @@ fn update_ui_from_scene_impl( RectTransform::from_to(letterboxed_bounds, response.rect) } +/// Pan and zoom, and return the current transform. fn ui_from_scene( ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, @@ -129,9 +130,15 @@ fn ui_from_scene( ctx, space_view_id, |aabb: &mut Option| { + // Convert to a Rect let mut rect: Rect = aabb.map_or(default_scene_rect, Rect::from); + + // Apply pan and zoom based on input let ui_from_scene = update_ui_from_scene_impl(&mut rect, response, default_scene_rect); + + // Store back the results *aabb = Some(rect.into()); + ui_from_scene }, ) From ce59b4a64b65aa30ebcc07e92cc914d2db9b9176 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 12:33:15 +0200 Subject: [PATCH 12/20] Fix: Treat an empty component list as a `None` value without warning --- crates/re_entity_db/src/entity_db.rs | 16 +++++ crates/re_query/src/latest_at/helpers.rs | 79 ++++++++++++++---------- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index c7b7e8f29fd..86c68652840 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -232,6 +232,14 @@ impl EntityDb { } } + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// This assumes that the row we get from the store contains at most one instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, it will merely log errors on failure. #[inline] pub fn latest_at_component( &self, @@ -246,6 +254,14 @@ impl EntityDb { ) } + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// This assumes that the row we get from the store contains at most one instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, and will quietly swallow any errors. #[inline] pub fn latest_at_component_quiet( &self, diff --git a/crates/re_query/src/latest_at/helpers.rs b/crates/re_query/src/latest_at/helpers.rs index d850bfc660d..adce7289eab 100644 --- a/crates/re_query/src/latest_at/helpers.rs +++ b/crates/re_query/src/latest_at/helpers.rs @@ -62,7 +62,7 @@ impl LatestAtComponentResults { /// Returns the component data of the single instance. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will log a warning otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -77,14 +77,19 @@ impl LatestAtComponentResults { re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(data[0].clone()), PromiseResult::Ready(data) => { - re_log::log_once!( - level, - "Couldn't deserialize {component_name}: not a mono-batch (length: {})", - data.len(), - ); - None + match data.len() { + 0 => { + None // Empty list = no data. + } + 1 => Some(data[0].clone()), + len => { + re_log::log_once!(level, + "Couldn't deserialize {component_name}: not a mono-batch (length: {len})" + ); + None + } + } } PromiseResult::Error(err) => { re_log::log_once!( @@ -99,7 +104,7 @@ impl LatestAtComponentResults { /// Returns the component data of the single instance as an arrow array. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will log a warning otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -118,16 +123,20 @@ impl LatestAtComponentResults { re_log::debug_once!("Couldn't get {component_name}: promise still pending"); None } - PromiseResult::Ready(cell) if cell.as_arrow_ref().len() == 1 => { - Some(cell.as_arrow_ref().sliced(0, 1)) - } PromiseResult::Ready(cell) => { - re_log::log_once!( - level, - "Couldn't get {component_name}: not a mono-batch (length: {})", - cell.as_arrow_ref().len(), - ); - None + match cell.as_arrow_ref().len() { + 0 => { + None // Empty list = no data. + } + 1 => Some(cell.as_arrow_ref().sliced(0, 1)), + len => { + re_log::log_once!( + level, + "Couldn't get {component_name}: not a mono-batch (length: {len})", + ); + None + } + } } PromiseResult::Error(err) => { re_log::log_once!( @@ -272,7 +281,7 @@ impl Caches { /// /// Returns `None` if the data is a promise that has yet to be resolved. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will generate a log message of `level` otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -303,18 +312,24 @@ impl Caches { ); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(LatestAtMonoResult { - index, - value: data[0].clone(), - }), PromiseResult::Ready(data) => { - re_log::log_once!( - level, - "Couldn't deserialize {entity_path}:{} @ {data_time:?}#{row_id}: not a mono-batch (length: {})", - C::name(), - data.len(), - ); - None + match data.len() { + 0 => { + None // Empty list = no data. + } + 1 => Some(LatestAtMonoResult { + index, + value: data[0].clone(), + }), + len => { + re_log::log_once!( + level, + "Couldn't deserialize {entity_path}:{} @ {data_time:?}#{row_id}: not a mono-batch (length: {len})", + C::name(), + ); + None + } + } } PromiseResult::Error(err) => { re_log::log_once!( @@ -330,7 +345,7 @@ impl Caches { /// Get the latest index and value for a given dense [`re_types_core::Component`]. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will log a warning otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -355,7 +370,7 @@ impl Caches { /// Get the latest index and value for a given dense [`re_types_core::Component`]. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will return None and log a debug message otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. From 14c8f6a1aee5ddf090b933b9dcc130e0d21cfa1d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 12:37:40 +0200 Subject: [PATCH 13/20] Reset snippet --- docs/snippets/all/annotation_context_rects.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/docs/snippets/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py index e5d77f4abcf..1c430116d22 100644 --- a/docs/snippets/all/annotation_context_rects.py +++ b/docs/snippets/all/annotation_context_rects.py @@ -1,5 +1,4 @@ import rerun as rr -import rerun.blueprint as rrb rr.init("rerun_example_annotation_context_rects", spawn=True) @@ -9,12 +8,5 @@ # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) -# Create a Spatial3D View -blueprint = rrb.Blueprint( - rrb.Spatial3DView( - origin="/points", - background=[80, 80, 80], - ) -) - -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4.5, -2.5], max=[2.5, 2.5]))) +# Log an extra rect to set the view bounds +rr.log("bounds", rr.Boxes2D(half_sizes=[2.5, 2.5])) From 816d542b2bee67146991fb1746578b01615d2699 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 13:57:15 +0200 Subject: [PATCH 14/20] Reset visible bounds to what's in the default blueprint --- crates/re_space_view/src/sub_archetypes.rs | 40 +++-- .../src/space_view_2d.rs | 4 +- crates/re_space_view_spatial/src/ui_2d.rs | 165 +++++++++--------- crates/re_viewer_context/src/store_context.rs | 3 + crates/re_viewer_context/src/store_hub.rs | 26 ++- 5 files changed, 136 insertions(+), 102 deletions(-) diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 98d14cee6a8..a19caa7ea33 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -84,23 +84,43 @@ pub fn get_blueprint_component( } /// Edit a single component of a blueprint archetype in a space view. +/// +/// Set to `None` to reset the value to the value in the default blueprint, if any, +/// else will just store `None` (an empty component list) in the store. pub fn edit_blueprint_component( ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, edit_component: impl FnOnce(&mut Option) -> R, ) -> R { - let blueprint_db = ctx.store_context.blueprint; - let query = ctx.blueprint_query; - let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); - let original = blueprint_db.latest_at_component::(&path, query); - let original: Option = original.map(|x| x.value); + let active_blueprint = ctx.store_context.blueprint; + let active_path = + entity_path_for_space_view_sub_archetype::(space_view_id, active_blueprint.tree()); + let original_value: Option = active_blueprint + .latest_at_component::(&active_path, ctx.blueprint_query) + .map(|x| x.value); - let mut edited = original.clone(); - let ret = edit_component(&mut edited); + let mut edited_value = original_value.clone(); + let ret = edit_component(&mut edited_value); - if edited != original { - // Will store an empty list of components if `edited` is `None`. - ctx.save_blueprint_component(&path, &edited); + if edited_value != original_value { + if let Some(edited) = edited_value { + ctx.save_blueprint_component(&active_path, &edited); + } else { + // Reset to the value in the default blueprint, if any. + let default_value = ctx + .store_context + .default_blueprint + .and_then(|default_blueprint| { + let default_path = entity_path_for_space_view_sub_archetype::( + space_view_id, + default_blueprint.tree(), + ); + default_blueprint + .latest_at_component::(&default_path, ctx.blueprint_query) + .map(|x| x.value) + }); + ctx.save_blueprint_component(&active_path, &default_value); + } } ret diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 71613bbf8c0..ea8797981f0 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -290,7 +290,7 @@ fn visual_bounds_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mu space_view_id, |aabb: &mut Option| { ctx.re_ui - .grid_left_hand_label(ui, "Bounds") + .grid_left_hand_label(ui, "Visible bounds") .on_hover_text(tooltip); ui.vertical(|ui| { ui.style_mut().wrap = Some(false); @@ -302,7 +302,7 @@ fn visual_bounds_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mu ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); } - if ui.button("Reset bounds").clicked() { + if ui.button("Reset visible bounds").clicked() { *aabb = None; } }); diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index 3b8e0e1aa94..6574da3e50e 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -27,101 +27,97 @@ use crate::{ // --- /// Pan and zoom, and return the current transform. -fn update_ui_from_scene_impl( - visual_bounds: &mut Rect, +fn ui_from_scene( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, response: &egui::Response, default_scene_rect: Rect, ) -> RectTransform { - fn valid_bound(rect: &Rect) -> bool { - rect.is_finite() && rect.is_positive() - } - - if response.double_clicked() { - *visual_bounds = default_scene_rect; // double-click to reset - } - - if !valid_bound(visual_bounds) { - *visual_bounds = default_scene_rect; - } - if !valid_bound(visual_bounds) { - // Nothing in scene, probably. - // Just return something that isn't NaN. - let fake_bounds = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1.0)); - return RectTransform::from_to(fake_bounds, response.rect); - } - - // -------------------------------------------------------------------------- - // Expand bounds for uniform scaling (letterboxing): - - let mut letterboxed_bounds = *visual_bounds; + /// Pan and zoom, and return the current transform. + fn update_ui_from_scene_impl( + visual_bounds: &mut Rect, + response: &egui::Response, + default_scene_rect: Rect, + ) -> RectTransform { + fn valid_bound(rect: &Rect) -> bool { + rect.is_finite() && rect.is_positive() + } - // Temporary before applying letterboxing: - let ui_from_scene = RectTransform::from_to(*visual_bounds, response.rect); + if !valid_bound(visual_bounds) { + *visual_bounds = default_scene_rect; + } + if !valid_bound(visual_bounds) { + // Nothing in scene, probably. + // Just return something that isn't NaN. + let fake_bounds = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1.0)); + return RectTransform::from_to(fake_bounds, response.rect); + } - let scale_aspect = ui_from_scene.scale().x / ui_from_scene.scale().y; - if scale_aspect < 1.0 { - // Letterbox top/bottom: - let add = visual_bounds.height() * (1.0 / scale_aspect - 1.0); - letterboxed_bounds.min.y -= 0.5 * add; - letterboxed_bounds.max.y += 0.5 * add; - } else { - // Letterbox sides: - let add = visual_bounds.width() * (scale_aspect - 1.0); - letterboxed_bounds.min.x -= 0.5 * add; - letterboxed_bounds.max.x += 0.5 * add; - } + // -------------------------------------------------------------------------- + // Expand bounds for uniform scaling (letterboxing): + + let mut letterboxed_bounds = *visual_bounds; + + // Temporary before applying letterboxing: + let ui_from_scene = RectTransform::from_to(*visual_bounds, response.rect); + + let scale_aspect = ui_from_scene.scale().x / ui_from_scene.scale().y; + if scale_aspect < 1.0 { + // Letterbox top/bottom: + let add = visual_bounds.height() * (1.0 / scale_aspect - 1.0); + letterboxed_bounds.min.y -= 0.5 * add; + letterboxed_bounds.max.y += 0.5 * add; + } else { + // Letterbox sides: + let add = visual_bounds.width() * (scale_aspect - 1.0); + letterboxed_bounds.min.x -= 0.5 * add; + letterboxed_bounds.max.x += 0.5 * add; + } - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - // Temporary before applying panning/zooming delta: - let ui_from_scene = RectTransform::from_to(letterboxed_bounds, response.rect); + // Temporary before applying panning/zooming delta: + let ui_from_scene = RectTransform::from_to(letterboxed_bounds, response.rect); - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - let mut pan_delta_in_ui = response.drag_delta(); - if response.hovered() { - // NOTE: we use `raw_scroll` instead of `smooth_scroll_delta` to avoid the - // added latency of smoothing, which is really annoying on Mac trackpads. - // The smoothing is only useful for users with discreet scroll wheels, - // and they are likely to pan with dragging instead. - // TODO(egui#4401): https://github.com/emilk/egui/issues/4401 - pan_delta_in_ui += response.ctx.input(|i| i.raw_scroll_delta); - } - if pan_delta_in_ui != Vec2::ZERO { - *visual_bounds = visual_bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); - } + let mut pan_delta_in_ui = response.drag_delta(); + if response.hovered() { + // NOTE: we use `raw_scroll` instead of `smooth_scroll_delta` to avoid the + // added latency of smoothing, which is really annoying on Mac trackpads. + // The smoothing is only useful for users with discreet scroll wheels, + // and they are likely to pan with dragging instead. + // TODO(egui#4401): https://github.com/emilk/egui/issues/4401 + pan_delta_in_ui += response.ctx.input(|i| i.raw_scroll_delta); + } + if pan_delta_in_ui != Vec2::ZERO { + *visual_bounds = visual_bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); + } - if response.hovered() { - let zoom_delta = response.ctx.input(|i| i.zoom_delta_2d()); - - if zoom_delta != Vec2::splat(1.0) { - let zoom_center_in_ui = response - .hover_pos() - .unwrap_or_else(|| response.rect.center()); - let zoom_center_in_scene = ui_from_scene - .inverse() - .transform_pos(zoom_center_in_ui) - .to_vec2(); - *visual_bounds = scale_rect( - visual_bounds.translate(-zoom_center_in_scene), - Vec2::splat(1.0) / zoom_delta, - ) - .translate(zoom_center_in_scene); + if response.hovered() { + let zoom_delta = response.ctx.input(|i| i.zoom_delta_2d()); + + if zoom_delta != Vec2::splat(1.0) { + let zoom_center_in_ui = response + .hover_pos() + .unwrap_or_else(|| response.rect.center()); + let zoom_center_in_scene = ui_from_scene + .inverse() + .transform_pos(zoom_center_in_ui) + .to_vec2(); + *visual_bounds = scale_rect( + visual_bounds.translate(-zoom_center_in_scene), + Vec2::splat(1.0) / zoom_delta, + ) + .translate(zoom_center_in_scene); + } } - } - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - RectTransform::from_to(letterboxed_bounds, response.rect) -} + RectTransform::from_to(letterboxed_bounds, response.rect) + } -/// Pan and zoom, and return the current transform. -fn ui_from_scene( - ctx: &ViewerContext<'_>, - space_view_id: SpaceViewId, - response: &egui::Response, - default_scene_rect: Rect, -) -> RectTransform { re_space_view::edit_blueprint_component::< VisualBounds, re_types::components::AABB2D, @@ -139,6 +135,13 @@ fn ui_from_scene( // Store back the results *aabb = Some(rect.into()); + if response.double_clicked() { + // Double-click to reset. + // We put it last so that we reset to the value in the default blueprint + // (which is not the same as `default_scene_rect`). + *aabb = None; + } + ui_from_scene }, ) diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index 45891cd87e1..b401952315e 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -11,6 +11,9 @@ pub struct StoreContext<'a> { /// The current active blueprint. pub blueprint: &'a EntityDb, + /// The default blueprint (i.e. the one logged from code), if any. + pub default_blueprint: Option<&'a EntityDb>, + /// The current active recording. /// /// If none is active, this will point to a dummy empty recording. diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 0160a1a1491..3ea006b33fd 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -178,15 +178,22 @@ impl StoreHub { } } - // Get the id is of whatever blueprint is now active, falling back on the "app blueprint" if needed. - let active_blueprint_id = self - .active_blueprint_by_app_id - .entry(app_id.clone()) - .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); + let active_blueprint = { + // Get the id is of whatever blueprint is now active, falling back on the "app blueprint" if needed. + let active_blueprint_id = self + .active_blueprint_by_app_id + .entry(app_id.clone()) + .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); + + // Get or create the blueprint: + self.store_bundle.blueprint_entry(active_blueprint_id); + self.store_bundle.get(active_blueprint_id)? + }; - // Get or create the blueprint: - self.store_bundle.blueprint_entry(active_blueprint_id); - let blueprint = self.store_bundle.get(active_blueprint_id)?; + let default_blueprint = self + .default_blueprint_by_app_id + .get(&app_id) + .and_then(|id| self.store_bundle.get(id)); let recording = self .active_rec_id @@ -199,7 +206,8 @@ impl StoreHub { Some(StoreContext { app_id, - blueprint, + blueprint: active_blueprint, + default_blueprint, recording: recording.unwrap_or(&EMPTY_ENTITY_DB), bundle: &self.store_bundle, hub: self, From 3c7f630e26f1fff581a604d32c923cd24b0bc8bf Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 14:02:48 +0200 Subject: [PATCH 15/20] Add `VisualBounds` to snippets where it makes sense --- docs/snippets/all/annotation_context_rects.py | 3 --- docs/snippets/all/box2d_simple.py | 3 --- docs/snippets/all/extra_values.py | 5 +++-- docs/snippets/all/line_segments2d_simple.py | 5 +++-- docs/snippets/all/line_strip2d_batch.py | 5 +++-- docs/snippets/all/line_strip2d_simple.py | 5 +++-- docs/snippets/all/point2d_random.py | 5 +++-- docs/snippets/all/point2d_simple.py | 5 +++-- rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py | 3 --- rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py | 5 +++-- rerun_py/rerun_sdk/rerun/archetypes/points2d.py | 5 +++-- 11 files changed, 24 insertions(+), 25 deletions(-) diff --git a/docs/snippets/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py index 1c430116d22..b69c17f0311 100644 --- a/docs/snippets/all/annotation_context_rects.py +++ b/docs/snippets/all/annotation_context_rects.py @@ -7,6 +7,3 @@ # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) - -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[2.5, 2.5])) diff --git a/docs/snippets/all/box2d_simple.py b/docs/snippets/all/box2d_simple.py index 864dbcddb75..c4d895b3c8c 100644 --- a/docs/snippets/all/box2d_simple.py +++ b/docs/snippets/all/box2d_simple.py @@ -5,6 +5,3 @@ rr.init("rerun_example_box2d", spawn=True) rr.log("simple", rr.Boxes2D(mins=[-1, -1], sizes=[2, 2])) - -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(sizes=[4.0, 3.0])) diff --git a/docs/snippets/all/extra_values.py b/docs/snippets/all/extra_values.py index 0d477be1c89..0f4ee366ab1 100644 --- a/docs/snippets/all/extra_values.py +++ b/docs/snippets/all/extra_values.py @@ -1,6 +1,7 @@ """Log extra values with a Points2D.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_extra_values", spawn=True) @@ -12,5 +13,5 @@ ), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(sizes=[3, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1.5, -1.5], max=[1.5, 1.5]))) diff --git a/docs/snippets/all/line_segments2d_simple.py b/docs/snippets/all/line_segments2d_simple.py index 1700bdaced3..6676dda3be0 100644 --- a/docs/snippets/all/line_segments2d_simple.py +++ b/docs/snippets/all/line_segments2d_simple.py @@ -2,6 +2,7 @@ import numpy as np import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_line_segments2d", spawn=True) @@ -10,5 +11,5 @@ rr.LineStrips2D(np.array([[[0, 0], [2, 1]], [[4, -1], [6, 0]]])), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(centers=[3, 0], half_sizes=[4, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 3]))) diff --git a/docs/snippets/all/line_strip2d_batch.py b/docs/snippets/all/line_strip2d_batch.py index a71c43f0bbb..7e72f53e105 100644 --- a/docs/snippets/all/line_strip2d_batch.py +++ b/docs/snippets/all/line_strip2d_batch.py @@ -1,6 +1,7 @@ """Log a batch of 2D line strips.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d_batch", spawn=True) @@ -17,5 +18,5 @@ ), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(centers=[3, 1.5], half_sizes=[4.0, 4.5])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 6]))) diff --git a/docs/snippets/all/line_strip2d_simple.py b/docs/snippets/all/line_strip2d_simple.py index 67ca4296e80..368e50662b5 100644 --- a/docs/snippets/all/line_strip2d_simple.py +++ b/docs/snippets/all/line_strip2d_simple.py @@ -1,6 +1,7 @@ """Log a simple line strip.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d", spawn=True) @@ -9,5 +10,5 @@ rr.LineStrips2D([[[0, 0], [2, 1], [4, -1], [6, 0]]]), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(centers=[3, 0], half_sizes=[4, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 3]))) diff --git a/docs/snippets/all/point2d_random.py b/docs/snippets/all/point2d_random.py index f4c4fb423be..fe100265e81 100644 --- a/docs/snippets/all/point2d_random.py +++ b/docs/snippets/all/point2d_random.py @@ -1,6 +1,7 @@ """Log some random points with color and radii.""" import rerun as rr +import rerun.blueprint as rrb from numpy.random import default_rng rr.init("rerun_example_points2d_random", spawn=True) @@ -12,5 +13,5 @@ rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[4, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4, -4], max=[4, 4]))) diff --git a/docs/snippets/all/point2d_simple.py b/docs/snippets/all/point2d_simple.py index 86d791ee067..569e4ab7227 100644 --- a/docs/snippets/all/point2d_simple.py +++ b/docs/snippets/all/point2d_simple.py @@ -1,10 +1,11 @@ """Log some very simple points.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_points2d", spawn=True) rr.log("points", rr.Points2D([[0, 0], [1, 1]])) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[2, 1.5])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -1], max=[2, 2]))) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index e0cf9418dc8..752998292eb 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -28,9 +28,6 @@ class Boxes2D(Boxes2DExt, Archetype): rr.init("rerun_example_box2d", spawn=True) rr.log("simple", rr.Boxes2D(mins=[-1, -1], sizes=[2, 2])) - - # Log an extra rect to set the view bounds - rr.log("bounds", rr.Boxes2D(sizes=[4.0, 3.0])) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index 735490af70d..f1995404a11 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -26,6 +26,7 @@ class LineStrips2D(Archetype): ### `line_strip2d_batch`: ```python import rerun as rr + import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d_batch", spawn=True) @@ -42,8 +43,8 @@ class LineStrips2D(Archetype): ), ) - # Log an extra rect to set the view bounds - rr.log("bounds", rr.Boxes2D(centers=[3, 1.5], half_sizes=[4.0, 4.5])) + # Set view bounds: + rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 6]))) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index e3348ea916b..25bcaaaef58 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -24,6 +24,7 @@ class Points2D(Points2DExt, Archetype): ### Randomly distributed 2D points with varying color and radius: ```python import rerun as rr + import rerun.blueprint as rrb from numpy.random import default_rng rr.init("rerun_example_points2d_random", spawn=True) @@ -35,8 +36,8 @@ class Points2D(Points2DExt, Archetype): rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) - # Log an extra rect to set the view bounds - rr.log("bounds", rr.Boxes2D(half_sizes=[4, 3])) + # Set view bounds: + rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4, -4], max=[4, 4]))) ```
From f1cdd5357d13a06e937da0a6b7444428b0d12824 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 14:09:27 +0200 Subject: [PATCH 16/20] Make the C++ and Rust snippets match the Python version --- docs/snippets/all/annotation_context_rects.cpp | 3 --- docs/snippets/all/annotation_context_rects.rs | 3 --- docs/snippets/all/box2d_simple.cpp | 3 --- docs/snippets/all/box2d_simple.rs | 3 --- docs/snippets/all/line_segments2d_simple.cpp | 3 +-- docs/snippets/all/line_segments2d_simple.rs | 6 +----- docs/snippets/all/line_strip2d_batch.cpp | 3 +-- docs/snippets/all/line_strip2d_batch.rs | 6 +----- docs/snippets/all/line_strip2d_simple.cpp | 3 +-- docs/snippets/all/line_strip2d_simple.rs | 6 +----- docs/snippets/all/point2d_random.cpp | 3 +-- docs/snippets/all/point2d_random.rs | 3 +-- docs/snippets/all/point2d_simple.cpp | 3 +-- docs/snippets/all/point2d_simple.rs | 3 +-- 14 files changed, 10 insertions(+), 41 deletions(-) diff --git a/docs/snippets/all/annotation_context_rects.cpp b/docs/snippets/all/annotation_context_rects.cpp index 4ba4c915070..e8c51745f89 100644 --- a/docs/snippets/all/annotation_context_rects.cpp +++ b/docs/snippets/all/annotation_context_rects.cpp @@ -23,7 +23,4 @@ int main() { {{3.0f, 3.0f}, {2.0f, 2.0f}} ).with_class_ids({1, 2}) ); - - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_half_sizes({{2.5f, 2.5f}})); } diff --git a/docs/snippets/all/annotation_context_rects.rs b/docs/snippets/all/annotation_context_rects.rs index 344fc1155db..866e037a26a 100644 --- a/docs/snippets/all/annotation_context_rects.rs +++ b/docs/snippets/all/annotation_context_rects.rs @@ -20,8 +20,5 @@ fn main() -> Result<(), Box> { .with_class_ids([1, 2]), )?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(2.5, 2.5)]))?; - Ok(()) } diff --git a/docs/snippets/all/box2d_simple.cpp b/docs/snippets/all/box2d_simple.cpp index 1030ceffb9b..41fd9499ea6 100644 --- a/docs/snippets/all/box2d_simple.cpp +++ b/docs/snippets/all/box2d_simple.cpp @@ -7,7 +7,4 @@ int main() { rec.spawn().exit_on_failure(); rec.log("simple", rerun::Boxes2D::from_mins_and_sizes({{-1.f, -1.f}}, {{2.f, 2.f}})); - - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_sizes({{4.f, 3.f}})); } diff --git a/docs/snippets/all/box2d_simple.rs b/docs/snippets/all/box2d_simple.rs index ad85656e64e..e0d785679e3 100644 --- a/docs/snippets/all/box2d_simple.rs +++ b/docs/snippets/all/box2d_simple.rs @@ -8,8 +8,5 @@ fn main() -> Result<(), Box> { &rerun::Boxes2D::from_mins_and_sizes([(-1., -1.)], [(2., 2.)]), )?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_sizes([(4., 3.)]))?; - Ok(()) } diff --git a/docs/snippets/all/line_segments2d_simple.cpp b/docs/snippets/all/line_segments2d_simple.cpp index e9ea998ceec..c4bad78d6c6 100644 --- a/docs/snippets/all/line_segments2d_simple.cpp +++ b/docs/snippets/all/line_segments2d_simple.cpp @@ -12,6 +12,5 @@ int main() { }; rec.log("segments", rerun::LineStrips2D(points)); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 0.0f}}, {{8.0f, 6.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/line_segments2d_simple.rs b/docs/snippets/all/line_segments2d_simple.rs index 36e6687a217..9b4d7ad3c51 100644 --- a/docs/snippets/all/line_segments2d_simple.rs +++ b/docs/snippets/all/line_segments2d_simple.rs @@ -6,11 +6,7 @@ fn main() -> Result<(), Box> { let points = [[0., 0.], [2., 1.], [4., -1.], [6., 0.]]; rec.log("segments", &rerun::LineStrips2D::new(points.chunks(2)))?; - // Log an extra rect to set the view bounds - rec.log( - "bounds", - &rerun::Boxes2D::from_centers_and_sizes([(3.0, 0.0)], [(8.0, 6.0)]), - )?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/line_strip2d_batch.cpp b/docs/snippets/all/line_strip2d_batch.cpp index 91508627b7a..9df91de80c4 100644 --- a/docs/snippets/all/line_strip2d_batch.cpp +++ b/docs/snippets/all/line_strip2d_batch.cpp @@ -19,6 +19,5 @@ int main() { .with_labels({"one strip here", "and one strip there"}) ); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 1.5f}}, {{8.0f, 9.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/line_strip2d_batch.rs b/docs/snippets/all/line_strip2d_batch.rs index d44120ae147..bb0b27ab793 100644 --- a/docs/snippets/all/line_strip2d_batch.rs +++ b/docs/snippets/all/line_strip2d_batch.rs @@ -14,11 +14,7 @@ fn main() -> Result<(), Box> { .with_labels(["one strip here", "and one strip there"]), )?; - // Log an extra rect to set the view bounds - rec.log( - "bounds", - &rerun::Boxes2D::from_centers_and_sizes([(3.0, 1.5)], [(8.0, 9.0)]), - )?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/line_strip2d_simple.cpp b/docs/snippets/all/line_strip2d_simple.cpp index 8a5d6faa357..c58ed459da4 100644 --- a/docs/snippets/all/line_strip2d_simple.cpp +++ b/docs/snippets/all/line_strip2d_simple.cpp @@ -9,6 +9,5 @@ int main() { const auto strip = rerun::LineStrip2D({{0.f, 0.f}, {2.f, 1.f}, {4.f, -1.f}, {6.f, 0.f}}); rec.log("strip", rerun::LineStrips2D(strip)); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 0.0f}}, {{8.0f, 6.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/line_strip2d_simple.rs b/docs/snippets/all/line_strip2d_simple.rs index 6ddd67027d6..1a80c2d218a 100644 --- a/docs/snippets/all/line_strip2d_simple.rs +++ b/docs/snippets/all/line_strip2d_simple.rs @@ -6,11 +6,7 @@ fn main() -> Result<(), Box> { let points = [[0., 0.], [2., 1.], [4., -1.], [6., 0.]]; rec.log("strip", &rerun::LineStrips2D::new([points]))?; - // Log an extra rect to set the view bounds - rec.log( - "bounds", - &rerun::Boxes2D::from_centers_and_sizes([(3., 0.)], [(8., 6.)]), - )?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/point2d_random.cpp b/docs/snippets/all/point2d_random.cpp index 5199256967a..26d74f7119d 100644 --- a/docs/snippets/all/point2d_random.cpp +++ b/docs/snippets/all/point2d_random.cpp @@ -33,6 +33,5 @@ int main() { rec.log("random", rerun::Points2D(points2d).with_colors(colors).with_radii(radii)); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_half_sizes({{4.0f, 3.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/point2d_random.rs b/docs/snippets/all/point2d_random.rs index 62d2150feae..d1d77d60117 100644 --- a/docs/snippets/all/point2d_random.rs +++ b/docs/snippets/all/point2d_random.rs @@ -15,8 +15,7 @@ fn main() -> Result<(), Box> { .with_radii((0..10).map(|_| rng.gen::())), )?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(4., 3.)]))?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/point2d_simple.cpp b/docs/snippets/all/point2d_simple.cpp index 05ecab38b3d..62cc7389c91 100644 --- a/docs/snippets/all/point2d_simple.cpp +++ b/docs/snippets/all/point2d_simple.cpp @@ -8,6 +8,5 @@ int main() { rec.log("points", rerun::Points2D({{0.0f, 0.0f}, {1.0f, 1.0f}})); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_half_sizes({{2.0f, 1.5f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/point2d_simple.rs b/docs/snippets/all/point2d_simple.rs index 114027c4f3e..3b21307e7c3 100644 --- a/docs/snippets/all/point2d_simple.rs +++ b/docs/snippets/all/point2d_simple.rs @@ -5,8 +5,7 @@ fn main() -> Result<(), Box> { rec.log("points", &rerun::Points2D::new([(0.0, 0.0), (1.0, 1.0)]))?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(2.0, 1.5)]))?; + // TODO(#5521): log VisualBounds Ok(()) } From 0d86e08c6212939f751a50db97faad9e1f25b3f2 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 14:18:01 +0200 Subject: [PATCH 17/20] Add missing `default_bliueprint` to tests --- crates/re_space_view/src/space_view.rs | 4 ++++ crates/re_space_view/src/space_view_contents.rs | 1 + 2 files changed, 5 insertions(+) diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 94936b7daaa..8f700529f15 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -553,6 +553,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), @@ -597,6 +598,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), @@ -647,6 +649,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), @@ -920,6 +923,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 82116aef381..fa99d65b506 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -695,6 +695,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &StoreHub::test_hub(), From 4795eb7e1ece6e3404fde6888e9d80f60060dbfc Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 14:23:05 +0200 Subject: [PATCH 18/20] codegen --- crates/re_types/src/archetypes/boxes2d.rs | 3 --- crates/re_types/src/archetypes/line_strips2d.rs | 6 +----- crates/re_types/src/archetypes/points2d.rs | 3 +-- rerun_cpp/src/rerun/archetypes/boxes2d.hpp | 3 --- rerun_cpp/src/rerun/archetypes/line_strips2d.hpp | 3 +-- rerun_cpp/src/rerun/archetypes/points2d.hpp | 3 +-- 6 files changed, 4 insertions(+), 17 deletions(-) diff --git a/crates/re_types/src/archetypes/boxes2d.rs b/crates/re_types/src/archetypes/boxes2d.rs index 157edaad7e6..09fe6905289 100644 --- a/crates/re_types/src/archetypes/boxes2d.rs +++ b/crates/re_types/src/archetypes/boxes2d.rs @@ -36,9 +36,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// &rerun::Boxes2D::from_mins_and_sizes([(-1., -1.)], [(2., 2.)]), /// )?; /// -/// // Log an extra rect to set the view bounds -/// rec.log("bounds", &rerun::Boxes2D::from_sizes([(4., 3.)]))?; -/// /// Ok(()) /// } /// ``` diff --git a/crates/re_types/src/archetypes/line_strips2d.rs b/crates/re_types/src/archetypes/line_strips2d.rs index 5f99edf23cc..a001bb9b97a 100644 --- a/crates/re_types/src/archetypes/line_strips2d.rs +++ b/crates/re_types/src/archetypes/line_strips2d.rs @@ -42,11 +42,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .with_labels(["one strip here", "and one strip there"]), /// )?; /// -/// // Log an extra rect to set the view bounds -/// rec.log( -/// "bounds", -/// &rerun::Boxes2D::from_centers_and_sizes([(3.0, 1.5)], [(8.0, 9.0)]), -/// )?; +/// // TODO(#5521): log VisualBounds /// /// Ok(()) /// } diff --git a/crates/re_types/src/archetypes/points2d.rs b/crates/re_types/src/archetypes/points2d.rs index 5c90d8f7680..70993dd824d 100644 --- a/crates/re_types/src/archetypes/points2d.rs +++ b/crates/re_types/src/archetypes/points2d.rs @@ -43,8 +43,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .with_radii((0..10).map(|_| rng.gen::())), /// )?; /// -/// // Log an extra rect to set the view bounds -/// rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(4., 3.)]))?; +/// // TODO(#5521): log VisualBounds /// /// Ok(()) /// } diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp index 70cc3bf45f9..8742f92b6cf 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp @@ -37,9 +37,6 @@ namespace rerun::archetypes { /// rec.spawn().exit_on_failure(); /// /// rec.log("simple", rerun::Boxes2D::from_mins_and_sizes({{-1.f, -1.f}}, {{2.f, 2.f}})); - /// - /// // Log an extra rect to set the view bounds - /// rec.log("bounds", rerun::Boxes2D::from_sizes({{4.f, 3.f}})); /// } /// ``` struct Boxes2D { diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp index ea7590b061e..a6b4f5e6b23 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp @@ -48,8 +48,7 @@ namespace rerun::archetypes { /// .with_labels({"one strip here", "and one strip there"}) /// ); /// - /// // Log an extra rect to set the view bounds - /// rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 1.5f}}, {{8.0f, 9.0f}})); + /// // TODO(#5520): log VisualBounds /// } /// ``` struct LineStrips2D { diff --git a/rerun_cpp/src/rerun/archetypes/points2d.hpp b/rerun_cpp/src/rerun/archetypes/points2d.hpp index 536d83b4268..171718d731f 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.hpp @@ -63,8 +63,7 @@ namespace rerun::archetypes { /// /// rec.log("random", rerun::Points2D(points2d).with_colors(colors).with_radii(radii)); /// - /// // Log an extra rect to set the view bounds - /// rec.log("bounds", rerun::Boxes2D::from_half_sizes({{4.0f, 3.0f}})); + /// // TODO(#5520): log VisualBounds /// } /// ``` struct Points2D { From f6b89f3ee806725149d9e7b67c66845a97d444e3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 14:46:39 +0200 Subject: [PATCH 19/20] Remove reference to deleted thing --- crates/re_space_view_spatial/src/ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 958d6714490..4d8c7198b3b 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -52,7 +52,7 @@ impl From for WidgetText { } } -/// TODO(andreas): Should turn this "inside out" - [`SpatialSpaceViewState`] should be used by [`View2DState`]/[`View3DState`], not the other way round. +/// TODO(andreas): Should turn this "inside out" - [`SpatialSpaceViewState`] should be used by [`View3DState`], not the other way round. #[derive(Clone, Default)] pub struct SpatialSpaceViewState { pub bounding_boxes: SceneBoundingBoxes, From ac3a4402f48f19c967596cf9974d42f055973835 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 17:02:16 +0200 Subject: [PATCH 20/20] `vector` -> `aabb` --- .../re_types/definitions/rerun/components/aabb2d.fbs | 2 +- crates/re_types/src/components/aabb2d.rs | 4 ++-- docs/content/reference/types/components/aabb2d.md | 2 +- rerun_cpp/src/rerun/components/aabb2d.hpp | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/re_types/definitions/rerun/components/aabb2d.fbs b/crates/re_types/definitions/rerun/components/aabb2d.fbs index b2264019b7e..6855c9298a9 100644 --- a/crates/re_types/definitions/rerun/components/aabb2d.fbs +++ b/crates/re_types/definitions/rerun/components/aabb2d.fbs @@ -14,5 +14,5 @@ struct AABB2D ( "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", "attr.rust.repr": "transparent" ) { - vector: rerun.datatypes.AABB2D (order: 100); + aabb: rerun.datatypes.AABB2D (order: 100); } diff --git a/crates/re_types/src/components/aabb2d.rs b/crates/re_types/src/components/aabb2d.rs index 36d15afb45d..fd332cff360 100644 --- a/crates/re_types/src/components/aabb2d.rs +++ b/crates/re_types/src/components/aabb2d.rs @@ -123,12 +123,12 @@ impl ::re_types_core::Loggable for AABB2D { use ::re_types_core::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; Ok(crate::datatypes::AABB2D::from_arrow_opt(arrow_data) - .with_context("rerun.components.AABB2D#vector")? + .with_context("rerun.components.AABB2D#aabb")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) .map(|res| res.map(|v| Some(Self(v)))) .collect::>>>() - .with_context("rerun.components.AABB2D#vector") + .with_context("rerun.components.AABB2D#aabb") .with_context("rerun.components.AABB2D")?) } } diff --git a/docs/content/reference/types/components/aabb2d.md b/docs/content/reference/types/components/aabb2d.md index 6ca71b7056c..e309a3ed321 100644 --- a/docs/content/reference/types/components/aabb2d.md +++ b/docs/content/reference/types/components/aabb2d.md @@ -6,7 +6,7 @@ An Axis-Aligned Bounding Box in 2D space. ## Fields -* vector: [`AABB2D`](../datatypes/aabb2d.md) +* aabb: [`AABB2D`](../datatypes/aabb2d.md) ## Links * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AABB2D.html) diff --git a/rerun_cpp/src/rerun/components/aabb2d.hpp b/rerun_cpp/src/rerun/components/aabb2d.hpp index c31753d4909..07d00176a8b 100644 --- a/rerun_cpp/src/rerun/components/aabb2d.hpp +++ b/rerun_cpp/src/rerun/components/aabb2d.hpp @@ -12,21 +12,21 @@ namespace rerun::components { /// **Component**: An Axis-Aligned Bounding Box in 2D space. struct AABB2D { - rerun::datatypes::AABB2D vector; + rerun::datatypes::AABB2D aabb; public: AABB2D() = default; - AABB2D(rerun::datatypes::AABB2D vector_) : vector(vector_) {} + AABB2D(rerun::datatypes::AABB2D aabb_) : aabb(aabb_) {} - AABB2D& operator=(rerun::datatypes::AABB2D vector_) { - vector = vector_; + AABB2D& operator=(rerun::datatypes::AABB2D aabb_) { + aabb = aabb_; return *this; } /// Cast to the underlying AABB2D datatype operator rerun::datatypes::AABB2D() const { - return vector; + return aabb; } }; } // namespace rerun::components @@ -48,7 +48,7 @@ namespace rerun { static Result> to_arrow( const components::AABB2D* instances, size_t num_instances ) { - return Loggable::to_arrow(&instances->vector, num_instances); + return Loggable::to_arrow(&instances->aabb, num_instances); } }; } // namespace rerun