diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs index 47eb842fc7c0..849f516aff66 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs @@ -3,6 +3,7 @@ include "./archetypes/background.fbs"; include "./archetypes/container_blueprint.fbs"; include "./archetypes/dataframe_query.fbs"; +include "./archetypes/default_camera.fbs"; include "./archetypes/map_background.fbs"; include "./archetypes/map_zoom.fbs"; include "./archetypes/panel_blueprint.fbs"; diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs new file mode 100644 index 000000000000..063e8fd58e9f --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs @@ -0,0 +1,16 @@ +namespace rerun.blueprint.archetypes; + + +/// Defines a default camera view. +table DefaultCamera ( + "attr.docs.category": "Spatial 3D", + "attr.docs.view_types": "Spatial3DView, Spatial2DView: if logged above active projection", + "attr.rust.derive": "Copy, PartialEq", + "attr.rerun.scope": "blueprint" +) { + /// Origin of the camera view. + origin: rerun.blueprint.components.CameraOrigin ("attr.rerun.component_optional", nullable, order: 1100); + + /// Target of the camera view. + target: rerun.blueprint.components.CameraTarget ("attr.rerun.component_optional", nullable, order: 1200); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/components.fbs b/crates/store/re_types/definitions/rerun/blueprint/components.fbs index 83ff2b9e8bdd..08827d2783e8 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/components.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/components.fbs @@ -5,6 +5,7 @@ include "./components/apply_latest_at.fbs"; include "./components/auto_layout.fbs"; include "./components/auto_space_views.fbs"; include "./components/background_kind.fbs"; +include "./components/camera_views.fbs"; include "./components/column_share.fbs"; include "./components/component_column_selector.fbs"; include "./components/container_kind.fbs"; diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs new file mode 100644 index 000000000000..e30fb43d8fe1 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs @@ -0,0 +1,24 @@ +namespace rerun.blueprint.components; + + +/// Origin of a camera. +struct CameraOrigin ( + "attr.rust.derive": "PartialEq, Copy", + "attr.rust.repr": "transparent", + "attr.rerun.scope": "blueprint" +) { + /// Position of the camera origin. + pos: rerun.datatypes.Vec3D (order: 100); +} + + +/// Target of a camera. +struct CameraTarget ( + "attr.rust.derive": "PartialEq, Copy", + "attr.rust.repr": "transparent", + "attr.rerun.scope": "blueprint" +) { + /// Position of the camera target. + pos: rerun.datatypes.Vec3D (order: 100); +} + diff --git a/crates/store/re_types/definitions/rerun/blueprint/views/spatial3d.fbs b/crates/store/re_types/definitions/rerun/blueprint/views/spatial3d.fbs index 53d18994433b..64d6fa2c2dfc 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/views/spatial3d.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/views/spatial3d.fbs @@ -14,4 +14,7 @@ table Spatial3DView ( /// If not specified, the default is to show the latest state of each component. /// If a timeline is specified more than once, the first entry will be used. time_ranges: rerun.blueprint.archetypes.VisibleTimeRanges (order: 10000); + + /// Configures the default camera position of the 3D view. + default_camera: rerun.blueprint.archetypes.DefaultCamera (order: 20000); } diff --git a/crates/store/re_types/src/blueprint/archetypes/.gitattributes b/crates/store/re_types/src/blueprint/archetypes/.gitattributes index 158c53d4bb45..e84f13af0c11 100644 --- a/crates/store/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/store/re_types/src/blueprint/archetypes/.gitattributes @@ -3,6 +3,7 @@ .gitattributes linguist-generated=true background.rs linguist-generated=true dataframe_query.rs linguist-generated=true +default_camera.rs linguist-generated=true map_background.rs linguist-generated=true map_zoom.rs linguist-generated=true mod.rs linguist-generated=true diff --git a/crates/store/re_types/src/blueprint/archetypes/default_camera.rs b/crates/store/re_types/src/blueprint/archetypes/default_camera.rs new file mode 100644 index 000000000000..29f813a15efd --- /dev/null +++ b/crates/store/re_types/src/blueprint/archetypes/default_camera.rs @@ -0,0 +1,198 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +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**: Defines a default camera view. +#[derive(Clone, Debug, Copy, PartialEq)] +pub struct DefaultCamera { + /// Origin of the camera view. + pub origin: Option, + + /// Target of the camera view. + pub target: Option, +} + +impl ::re_types_core::SizeBytes for DefaultCamera { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.origin.heap_size_bytes() + self.target.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::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.DefaultCameraIndicator".into()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.CameraOrigin".into(), + "rerun.blueprint.components.CameraTarget".into(), + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.DefaultCameraIndicator".into(), + "rerun.blueprint.components.CameraOrigin".into(), + "rerun.blueprint.components.CameraTarget".into(), + ] + }); + +impl DefaultCamera { + /// The total number of components in the archetype: 0 required, 1 recommended, 2 optional + pub const NUM_COMPONENTS: usize = 3usize; +} + +/// Indicator component for the [`DefaultCamera`] [`::re_types_core::Archetype`] +pub type DefaultCameraIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for DefaultCamera { + type Indicator = DefaultCameraIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.DefaultCamera".into() + } + + #[inline] + fn display_name() -> &'static str { + "Default camera" + } + + #[inline] + fn indicator() -> MaybeOwnedComponentBatch<'static> { + static INDICATOR: DefaultCameraIndicator = DefaultCameraIndicator::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 origin = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.CameraOrigin") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.DefaultCamera#origin")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let target = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.CameraTarget") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.DefaultCamera#target")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { origin, target }) + } +} + +impl ::re_types_core::AsComponents for DefaultCamera { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.origin + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + self.target + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for DefaultCamera {} + +impl DefaultCamera { + /// Create a new `DefaultCamera`. + #[inline] + pub fn new() -> Self { + Self { + origin: None, + target: None, + } + } + + /// Origin of the camera view. + #[inline] + pub fn with_origin( + mut self, + origin: impl Into, + ) -> Self { + self.origin = Some(origin.into()); + self + } + + /// Target of the camera view. + #[inline] + pub fn with_target( + mut self, + target: impl Into, + ) -> Self { + self.target = Some(target.into()); + self + } +} diff --git a/crates/store/re_types/src/blueprint/archetypes/mod.rs b/crates/store/re_types/src/blueprint/archetypes/mod.rs index 360c1b887939..2a2e762ca318 100644 --- a/crates/store/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/store/re_types/src/blueprint/archetypes/mod.rs @@ -2,6 +2,7 @@ mod background; mod dataframe_query; +mod default_camera; mod map_background; mod map_zoom; mod plot_legend; @@ -17,6 +18,7 @@ mod visual_bounds2d; pub use self::background::Background; pub use self::dataframe_query::DataframeQuery; +pub use self::default_camera::DefaultCamera; pub use self::map_background::MapBackground; pub use self::map_zoom::MapZoom; pub use self::plot_legend::PlotLegend; diff --git a/crates/store/re_types/src/blueprint/components/.gitattributes b/crates/store/re_types/src/blueprint/components/.gitattributes index 4a1915dc979d..3490f04a68c2 100644 --- a/crates/store/re_types/src/blueprint/components/.gitattributes +++ b/crates/store/re_types/src/blueprint/components/.gitattributes @@ -4,6 +4,8 @@ active_tab.rs linguist-generated=true apply_latest_at.rs linguist-generated=true background_kind.rs linguist-generated=true +camera_origin.rs linguist-generated=true +camera_target.rs linguist-generated=true column_share.rs linguist-generated=true component_column_selector.rs linguist-generated=true corner2d.rs linguist-generated=true diff --git a/crates/store/re_types/src/blueprint/components/camera_origin.rs b/crates/store/re_types/src/blueprint/components/camera_origin.rs new file mode 100644 index 000000000000..ba15c2fc0fe9 --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/camera_origin.rs @@ -0,0 +1,116 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +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**: Origin of a camera. +#[derive(Clone, Debug, PartialEq, Copy)] +#[repr(transparent)] +pub struct CameraOrigin( + /// Position of the camera origin. + pub crate::datatypes::Vec3D, +); + +impl ::re_types_core::SizeBytes for CameraOrigin { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for CameraOrigin { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for CameraOrigin { + #[inline] + fn borrow(&self) -> &crate::datatypes::Vec3D { + &self.0 + } +} + +impl std::ops::Deref for CameraOrigin { + type Target = crate::datatypes::Vec3D; + + #[inline] + fn deref(&self) -> &crate::datatypes::Vec3D { + &self.0 + } +} + +impl std::ops::DerefMut for CameraOrigin { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Vec3D { + &mut self.0 + } +} + +::re_types_core::macros::impl_into_cow!(CameraOrigin); + +impl ::re_types_core::Loggable for CameraOrigin { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.CameraOrigin".into() + } + + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + crate::datatypes::Vec3D::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + crate::datatypes::Vec3D::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::Vec3D::from_arrow_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } + + #[inline] + fn from_arrow(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> + where + Self: Sized, + { + crate::datatypes::Vec3D::from_arrow(arrow_data).map(|v| v.into_iter().map(Self).collect()) + } +} diff --git a/crates/store/re_types/src/blueprint/components/camera_target.rs b/crates/store/re_types/src/blueprint/components/camera_target.rs new file mode 100644 index 000000000000..e6b0f0df8da6 --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/camera_target.rs @@ -0,0 +1,116 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +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**: Target of a camera. +#[derive(Clone, Debug, PartialEq, Copy)] +#[repr(transparent)] +pub struct CameraTarget( + /// Position of the camera target. + pub crate::datatypes::Vec3D, +); + +impl ::re_types_core::SizeBytes for CameraTarget { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for CameraTarget { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for CameraTarget { + #[inline] + fn borrow(&self) -> &crate::datatypes::Vec3D { + &self.0 + } +} + +impl std::ops::Deref for CameraTarget { + type Target = crate::datatypes::Vec3D; + + #[inline] + fn deref(&self) -> &crate::datatypes::Vec3D { + &self.0 + } +} + +impl std::ops::DerefMut for CameraTarget { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Vec3D { + &mut self.0 + } +} + +::re_types_core::macros::impl_into_cow!(CameraTarget); + +impl ::re_types_core::Loggable for CameraTarget { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.CameraTarget".into() + } + + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + crate::datatypes::Vec3D::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + crate::datatypes::Vec3D::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::Vec3D::from_arrow_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } + + #[inline] + fn from_arrow(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> + where + Self: Sized, + { + crate::datatypes::Vec3D::from_arrow(arrow_data).map(|v| v.into_iter().map(Self).collect()) + } +} diff --git a/crates/store/re_types/src/blueprint/components/mod.rs b/crates/store/re_types/src/blueprint/components/mod.rs index a915957fd392..1198933f79cf 100644 --- a/crates/store/re_types/src/blueprint/components/mod.rs +++ b/crates/store/re_types/src/blueprint/components/mod.rs @@ -3,6 +3,8 @@ mod active_tab; mod apply_latest_at; mod background_kind; +mod camera_origin; +mod camera_target; mod column_share; mod component_column_selector; mod component_column_selector_ext; @@ -43,6 +45,8 @@ mod zoom_level; pub use self::active_tab::ActiveTab; pub use self::apply_latest_at::ApplyLatestAt; pub use self::background_kind::BackgroundKind; +pub use self::camera_origin::CameraOrigin; +pub use self::camera_target::CameraTarget; pub use self::column_share::ColumnShare; pub use self::component_column_selector::ComponentColumnSelector; pub use self::corner2d::Corner2D; diff --git a/crates/store/re_types/src/blueprint/views/spatial3d_view.rs b/crates/store/re_types/src/blueprint/views/spatial3d_view.rs index 7eb491d3334f..0d7de93be259 100644 --- a/crates/store/re_types/src/blueprint/views/spatial3d_view.rs +++ b/crates/store/re_types/src/blueprint/views/spatial3d_view.rs @@ -29,18 +29,24 @@ pub struct Spatial3DView { /// If not specified, the default is to show the latest state of each component. /// If a timeline is specified more than once, the first entry will be used. pub time_ranges: crate::blueprint::archetypes::VisibleTimeRanges, + + /// Configures the default camera position of the 3D view. + pub default_camera: crate::blueprint::archetypes::DefaultCamera, } impl ::re_types_core::SizeBytes for Spatial3DView { #[inline] fn heap_size_bytes(&self) -> u64 { - self.background.heap_size_bytes() + self.time_ranges.heap_size_bytes() + self.background.heap_size_bytes() + + self.time_ranges.heap_size_bytes() + + self.default_camera.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() && ::is_pod() + && ::is_pod() } } diff --git a/crates/viewer/re_space_view_spatial/src/ui_3d.rs b/crates/viewer/re_space_view_spatial/src/ui_3d.rs index bcf45adeb3e3..0812abb93df4 100644 --- a/crates/viewer/re_space_view_spatial/src/ui_3d.rs +++ b/crates/viewer/re_space_view_spatial/src/ui_3d.rs @@ -13,7 +13,13 @@ use re_space_view::controls::{ ROTATE3D_BUTTON, SPEED_UP_3D_MODIFIER, TRACKED_OBJECT_RESTORE_KEY, }; use re_types::{ - blueprint::archetypes::Background, components::ViewCoordinates, view_coordinates::SignedAxis3, + blueprint::{ + archetypes::{Background, DefaultCamera}, + components::{CameraOrigin, CameraTarget}, + }, + components::ViewCoordinates, + datatypes::Vec3D, + view_coordinates::SignedAxis3, }; use re_ui::{ContextExt, ModifiersMarkdown, MouseButtonMarkdown}; use re_viewer_context::{ @@ -41,6 +47,8 @@ use super::eye::{Eye, ViewEye}; pub struct View3DState { pub view_eye: Option, + pub view_eye_default: Option, + /// Used to show the orbit center of the eye-camera when the user interacts. /// None: user has never interacted with the eye-camera. pub last_eye_interaction: Option, @@ -73,6 +81,7 @@ impl Default for View3DState { fn default() -> Self { Self { view_eye: Default::default(), + view_eye_default: Default::default(), last_eye_interaction: None, tracked_entity: None, camera_before_tracked_entity: None, @@ -92,6 +101,10 @@ fn ease_out(t: f32) -> f32 { 1. - (1. - t) * (1. - t) } +fn vec3(v: Vec3D) -> Vec3 { + Vec3::from_array(v.0) +} + impl View3DState { pub fn reset_camera( &mut self, @@ -101,7 +114,10 @@ impl View3DState { // Mark as interaction since we want to stop doing any automatic interpolations, // even if this is caused by a full reset. self.last_eye_interaction = Some(Instant::now()); - self.interpolate_to_view_eye(default_eye(&scene_bbox.current, scene_view_coordinates)); + self.interpolate_to_view_eye( + self.view_eye_default + .unwrap_or(default_eye(&scene_bbox.current, scene_view_coordinates)), + ); self.tracked_entity = None; self.camera_before_tracked_entity = None; } @@ -112,7 +128,28 @@ impl View3DState { bounding_boxes: &SceneBoundingBoxes, space_cameras: &[SpaceCamera3D], scene_view_coordinates: Option, + default_camera: &ViewProperty, ) -> ViewEye { + if let Ok(Some(pos_origin)) = default_camera.component_or_empty::() { + if let Ok(Some(pos_target)) = default_camera.component_or_empty::() { + if self.view_eye_default.is_none() { + // Facking last eye interaction. Otherwise the next `if` + // statement in this function causes the camera to change + // if there is a change to the bounding box (e.g. when new + // objects are added to the scene.) + self.last_eye_interaction = Some(Instant::now()); + + self.view_eye_default = Some(from_to_eye( + vec3(pos_origin.0), + vec3(pos_target.0), + scene_view_coordinates, + )); + + self.view_eye = self.view_eye_default; + } + } + } + // If the user has not interacted with the eye-camera yet, continue to // interpolate to the new default eye. This gives much better robustness // with scenes that change over time. @@ -446,11 +483,18 @@ impl SpatialSpaceView3D { return Ok(()); // protect against problems with zero-sized views } + let default_camera = ViewProperty::from_archetype::( + ctx.blueprint_db(), + ctx.blueprint_query, + query.space_view_id, + ); + let view_eye = state.state_3d.update_eye( &response, &state.bounding_boxes, space_cameras, scene_view_coordinates, + &default_camera, ); let eye = view_eye.to_eye(); @@ -909,6 +953,22 @@ fn add_picking_ray( .radius(Size::new_ui_points(0.5)); } +fn from_to_eye(from: Vec3, to: Vec3, scene_view_coordinates: Option) -> ViewEye { + let scene_up = scene_view_coordinates + .unwrap_or_default() + .up() + .unwrap_or(SignedAxis3::POSITIVE_Z); + + let eye_up: glam::Vec3 = scene_up.into(); + + ViewEye::new_orbital( + to, + from.distance(to), + Quat::from_affine3(&Affine3A::look_at_rh(from, to, eye_up).inverse()), + eye_up, + ) +} + fn default_eye( bounding_box: &re_math::BoundingBox, scene_view_coordinates: Option, diff --git a/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs index da5fcef01771..cc73293db1eb 100644 --- a/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs @@ -4,6 +4,8 @@ use re_entity_db::EntityDb; pub use re_types::blueprint::components::ActiveTab; pub use re_types::blueprint::components::ApplyLatestAt; pub use re_types::blueprint::components::BackgroundKind; +pub use re_types::blueprint::components::CameraOrigin; +pub use re_types::blueprint::components::CameraTarget; pub use re_types::blueprint::components::ColumnShare; pub use re_types::blueprint::components::ComponentColumnSelector; pub use re_types::blueprint::components::Corner2D; @@ -45,6 +47,8 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) + && validate_component::(blueprint) + && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) diff --git a/crates/viewer/re_viewer/src/reflection/mod.rs b/crates/viewer/re_viewer/src/reflection/mod.rs index 4d8643b5c7fb..ffea55192435 100644 --- a/crates/viewer/re_viewer/src/reflection/mod.rs +++ b/crates/viewer/re_viewer/src/reflection/mod.rs @@ -69,6 +69,20 @@ fn generate_component_reflection() -> Result::name(), + ComponentReflection { + docstring_md: "Origin of a camera.", + custom_placeholder: None, + }, + ), + ( + ::name(), + ComponentReflection { + docstring_md: "Target of a camera.", + custom_placeholder: None, + }, + ), ( ::name(), ComponentReflection { @@ -1681,6 +1695,21 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ], }, ), + ( + ArchetypeName::new("rerun.blueprint.archetypes.DefaultCamera"), + ArchetypeReflection { + display_name: "Default camera", + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.CameraOrigin".into(), display_name : + "Origin", docstring_md : "Origin of the camera view.", is_required : + false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.CameraTarget".into(), display_name : + "Target", docstring_md : "Target of the camera view.", is_required : + false, }, + ], + }, + ), ( ArchetypeName::new("rerun.blueprint.archetypes.MapBackground"), ArchetypeReflection { diff --git a/docs/content/reference/types/views/spatial2d_view.md b/docs/content/reference/types/views/spatial2d_view.md index 958e931f5efd..06a99f6f0910 100644 --- a/docs/content/reference/types/views/spatial2d_view.md +++ b/docs/content/reference/types/views/spatial2d_view.md @@ -68,4 +68,5 @@ snippet: views/spatial2d * [`Mesh3D`](../archetypes/mesh3d.md) (if logged above active projection) * [`Points3D`](../archetypes/points3d.md) (if logged above active projection) * [`Transform3D`](../archetypes/transform3d.md) (if logged above active projection) +* [`DefaultCamera`](../archetypes/default_camera.md) (if logged above active projection) diff --git a/docs/content/reference/types/views/spatial3d_view.md b/docs/content/reference/types/views/spatial3d_view.md index 95f5ecbb2068..4ed6788e41b4 100644 --- a/docs/content/reference/types/views/spatial3d_view.md +++ b/docs/content/reference/types/views/spatial3d_view.md @@ -17,6 +17,11 @@ Configures which range on each timeline is shown by this view (unless specified If not specified, the default is to show the latest state of each component. If a timeline is specified more than once, the first entry will be used. +### `default_camera` +Configures the default camera position of the 3D view. + +* `origin`: Origin of the camera view. +* `target`: Target of the camera view. ## API reference links * 🐍 [Python API docs for `Spatial3DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial3DView) @@ -52,6 +57,7 @@ snippet: views/spatial3d * [`Points3D`](../archetypes/points3d.md) * [`Transform3D`](../archetypes/transform3d.md) * [`ViewCoordinates`](../archetypes/view_coordinates.md) +* [`DefaultCamera`](../archetypes/default_camera.md) * [`Arrows2D`](../archetypes/arrows2d.md) (if logged under a projection) * [`AssetVideo`](../archetypes/asset_video.md) (if logged under a projection) * [`Boxes2D`](../archetypes/boxes2d.md) (if logged under a projection) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index 2fd779424b1f..1bfccee85ac9 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -5,6 +5,7 @@ #include "blueprint/archetypes/background.hpp" #include "blueprint/archetypes/container_blueprint.hpp" #include "blueprint/archetypes/dataframe_query.hpp" +#include "blueprint/archetypes/default_camera.hpp" #include "blueprint/archetypes/map_background.hpp" #include "blueprint/archetypes/map_zoom.hpp" #include "blueprint/archetypes/panel_blueprint.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 26e1a60b89a6..eb88a75aae07 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -7,6 +7,8 @@ container_blueprint.cpp linguist-generated=true container_blueprint.hpp linguist-generated=true dataframe_query.cpp linguist-generated=true dataframe_query.hpp linguist-generated=true +default_camera.cpp linguist-generated=true +default_camera.hpp linguist-generated=true map_background.cpp linguist-generated=true map_background.hpp linguist-generated=true map_zoom.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/default_camera.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/default_camera.cpp new file mode 100644 index 000000000000..58539eddc46d --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/default_camera.cpp @@ -0,0 +1,39 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs". + +#include "default_camera.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> + AsComponents::serialize( + const blueprint::archetypes::DefaultCamera& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(3); + + if (archetype.origin.has_value()) { + auto result = ComponentBatch::from_loggable(archetype.origin.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.target.has_value()) { + auto result = ComponentBatch::from_loggable(archetype.target.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = DefaultCamera::IndicatorComponent(); + auto result = ComponentBatch::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/default_camera.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/default_camera.hpp new file mode 100644 index 000000000000..c63e4f8a5d10 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/default_camera.hpp @@ -0,0 +1,69 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs". + +#pragma once + +#include "../../blueprint/components/camera_origin.hpp" +#include "../../blueprint/components/camera_target.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Defines a default camera view. + struct DefaultCamera { + /// Origin of the camera view. + std::optional origin; + + /// Target of the camera view. + std::optional target; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.DefaultCameraIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + DefaultCamera() = default; + DefaultCamera(DefaultCamera&& other) = default; + + /// Origin of the camera view. + DefaultCamera with_origin(rerun::blueprint::components::CameraOrigin _origin) && { + origin = std::move(_origin); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// Target of the camera view. + DefaultCamera with_target(rerun::blueprint::components::CameraTarget _target) && { + target = std::move(_target); + // 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::DefaultCamera& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index 9499183c3571..bfb002a96aab 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -7,6 +7,8 @@ #include "blueprint/components/auto_layout.hpp" #include "blueprint/components/auto_space_views.hpp" #include "blueprint/components/background_kind.hpp" +#include "blueprint/components/camera_origin.hpp" +#include "blueprint/components/camera_target.hpp" #include "blueprint/components/column_share.hpp" #include "blueprint/components/component_column_selector.hpp" #include "blueprint/components/container_kind.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index 8bf0eaf38c0e..4f32671130a5 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -7,6 +7,8 @@ auto_layout.hpp linguist-generated=true auto_space_views.hpp linguist-generated=true background_kind.cpp linguist-generated=true background_kind.hpp linguist-generated=true +camera_origin.hpp linguist-generated=true +camera_target.hpp linguist-generated=true column_share.hpp linguist-generated=true component_column_selector.hpp linguist-generated=true container_kind.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/camera_target.hpp b/rerun_cpp/src/rerun/blueprint/components/camera_target.hpp new file mode 100644 index 000000000000..70ae37fc72f7 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/camera_target.hpp @@ -0,0 +1,72 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs". + +#pragma once + +#include "../../datatypes/vec3d.hpp" +#include "../../result.hpp" + +#include +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: Target of a camera. + struct CameraTarget { + /// Position of the camera target. + rerun::datatypes::Vec3D pos; + + public: + CameraTarget() = default; + + CameraTarget(rerun::datatypes::Vec3D pos_) : pos(pos_) {} + + CameraTarget& operator=(rerun::datatypes::Vec3D pos_) { + pos = pos_; + return *this; + } + + CameraTarget(std::array xyz_) : pos(xyz_) {} + + CameraTarget& operator=(std::array xyz_) { + pos = xyz_; + return *this; + } + + /// Cast to the underlying Vec3D datatype + operator rerun::datatypes::Vec3D() const { + return pos; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(blueprint::components::CameraTarget)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.CameraTarget"; + + /// 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::blueprint:: components::CameraTarget` into an arrow array. + static Result> to_arrow( + const blueprint::components::CameraTarget* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow(&instances->pos, num_instances); + } + } + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 3ba51bcc058f..faeb41c97f00 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -29,6 +29,7 @@ ) from .archetypes import ( Background as Background, + DefaultCamera as DefaultCamera, PlotLegend as PlotLegend, ScalarAxis as ScalarAxis, TensorScalarMapping as TensorScalarMapping, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index bb528bfbaf9a..68e7239918e1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -5,6 +5,7 @@ __init__.py linguist-generated=true background.py linguist-generated=true container_blueprint.py linguist-generated=true dataframe_query.py linguist-generated=true +default_camera.py linguist-generated=true map_background.py linguist-generated=true map_zoom.py linguist-generated=true panel_blueprint.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 018ec6c34d5e..8b0022cf0f79 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -5,6 +5,7 @@ from .background import Background from .container_blueprint import ContainerBlueprint from .dataframe_query import DataframeQuery +from .default_camera import DefaultCamera from .map_background import MapBackground from .map_zoom import MapZoom from .panel_blueprint import PanelBlueprint @@ -23,6 +24,7 @@ "Background", "ContainerBlueprint", "DataframeQuery", + "DefaultCamera", "MapBackground", "MapZoom", "PanelBlueprint", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/default_camera.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/default_camera.py new file mode 100644 index 000000000000..c0ec29f6f1a0 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/default_camera.py @@ -0,0 +1,78 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/default_camera.fbs". + +# You can extend this class by creating a "DefaultCameraExt" class in "default_camera_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["DefaultCamera"] + + +@define(str=False, repr=False, init=False) +class DefaultCamera(Archetype): + """**Archetype**: Defines a default camera view.""" + + def __init__(self: Any, *, origin: datatypes.Vec3DLike | None = None, target: datatypes.Vec3DLike | None = None): + """ + Create a new instance of the DefaultCamera archetype. + + Parameters + ---------- + origin: + Origin of the camera view. + target: + Target of the camera view. + + """ + + # You can define your own __init__ function as a member of DefaultCameraExt in default_camera_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(origin=origin, target=target) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + origin=None, # type: ignore[arg-type] + target=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> DefaultCamera: + """Produce an empty DefaultCamera, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + origin: blueprint_components.CameraOriginBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.CameraOriginBatch._optional, # type: ignore[misc] + ) + # Origin of the camera view. + # + # (Docstring intentionally commented out to hide this field from the docs) + + target: blueprint_components.CameraTargetBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.CameraTargetBatch._optional, # type: ignore[misc] + ) + # Target of the camera view. + # + # (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/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index d169ad0ec28c..94da8e650daf 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -7,6 +7,8 @@ apply_latest_at.py linguist-generated=true auto_layout.py linguist-generated=true auto_space_views.py linguist-generated=true background_kind.py linguist-generated=true +camera_origin.py linguist-generated=true +camera_target.py linguist-generated=true column_share.py linguist-generated=true component_column_selector.py linguist-generated=true container_kind.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index 1f82d7bb448a..2e43c3202ebd 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -13,6 +13,8 @@ BackgroundKindLike, BackgroundKindType, ) +from .camera_origin import CameraOrigin, CameraOriginBatch, CameraOriginType +from .camera_target import CameraTarget, CameraTargetBatch, CameraTargetType from .column_share import ColumnShare, ColumnShareBatch, ColumnShareType from .component_column_selector import ( ComponentColumnSelector, @@ -79,6 +81,12 @@ "BackgroundKindBatch", "BackgroundKindLike", "BackgroundKindType", + "CameraOrigin", + "CameraOriginBatch", + "CameraOriginType", + "CameraTarget", + "CameraTargetBatch", + "CameraTargetType", "ColumnShare", "ColumnShareBatch", "ColumnShareType", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/camera_origin.py b/rerun_py/rerun_sdk/rerun/blueprint/components/camera_origin.py new file mode 100644 index 000000000000..73c6fe4294af --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/camera_origin.py @@ -0,0 +1,36 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs". + +# You can extend this class by creating a "CameraOriginExt" class in "camera_origin_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentMixin, +) + +__all__ = ["CameraOrigin", "CameraOriginBatch", "CameraOriginType"] + + +class CameraOrigin(datatypes.Vec3D, ComponentMixin): + """**Component**: Origin of a camera.""" + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of CameraOriginExt in camera_origin_ext.py + + # Note: there are no fields here because CameraOrigin delegates to datatypes.Vec3D + pass + + +class CameraOriginType(datatypes.Vec3DType): + _TYPE_NAME: str = "rerun.blueprint.components.CameraOrigin" + + +class CameraOriginBatch(datatypes.Vec3DBatch, ComponentBatchMixin): + _ARROW_TYPE = CameraOriginType() + + +# This is patched in late to avoid circular dependencies. +CameraOrigin._BATCH_TYPE = CameraOriginBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/camera_target.py b/rerun_py/rerun_sdk/rerun/blueprint/components/camera_target.py new file mode 100644 index 000000000000..f2817ab50291 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/camera_target.py @@ -0,0 +1,36 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/camera_views.fbs". + +# You can extend this class by creating a "CameraTargetExt" class in "camera_target_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentMixin, +) + +__all__ = ["CameraTarget", "CameraTargetBatch", "CameraTargetType"] + + +class CameraTarget(datatypes.Vec3D, ComponentMixin): + """**Component**: Target of a camera.""" + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of CameraTargetExt in camera_target_ext.py + + # Note: there are no fields here because CameraTarget delegates to datatypes.Vec3D + pass + + +class CameraTargetType(datatypes.Vec3DType): + _TYPE_NAME: str = "rerun.blueprint.components.CameraTarget" + + +class CameraTargetBatch(datatypes.Vec3DBatch, ComponentBatchMixin): + _ARROW_TYPE = CameraTargetType() + + +# This is patched in late to avoid circular dependencies. +CameraTarget._BATCH_TYPE = CameraTargetBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py index f2684b5493d1..cb022d6172d4 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py @@ -80,6 +80,7 @@ def __init__( | datatypes.VisibleTimeRangeLike | Sequence[datatypes.VisibleTimeRangeLike] | None = None, + default_camera: blueprint_archetypes.DefaultCamera | None = None, ) -> None: """ Construct a blueprint for a new Spatial3DView view. @@ -117,6 +118,8 @@ def __init__( If not specified, the default is to show the latest state of each component. If a timeline is specified more than once, the first entry will be used. + default_camera: + Configures the default camera position of the 3D view. """ @@ -131,6 +134,11 @@ def __init__( time_ranges = blueprint_archetypes.VisibleTimeRanges(time_ranges) properties["VisibleTimeRanges"] = time_ranges + if default_camera is not None: + if not isinstance(default_camera, blueprint_archetypes.DefaultCamera): + default_camera = blueprint_archetypes.DefaultCamera(default_camera) + properties["DefaultCamera"] = default_camera + super().__init__( class_identifier="3D", origin=origin,