From 1a7951037691f479d5a27b7fa0516a76f7f67f24 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 18 Mar 2024 11:50:47 +0100 Subject: [PATCH] Visible Range as a component override / fix non-inheriting visual range regression (#5538) ### What * next step on #5463 Fixes the "Visual Range does not inherit" regression we got when removing groups. Does this by moving the visual time range out of `EntityProperties`. I kept all the previous data structures and convert from and to avoid even deeper changes than already necessary. This PR explicitly aims at getting 0.14 time range behavior back, the ui is expected to behave exactly as it did before. ![image](https://github.com/rerun-io/rerun/assets/1220815/1ac1223c-3bc4-44d9-bf08-1ab2cd394fbe) (much same) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5538/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5538/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5538/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5538) - [Docs preview](https://rerun.io/preview/477bfed3dd24a6cf61a5867e309ed41d9ea7eab8/docs) - [Examples preview](https://rerun.io/preview/477bfed3dd24a6cf61a5867e309ed41d9ea7eab8/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_entity_db/src/entity_properties.rs | 8 +- .../re_log_types/src/time_point/time_int.rs | 7 + crates/re_query/src/util.rs | 17 - crates/re_space_view/src/lib.rs | 5 + crates/re_space_view/src/space_view.rs | 178 +++------ crates/re_space_view/src/visual_time_range.rs | 114 ++++++ .../src/visualizers/entity_iterator.rs | 13 +- .../src/legacy_visualizer_system.rs | 1 + .../src/line_visualizer_system.rs | 1 + .../src/point_visualizer_system.rs | 1 + crates/re_space_view_time_series/src/util.rs | 32 +- .../re_types/definitions/rerun/blueprint.fbs | 3 + .../components/visible_time_range.fbs | 20 ++ .../datatypes/visible_time_range.fbs | 58 +++ .../re_types/definitions/rerun/datatypes.fbs | 5 +- .../definitions/rerun/datatypes/time_int.fbs | 19 + .../src/blueprint/components/.gitattributes | 1 + .../re_types/src/blueprint/components/mod.rs | 3 + .../components/visible_time_range.rs | 153 ++++++++ .../components/visible_time_range_ext.rs | 6 + .../src/blueprint/datatypes/.gitattributes | 4 +- .../re_types/src/blueprint/datatypes/mod.rs | 10 +- .../blueprint/datatypes/visible_time_range.rs | 340 ++++++++++++++++++ ...gend.rs => visible_time_range_boundary.rs} | 194 +++++----- .../visible_time_range_boundary_ext.rs | 47 +++ .../visible_time_range_boundary_kind.rs | 166 +++++++++ .../datatypes/visible_time_range_ext.rs | 17 + .../src/codegen/python/mod.rs | 2 +- .../src/datatypes/.gitattributes | 1 + crates/re_types_core/src/datatypes/mod.rs | 3 + .../re_types_core/src/datatypes/time_int.rs | 131 +++++++ .../src/datatypes/time_int_ext.rs | 6 + .../src/blueprint/validation_gen/mod.rs | 2 + crates/re_viewer/src/ui/selection_panel.rs | 51 +-- crates/re_viewer/src/ui/visible_history.rs | 155 ++++---- .../src/space_view/view_query.rs | 52 ++- docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../reference/types/datatypes/time_int.md | 16 + rerun_cpp/src/rerun/blueprint/.gitattributes | 1 + rerun_cpp/src/rerun/blueprint/components.hpp | 1 + .../rerun/blueprint/components/.gitattributes | 1 + .../components/visible_time_range.hpp | 60 ++++ rerun_cpp/src/rerun/blueprint/datatypes.hpp | 7 + .../rerun/blueprint/datatypes/.gitattributes | 8 +- .../src/rerun/blueprint/datatypes/legend.cpp | 78 ---- .../datatypes/visible_time_range.cpp | 124 +++++++ .../datatypes/visible_time_range.hpp | 61 ++++ .../datatypes/visible_time_range_boundary.cpp | 91 +++++ ...nd.hpp => visible_time_range_boundary.hpp} | 45 ++- .../visible_time_range_boundary_kind.cpp | 67 ++++ .../visible_time_range_boundary_kind.hpp | 57 +++ rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + rerun_cpp/src/rerun/datatypes/time_int.cpp | 57 +++ rerun_cpp/src/rerun/datatypes/time_int.hpp | 61 ++++ .../rerun/blueprint/components/.gitattributes | 1 + .../rerun/blueprint/components/__init__.py | 4 + .../components/visible_time_range.py | 28 ++ .../rerun/blueprint/datatypes/.gitattributes | 4 +- .../rerun/blueprint/datatypes/__init__.py | 42 ++- .../rerun/blueprint/datatypes/legend.py | 92 ----- .../blueprint/datatypes/visible_time_range.py | 194 ++++++++++ .../datatypes/visible_time_range_boundary.py | 104 ++++++ .../visible_time_range_boundary_kind.py | 105 ++++++ .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + .../rerun_sdk/rerun/datatypes/time_int.py | 59 +++ 68 files changed, 2616 insertions(+), 590 deletions(-) create mode 100644 crates/re_space_view/src/visual_time_range.rs create mode 100644 crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs create mode 100644 crates/re_types/definitions/rerun/datatypes/time_int.fbs create mode 100644 crates/re_types/src/blueprint/components/visible_time_range.rs create mode 100644 crates/re_types/src/blueprint/components/visible_time_range_ext.rs create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range.rs rename crates/re_types/src/blueprint/datatypes/{legend.rs => visible_time_range_boundary.rs} (53%) create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs create mode 100644 crates/re_types_core/src/datatypes/time_int.rs create mode 100644 crates/re_types_core/src/datatypes/time_int_ext.rs create mode 100644 docs/content/reference/types/datatypes/time_int.md create mode 100644 rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes.hpp delete mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp rename rerun_cpp/src/rerun/blueprint/datatypes/{legend.hpp => visible_time_range_boundary.hpp} (55%) create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp create mode 100644 rerun_cpp/src/rerun/datatypes/time_int.cpp create mode 100644 rerun_cpp/src/rerun/datatypes/time_int.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/time_int.py diff --git a/crates/re_entity_db/src/entity_properties.rs b/crates/re_entity_db/src/entity_properties.rs index 02f6e29325a1..fb50dc0d39bc 100644 --- a/crates/re_entity_db/src/entity_properties.rs +++ b/crates/re_entity_db/src/entity_properties.rs @@ -94,7 +94,6 @@ impl FromIterator<(EntityPath, EntityProperties)> for EntityPropertyMap { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct EntityProperties { - pub visible_history: re_query::ExtraQueryHistory, pub interactive: bool, /// What kind of color mapping should be applied (none, map, texture, transfer..)? @@ -143,7 +142,6 @@ pub struct EntityProperties { impl Default for EntityProperties { fn default() -> Self { Self { - visible_history: re_query::ExtraQueryHistory::default(), interactive: true, color_mapper: EditableAutoValue::default(), pinhole_image_plane_distance: EditableAutoValue::Auto(1.0), @@ -164,7 +162,6 @@ impl EntityProperties { /// Multiply/and these together. pub fn with_child(&self, child: &Self) -> Self { Self { - visible_history: self.visible_history.with_child(&child.visible_history), interactive: self.interactive && child.interactive, color_mapper: self.color_mapper.or(&child.color_mapper).clone(), @@ -208,7 +205,6 @@ impl EntityProperties { /// loaded from the Blueprint store where the Auto values are not up-to-date. pub fn merge_with(&self, other: &Self) -> Self { Self { - visible_history: self.visible_history.with_child(&other.visible_history), interactive: other.interactive, color_mapper: other.color_mapper.or(&self.color_mapper).clone(), @@ -246,7 +242,6 @@ impl EntityProperties { /// Determine whether this `EntityProperty` has user-edits relative to another `EntityProperty` pub fn has_edits(&self, other: &Self) -> bool { let Self { - visible_history, interactive, color_mapper, pinhole_image_plane_distance, @@ -260,8 +255,7 @@ impl EntityProperties { time_series_aggregator, } = self; - visible_history != &other.visible_history - || interactive != &other.interactive + interactive != &other.interactive || color_mapper.has_edits(&other.color_mapper) || pinhole_image_plane_distance.has_edits(&other.pinhole_image_plane_distance) || backproject_depth.has_edits(&other.backproject_depth) diff --git a/crates/re_log_types/src/time_point/time_int.rs b/crates/re_log_types/src/time_point/time_int.rs index fa633336323a..de13e0d624df 100644 --- a/crates/re_log_types/src/time_point/time_int.rs +++ b/crates/re_log_types/src/time_point/time_int.rs @@ -113,6 +113,13 @@ impl From for Duration { } } +impl From for re_types_core::datatypes::TimeInt { + #[inline] + fn from(int: TimeInt) -> Self { + Self(int.as_i64()) + } +} + impl std::ops::Neg for TimeInt { type Output = Self; diff --git a/crates/re_query/src/util.rs b/crates/re_query/src/util.rs index d1c72298bdf9..11cfe034e48f 100644 --- a/crates/re_query/src/util.rs +++ b/crates/re_query/src/util.rs @@ -11,7 +11,6 @@ use crate::{query_archetype, range::range_archetype, ArchetypeView}; /// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], /// the value are either nanos or frames, depending on the type of timeline. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum VisibleHistoryBoundary { /// Boundary is a value relative to the time cursor RelativeToTimeCursor(i64), @@ -36,7 +35,6 @@ impl Default for VisibleHistoryBoundary { /// Visible history bounds. #[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct VisibleHistory { /// Low time boundary. pub from: VisibleHistoryBoundary, @@ -99,8 +97,6 @@ impl VisibleHistory { /// When showing an entity in the history view, add this much history to it. #[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(default))] pub struct ExtraQueryHistory { /// Is the feature enabled? pub enabled: bool, @@ -112,19 +108,6 @@ pub struct ExtraQueryHistory { pub sequences: VisibleHistory, } -impl ExtraQueryHistory { - /// Multiply/and these together. - pub fn with_child(&self, child: &Self) -> Self { - if child.enabled { - *child - } else if self.enabled { - *self - } else { - Self::default() - } - } -} - // --- pub fn query_archetype_with_history<'a, A: Archetype + 'a, const N: usize>( diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index dea050e7ca05..fc879706ef7d 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -9,6 +9,7 @@ mod screenshot; mod space_view; mod space_view_contents; mod sub_archetypes; // TODO(andreas): better name before `sub_archetype` sticks around? +mod visual_time_range; mod visualizable; pub use data_query::{DataQuery, EntityOverrideContext, PropertyResolver}; @@ -20,6 +21,10 @@ pub use sub_archetypes::{ entity_path_for_space_view_sub_archetype, query_space_view_sub_archetype, query_space_view_sub_archetype_or_default, }; +pub use visual_time_range::{ + default_time_range, query_visual_history, time_range_boundary_to_visible_history_boundary, + visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, +}; pub use visualizable::determine_visualizable_entities; // ----------- diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 02804b85b60b..4b8dc2214af7 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,9 +1,9 @@ use itertools::{FoldWhile, Itertools}; -use re_data_store::LatestAtQuery; -use re_entity_db::{EntityDb, EntityPath, EntityProperties, VisibleHistory}; -use re_entity_db::{EntityPropertiesComponent, EntityPropertyMap}; +use nohash_hasher::IntMap; use crate::SpaceViewContents; +use re_data_store::LatestAtQuery; +use re_entity_db::{EntityDb, EntityPath, EntityPropertiesComponent, EntityPropertyMap}; use re_log_types::{DataRow, EntityPathSubs, RowId}; use re_query::query_archetype; use re_types::blueprint::archetypes as blueprint_archetypes; @@ -14,9 +14,9 @@ use re_types::{ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ - DataResult, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, - SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, + DataResult, OverridePath, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, + SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, }; // ---------------------------------------------------------------------------- @@ -416,46 +416,56 @@ impl SpaceViewBlueprint { } pub fn root_data_result(&self, ctx: &StoreContext<'_>, query: &LatestAtQuery) -> DataResult { - let entity_path = self.entity_path(); - - let is_time_series = self.class_identifier == "Time Series"; + let base_override_root = self.entity_path(); + let individual_override_path = + base_override_root.join(&DataResult::INDIVIDUAL_OVERRIDES_PREFIX.into()); + let recursive_override_path = + base_override_root.join(&DataResult::RECURSIVE_OVERRIDES_PREFIX.into()); - let mut individual_properties = ctx + let individual_properties = ctx .blueprint .store() - .query_latest_component_quiet::(&self.entity_path(), query) + .query_latest_component_quiet::( + &individual_override_path, + query, + ) .map(|result| result.value.0); + let accumulated_properties = individual_properties.clone().unwrap_or_default(); - // TODO(#4194): this should come from delegation to the space-view-class - if individual_properties.is_none() && is_time_series { - let mut time_series_defaults = EntityProperties::default(); - time_series_defaults.visible_history.nanos = VisibleHistory::ALL; - time_series_defaults.visible_history.sequences = VisibleHistory::ALL; - individual_properties = Some(time_series_defaults); - } - - let mut accumulated_properties = individual_properties.clone().unwrap_or_default(); - - if is_time_series { - // TODO(#4194): enabled == false means use defaults - if !accumulated_properties.visible_history.enabled { - accumulated_properties.visible_history.enabled = true; - accumulated_properties.visible_history.nanos = VisibleHistory::ALL; - accumulated_properties.visible_history.sequences = VisibleHistory::ALL; + // Gather recursive component overrides. + // Ignore individual overrides on SpaceView root. + let mut recursive_component_overrides = IntMap::default(); + if let Some(recursive_override_subtree) = + ctx.blueprint.tree().subtree(&recursive_override_path) + { + for component in recursive_override_subtree.entity.components.keys() { + if let Some(component_data) = ctx + .blueprint + .store() + .latest_at(query, &recursive_override_path, *component, &[*component]) + .and_then(|(_, _, cells)| cells[0].clone()) + { + if !component_data.is_empty() { + recursive_component_overrides.insert( + *component, + OverridePath::blueprint_path(recursive_override_path.clone()), + ); + } + } } } DataResult { - entity_path: entity_path.clone(), + entity_path: base_override_root, visualizers: Default::default(), tree_prefix_only: false, property_overrides: Some(PropertyOverrides { accumulated_properties, individual_properties, recursive_properties: Default::default(), - resolved_component_overrides: Default::default(), - recursive_override_path: entity_path.clone(), - individual_override_path: entity_path, + resolved_component_overrides: recursive_component_overrides, + recursive_override_path, + individual_override_path, }), } } @@ -464,7 +474,7 @@ impl SpaceViewBlueprint { #[cfg(test)] mod tests { use crate::data_query::{DataQuery, PropertyResolver}; - use re_entity_db::EntityDb; + use re_entity_db::{EntityDb, EntityProperties, EntityPropertiesComponent}; use re_log_types::{ example_components::{MyColor, MyLabel, MyPoint}, DataCell, DataRow, RowId, StoreId, StoreKind, TimePoint, @@ -673,110 +683,6 @@ mod tests { assert!(!result.accumulated_properties().interactive); } } - - // Override interactive range on root - { - let root = space_view.root_data_result( - &StoreContext { - app_id: re_log_types::ApplicationId::unknown(), - blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], - }, - &blueprint_query, - ); - let mut overrides = root.individual_properties().cloned().unwrap_or_default(); - overrides.visible_history.enabled = true; - overrides.visible_history.nanos = VisibleHistory::ALL; - - save_override( - overrides, - root.recursive_override_path().unwrap(), - &mut blueprint, - ); - } - - // Everyone has interactive history - { - let ctx = StoreContext { - app_id: re_log_types::ApplicationId::unknown(), - blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], - }; - let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); - - let parent = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent")) - .unwrap(); - let child1 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child1")) - .unwrap(); - let child2 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child2")) - .unwrap(); - - for result in [parent, child1, child2] { - assert!(result.accumulated_properties().visible_history.enabled); - assert_eq!( - result.accumulated_properties().visible_history.nanos, - VisibleHistory::ALL - ); - } - - let mut overrides = child2.individual_properties().cloned().unwrap_or_default(); - overrides.visible_history.enabled = true; - - save_override( - overrides, - child2.individual_override_path().unwrap(), - &mut blueprint, - ); - } - - // Child2 has its own interactive history - { - let ctx = StoreContext { - app_id: re_log_types::ApplicationId::unknown(), - blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], - }; - - let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); - - let parent = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent")) - .unwrap(); - let child1 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child1")) - .unwrap(); - let child2 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child2")) - .unwrap(); - - for result in [parent, child1] { - assert!(result.accumulated_properties().visible_history.enabled); - assert_eq!( - result.accumulated_properties().visible_history.nanos, - VisibleHistory::ALL - ); - } - - assert!(child2.accumulated_properties().visible_history.enabled); - assert_eq!( - child2.accumulated_properties().visible_history.nanos, - VisibleHistory::OFF - ); - } } #[test] diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs new file mode 100644 index 000000000000..b07261f7b4f9 --- /dev/null +++ b/crates/re_space_view/src/visual_time_range.rs @@ -0,0 +1,114 @@ +//! For the most part this module bridges older visual history types to the newer +//! visual range types that are defined in the `re_types` crate. +//! +//! Historically there was a special `EntityProperty` bag that was used to store the visual history. +//! Now, visual history makes use of the component override system (components stored at special paths in the blueprint store). +//! +//! The intent is to eventually remove the old types, but this bridge here is there in order +//! to reduce the amount of changes in code that is likely to be refactored soon anyways. + +use re_log_types::TimeRange; +use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_types::blueprint::{ + components::VisibleTimeRange, + datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, +}; +use re_viewer_context::{SpaceViewClassIdentifier, ViewerContext}; + +pub fn time_range_boundary_to_visible_history_boundary( + boundary: &VisibleTimeRangeBoundary, +) -> VisibleHistoryBoundary { + match boundary.kind { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { + VisibleHistoryBoundary::RelativeToTimeCursor(boundary.time.0) + } + VisibleTimeRangeBoundaryKind::Absolute => VisibleHistoryBoundary::Absolute(boundary.time.0), + VisibleTimeRangeBoundaryKind::Infinite => VisibleHistoryBoundary::Infinite, + } +} + +pub fn visible_history_boundary_to_time_range_boundary( + boundary: &VisibleHistoryBoundary, +) -> VisibleTimeRangeBoundary { + match boundary { + VisibleHistoryBoundary::RelativeToTimeCursor(v) => VisibleTimeRangeBoundary { + kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, + time: (*v).into(), + }, + VisibleHistoryBoundary::Absolute(v) => VisibleTimeRangeBoundary { + kind: VisibleTimeRangeBoundaryKind::Absolute, + time: (*v).into(), + }, + VisibleHistoryBoundary::Infinite => VisibleTimeRangeBoundary { + kind: VisibleTimeRangeBoundaryKind::Infinite, + time: 0.into(), + }, + } +} + +pub fn visible_time_range_to_time_range( + range: &VisibleTimeRange, + time_type: re_log_types::TimeType, + cursor: re_log_types::TimeInt, +) -> re_log_types::TimeRange { + let cursor = cursor.as_i64().into(); + + let mut min = match time_type { + re_log_types::TimeType::Sequence => range.0.from_sequence.start_boundary_time(cursor).0, + re_log_types::TimeType::Time => range.0.from_time.start_boundary_time(cursor).0, + }; + let mut max = match time_type { + re_log_types::TimeType::Sequence => range.0.to_sequence.end_boundary_time(cursor).0, + re_log_types::TimeType::Time => range.0.to_time.end_boundary_time(cursor).0, + }; + + if min > max { + std::mem::swap(&mut min, &mut max); + } + + TimeRange::new(min.into(), max.into()) +} + +pub fn query_visual_history( + ctx: &ViewerContext<'_>, + data_result: &re_viewer_context::DataResult, +) -> ExtraQueryHistory { + let visual_time_range_component = + data_result.lookup_override::(ctx); + if let Some(visual_time_range_component) = visual_time_range_component { + ExtraQueryHistory { + enabled: true, + nanos: VisibleHistory { + from: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.from_time, + ), + to: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.to_time, + ), + }, + sequences: VisibleHistory { + from: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.from_sequence, + ), + to: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.to_sequence, + ), + }, + } + } else { + ExtraQueryHistory { + enabled: false, + nanos: VisibleHistory::default(), + sequences: VisibleHistory::default(), + } + } +} + +// TODO(#4194): this should come from delegation to the space-view-class +pub fn default_time_range(class_identifier: SpaceViewClassIdentifier) -> VisibleTimeRange { + if class_identifier == "Time Series" { + VisibleTimeRange::EVERYTHING.clone() + } else { + VisibleTimeRange::EMPTY.clone() + } +} diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 986c40c7db18..8b37590166dc 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,6 +2,7 @@ use re_entity_db::EntityProperties; use re_log_types::{EntityPath, RowId, TimeInt}; use re_query::{query_archetype_with_history, ArchetypeView, QueryError}; use re_renderer::DepthOffset; +use re_space_view::query_visual_history; use re_types::{components::InstanceKey, Archetype, Component}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewClass, SpaceViewSystemExecutionError, ViewContextCollection, @@ -71,11 +72,13 @@ where space_view_class_identifier: view_ctx.space_view_class_identifier(), }; + let extra_history = query_visual_history(ctx, data_result); + match query_archetype_with_history::( ctx.entity_db.store(), &query.timeline, &query.latest_at, - &data_result.accumulated_properties().visible_history, + &extra_history, &data_result.entity_path, ) .and_then(|arch_views| { @@ -179,11 +182,13 @@ macro_rules! impl_process_archetype { space_view_class_identifier: view_ctx.space_view_class_identifier(), }; + let extra_history = query_visual_history(ctx, data_result); + match ctx.entity_db.query_caches().[]::( ctx.entity_db.store(), &query.timeline, &query.latest_at, - &data_result.accumulated_properties().visible_history, + &extra_history, &data_result.entity_path, |(t, keys, $($pov,)+ $($comp,)*)| { counter @@ -257,11 +262,13 @@ pub fn count_instances_in_archetype_views< let mut num_instances = 0; for data_result in query.iter_visible_data_results(ctx, System::identifier()) { + let extra_history = query_visual_history(ctx, data_result); + match query_archetype_with_history::( ctx.entity_db.store(), &query.timeline, &query.latest_at, - &data_result.accumulated_properties().visible_history, + &extra_history, &data_result.entity_path, ) .map(|arch_views| { diff --git a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs index 6d71a991ed03..bd9753f1d33c 100644 --- a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs @@ -140,6 +140,7 @@ impl LegacyTimeSeriesSystem { let mut points = Vec::new(); let time_range = determine_time_range( + ctx, query, data_result, plot_bounds, diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 5672f84770f5..4668bb409c53 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -184,6 +184,7 @@ fn load_series( let mut points = Vec::new(); let time_range = determine_time_range( + ctx, query, data_result, plot_bounds, diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index f0b612798773..58a7d5423639 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -138,6 +138,7 @@ impl SeriesPointSystem { let mut points = Vec::new(); let time_range = determine_time_range( + ctx, query, data_result, plot_bounds, diff --git a/crates/re_space_view_time_series/src/util.rs b/crates/re_space_view_time_series/src/util.rs index d58faaeb51ee..b703b7d20ae7 100644 --- a/crates/re_space_view_time_series/src/util.rs +++ b/crates/re_space_view_time_series/src/util.rs @@ -1,10 +1,13 @@ use re_log_types::{EntityPath, TimeInt, TimeRange}; +use re_space_view::{default_time_range, visible_time_range_to_time_range}; use re_types::datatypes::Utf8; -use re_viewer_context::{external::re_entity_db::TimeSeriesAggregator, ViewQuery, ViewerContext}; +use re_viewer_context::{ + external::re_entity_db::TimeSeriesAggregator, SpaceViewClass, ViewQuery, ViewerContext, +}; use crate::{ aggregation::{AverageAggregator, MinMaxAggregator}, - PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs, + PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs, TimeSeriesSpaceView, }; /// Find the plot bounds and the per-ui-point delta from egui. @@ -28,26 +31,21 @@ pub fn determine_plot_bounds_and_time_per_pixel( } pub fn determine_time_range( + ctx: &ViewerContext<'_>, query: &ViewQuery<'_>, data_result: &re_viewer_context::DataResult, plot_bounds: Option, enable_query_clamping: bool, ) -> TimeRange { - let visible_history = match query.timeline.typ() { - re_log_types::TimeType::Time => data_result.accumulated_properties().visible_history.nanos, - re_log_types::TimeType::Sequence => { - data_result - .accumulated_properties() - .visible_history - .sequences - } - }; - - let mut time_range = if data_result.accumulated_properties().visible_history.enabled { - visible_history.time_range(query.latest_at) - } else { - TimeRange::new(TimeInt::MIN, TimeInt::MAX) - }; + let visible_time_range_override = data_result + .lookup_override::(ctx) + .unwrap_or(default_time_range(TimeSeriesSpaceView::identifier())); + + let mut time_range = visible_time_range_to_time_range( + &visible_time_range_override, + query.timeline.typ(), + query.latest_at, + ); // TODO(cmc): We would love to reduce the query to match the actual plot bounds, but because // the plot widget handles zoom after we provide it with data for the current frame, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 1d629523d648..c7056192eca7 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -1,3 +1,5 @@ +include "./blueprint/datatypes/visible_time_range.fbs"; + include "./blueprint/components/active_tab.fbs"; include "./blueprint/components/auto_layout.fbs"; include "./blueprint/components/auto_space_views.fbs"; @@ -18,6 +20,7 @@ include "./blueprint/components/space_view_class.fbs"; include "./blueprint/components/space_view_maximized.fbs"; include "./blueprint/components/space_view_origin.fbs"; include "./blueprint/components/viewer_recommendation_hash.fbs"; +include "./blueprint/components/visible_time_range.fbs"; include "./blueprint/components/visible.fbs"; include "./blueprint/archetypes/background_3d.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs new file mode 100644 index 000000000000..7e71f15c0d08 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs @@ -0,0 +1,20 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.components; + +// --- + +/// The range of values that will be included in a Space View query. +table VisibleTimeRange ( + "attr.arrow.transparent", + "attr.rerun.scope": "blueprint", + "attr.rust.repr": "transparent", + "attr.rust.derive": "PartialEq, Eq" +) { + value: rerun.blueprint.datatypes.VisibleTimeRange (order: 100); +} diff --git a/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs new file mode 100644 index 000000000000..584a6f42366e --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs @@ -0,0 +1,58 @@ + +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/attributes.fbs"; + +include "../../datatypes/time_int.fbs"; + +namespace rerun.blueprint.datatypes; + +/// Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. +enum VisibleTimeRangeBoundaryKind: byte ( + "attr.rerun.scope": "blueprint", + "attr.docs.unreleased" +) { + /// Boundary is a value relative to the time cursor. + RelativeToTimeCursor, + + /// Boundary is an absolute value. + Absolute, + + /// The boundary extends to infinity. + Infinite, +} + +/// Type of boundary for visible history. +struct VisibleTimeRangeBoundary ( + "attr.rerun.scope": "blueprint", + "attr.docs.unreleased" +) { + /// Type of the boundary. + kind: rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind (order: 100); + + /// Value of the boundary (ignored for `Infinite` type). + time: rerun.datatypes.TimeInt (order: 200); +} + +/// Visible time range bounds. +struct VisibleTimeRange ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "PartialEq, Eq", + "attr.docs.unreleased" +) { + // TODO(andreas): Split this up into two separate components. + + /// Low time boundary for sequence timeline. + from_sequence: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 100); + + /// High time boundary for sequence timeline. + to_sequence: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 200); + + /// Low time boundary for time timeline. + from_time: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 300); + + /// High time boundary for time timeline. + to_time: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 400); +} diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index 3b8adb39a597..74d5fc31fea0 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -1,8 +1,8 @@ include "./datatypes/angle.fbs"; include "./datatypes/annotation_info.fbs"; include "./datatypes/bool.fbs"; -include "./datatypes/class_description.fbs"; include "./datatypes/class_description_map_elem.fbs"; +include "./datatypes/class_description.fbs"; include "./datatypes/class_id.fbs"; include "./datatypes/entity_path.fbs"; include "./datatypes/float32.fbs"; @@ -14,12 +14,13 @@ include "./datatypes/material.fbs"; include "./datatypes/mesh_properties.fbs"; include "./datatypes/quaternion.fbs"; include "./datatypes/rgba32.fbs"; -include "./datatypes/rotation3d.fbs"; include "./datatypes/rotation_axis_angle.fbs"; +include "./datatypes/rotation3d.fbs"; include "./datatypes/scale3d.fbs"; include "./datatypes/tensor_buffer.fbs"; include "./datatypes/tensor_data.fbs"; include "./datatypes/tensor_dimension.fbs"; +include "./datatypes/time_int.fbs"; include "./datatypes/transform3d.fbs"; include "./datatypes/translation_and_mat3x3.fbs"; include "./datatypes/translation_rotation_scale3d.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/time_int.fbs b/crates/re_types/definitions/rerun/datatypes/time_int.fbs new file mode 100644 index 000000000000..dfecb256d70b --- /dev/null +++ b/crates/re_types/definitions/rerun/datatypes/time_int.fbs @@ -0,0 +1,19 @@ + +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/attributes.fbs"; + +namespace rerun.datatypes; + +/// A 64-bit number describing either nanoseconds OR sequence numbers. +struct TimeInt ( + "attr.docs.unreleased", + "attr.arrow.transparent", + "attr.rust.derive": "Copy, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.tuple_struct", + "attr.rust.override_crate": "re_types_core" +) { + value: long (order: 100); +} diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index 9f8d0a8dd3bf..02afa95257cd 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -15,3 +15,4 @@ space_view_class.rs linguist-generated=true space_view_origin.rs linguist-generated=true viewer_recommendation_hash.rs linguist-generated=true visible.rs linguist-generated=true +visible_time_range.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index 0b873668d40b..d3670e91167c 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -15,6 +15,8 @@ mod space_view_origin; mod viewer_recommendation_hash; mod visible; mod visible_ext; +mod visible_time_range; +mod visible_time_range_ext; pub use self::active_tab::ActiveTab; pub use self::background3d_kind::Background3DKind; @@ -29,3 +31,4 @@ pub use self::space_view_class::SpaceViewClass; pub use self::space_view_origin::SpaceViewOrigin; pub use self::viewer_recommendation_hash::ViewerRecommendationHash; pub use self::visible::Visible; +pub use self::visible_time_range::VisibleTimeRange; diff --git a/crates/re_types/src/blueprint/components/visible_time_range.rs b/crates/re_types/src/blueprint/components/visible_time_range.rs new file mode 100644 index 000000000000..053681357c0c --- /dev/null +++ b/crates/re_types/src/blueprint/components/visible_time_range.rs @@ -0,0 +1,153 @@ +// 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/components/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![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**: The range of values that will be included in a Space View query. +#[derive(Clone, Debug, PartialEq, Eq)] +#[repr(transparent)] +pub struct VisibleTimeRange(pub crate::blueprint::datatypes::VisibleTimeRange); + +impl ::re_types_core::SizeBytes for VisibleTimeRange { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for VisibleTimeRange { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for VisibleTimeRange { + #[inline] + fn borrow(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + &self.0 + } +} + +impl std::ops::Deref for VisibleTimeRange { + type Target = crate::blueprint::datatypes::VisibleTimeRange; + + #[inline] + fn deref(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + &self.0 + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRange); + +impl ::re_types_core::Loggable for VisibleTimeRange { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.VisibleTimeRange".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "from_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "to_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "from_time", + ::arrow_datatype(), + false, + ), + Field::new( + "to_time", + ::arrow_datatype(), + 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::blueprint::datatypes::VisibleTimeRange::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::blueprint::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) + .with_context("rerun.blueprint.components.VisibleTimeRange#value")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.blueprint.components.VisibleTimeRange#value") + .with_context("rerun.blueprint.components.VisibleTimeRange")?, + ) + } +} diff --git a/crates/re_types/src/blueprint/components/visible_time_range_ext.rs b/crates/re_types/src/blueprint/components/visible_time_range_ext.rs new file mode 100644 index 000000000000..051f3d145a13 --- /dev/null +++ b/crates/re_types/src/blueprint/components/visible_time_range_ext.rs @@ -0,0 +1,6 @@ +use super::VisibleTimeRange; + +impl VisibleTimeRange { + pub const EMPTY: Self = Self(crate::blueprint::datatypes::VisibleTimeRange::EMPTY); + pub const EVERYTHING: Self = Self(crate::blueprint::datatypes::VisibleTimeRange::EVERYTHING); +} diff --git a/crates/re_types/src/blueprint/datatypes/.gitattributes b/crates/re_types/src/blueprint/datatypes/.gitattributes index f8cc2be56035..788b8f6860a3 100644 --- a/crates/re_types/src/blueprint/datatypes/.gitattributes +++ b/crates/re_types/src/blueprint/datatypes/.gitattributes @@ -1,5 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -legend.rs linguist-generated=true mod.rs linguist-generated=true +visible_time_range.rs linguist-generated=true +visible_time_range_boundary.rs linguist-generated=true +visible_time_range_boundary_kind.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/datatypes/mod.rs b/crates/re_types/src/blueprint/datatypes/mod.rs index af61829b13e1..c843412e734b 100644 --- a/crates/re_types/src/blueprint/datatypes/mod.rs +++ b/crates/re_types/src/blueprint/datatypes/mod.rs @@ -1,5 +1,11 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -mod legend; +mod visible_time_range; +mod visible_time_range_boundary; +mod visible_time_range_boundary_ext; +mod visible_time_range_boundary_kind; +mod visible_time_range_ext; -pub use self::legend::Legend; +pub use self::visible_time_range::VisibleTimeRange; +pub use self::visible_time_range_boundary::VisibleTimeRangeBoundary; +pub use self::visible_time_range_boundary_kind::VisibleTimeRangeBoundaryKind; diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range.rs new file mode 100644 index 000000000000..bc1bd84fef03 --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range.rs @@ -0,0 +1,340 @@ +// 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/datatypes/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![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**: Visible time range bounds. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct VisibleTimeRange { + /// Low time boundary for sequence timeline. + pub from_sequence: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + + /// High time boundary for sequence timeline. + pub to_sequence: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + + /// Low time boundary for time timeline. + pub from_time: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + + /// High time boundary for time timeline. + pub to_time: crate::blueprint::datatypes::VisibleTimeRangeBoundary, +} + +impl ::re_types_core::SizeBytes for VisibleTimeRange { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.from_sequence.heap_size_bytes() + + self.to_sequence.heap_size_bytes() + + self.from_time.heap_size_bytes() + + self.to_time.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + && ::is_pod() + && ::is_pod() + && ::is_pod() + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRange); + +impl ::re_types_core::Loggable for VisibleTimeRange { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.datatypes.VisibleTimeRange".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "from_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "to_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "from_time", + ::arrow_datatype(), + false, + ), + Field::new( + "to_time", + ::arrow_datatype(), + 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, from_sequence): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { from_sequence, .. } = &**datum; + from_sequence.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let from_sequence_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = from_sequence_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + from_sequence, + )? + } + }, + { + let (somes, to_sequence): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { to_sequence, .. } = &**datum; + to_sequence.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let to_sequence_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = to_sequence_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + to_sequence, + )? + } + }, + { + let (somes, from_time): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { from_time, .. } = &**datum; + from_time.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let from_time_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = from_time_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + from_time, + )? + } + }, + { + let (somes, to_time): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { to_time, .. } = &**datum; + to_time.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let to_time_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = to_time_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + to_time, + )? + } + }, + ], + 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.blueprint.datatypes.VisibleTimeRange")?; + 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 from_sequence = { + if !arrays_by_name.contains_key("from_sequence") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "from_sequence", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["from_sequence"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#from_sequence")? + .into_iter() + }; + let to_sequence = { + if !arrays_by_name.contains_key("to_sequence") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "to_sequence", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["to_sequence"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#to_sequence")? + .into_iter() + }; + let from_time = { + if !arrays_by_name.contains_key("from_time") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "from_time", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["from_time"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#from_time")? + .into_iter() + }; + let to_time = { + if !arrays_by_name.contains_key("to_time") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "to_time", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["to_time"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#to_time")? + .into_iter() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + ::itertools::izip!(from_sequence, to_sequence, from_time, to_time), + arrow_data.validity(), + ) + .map(|opt| { + opt.map(|(from_sequence, to_sequence, from_time, to_time)| { + Ok(Self { + from_sequence: from_sequence + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#from_sequence", + )?, + to_sequence: to_sequence + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#to_sequence", + )?, + from_time: from_time + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#from_time", + )?, + to_time: to_time + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#to_time", + )?, + }) + }) + .transpose() + }) + .collect::>>() + .with_context("rerun.blueprint.datatypes.VisibleTimeRange")? + } + }) + } +} diff --git a/crates/re_types/src/blueprint/datatypes/legend.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs similarity index 53% rename from crates/re_types/src/blueprint/datatypes/legend.rs rename to crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs index a75e3bc464e4..2307d5fcf906 100644 --- a/crates/re_types/src/blueprint/datatypes/legend.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs @@ -1,5 +1,5 @@ // 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/datatypes/legend.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -21,42 +21,37 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Datatype**: Configuration for the legend of a plot. -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Legend { - /// Whether or not the legend should be displayed. - pub visible: bool, +/// **Datatype**: Type of boundary for visible history. +#[derive(Clone, Debug)] +pub struct VisibleTimeRangeBoundary { + /// Type of the boundary. + pub kind: crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind, - /// Where should the legend be located. - /// - /// Allowed values: - /// - LeftTop = 1, - /// - RightTop = 2, - /// - LeftBottom = 3, - /// - RightBottom = 4 - pub location: Option, + /// Value of the boundary (ignored for `Infinite` type). + pub time: crate::datatypes::TimeInt, } -impl ::re_types_core::SizeBytes for Legend { +impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundary { #[inline] fn heap_size_bytes(&self) -> u64 { - self.visible.heap_size_bytes() + self.location.heap_size_bytes() + self.kind.heap_size_bytes() + self.time.heap_size_bytes() } #[inline] fn is_pod() -> bool { - ::is_pod() && >::is_pod() + ::is_pod() + && ::is_pod() } } -::re_types_core::macros::impl_into_cow!(Legend); +::re_types_core::macros::impl_into_cow!(VisibleTimeRangeBoundary); -impl ::re_types_core::Loggable for Legend { +impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { type Name = ::re_types_core::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.datatypes.Legend".into() + "rerun.blueprint.datatypes.VisibleTimeRangeBoundary".into() } #[allow(clippy::wildcard_imports)] @@ -64,18 +59,12 @@ impl ::re_types_core::Loggable for Legend { fn arrow_datatype() -> arrow2::datatypes::DataType { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ - Field { - name: "visible".to_owned(), - data_type: DataType::Boolean, - is_nullable: false, - metadata: [].into(), - }, - Field { - name: "location".to_owned(), - data_type: DataType::UInt8, - is_nullable: true, - metadata: [].into(), - }, + Field::new( + "kind", + ::arrow_datatype(), + false, + ), + Field::new("time", ::arrow_datatype(), false), ])) } @@ -101,55 +90,58 @@ impl ::re_types_core::Loggable for Legend { any_nones.then(|| somes.into()) }; StructArray::new( - ::arrow_datatype(), + ::arrow_datatype(), vec![ { - let (somes, visible): (Vec<_>, Vec<_>) = data + let (somes, kind): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { visible, .. } = &**datum; - visible.clone() + let Self { kind, .. } = &**datum; + kind.clone() }); (datum.is_some(), datum) }) .unzip(); - let visible_bitmap: Option = { + let kind_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; - BooleanArray::new( - DataType::Boolean, - visible.into_iter().map(|v| v.unwrap_or_default()).collect(), - visible_bitmap, - ) - .boxed() + { + _ = kind_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind::to_arrow_opt( + kind, + )? + } }, { - let (somes, location): (Vec<_>, Vec<_>) = data + let (somes, time): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { - let datum = datum - .as_ref() - .map(|datum| { - let Self { location, .. } = &**datum; - location.clone() - }) - .flatten(); + let datum = datum.as_ref().map(|datum| { + let Self { time, .. } = &**datum; + time.clone() + }); (datum.is_some(), datum) }) .unzip(); - let location_bitmap: Option = { + let time_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; PrimitiveArray::new( - DataType::UInt8, - location - .into_iter() - .map(|v| v.unwrap_or_default()) + DataType::Int64, + time.into_iter() + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::TimeInt(data0) = datum; + data0 + }) + .unwrap_or_default() + }) .collect(), - location_bitmap, + time_bitmap, ) .boxed() }, @@ -174,25 +166,11 @@ impl ::re_types_core::Loggable for Legend { .as_any() .downcast_ref::() .ok_or_else(|| { - DeserializationError::datatype_mismatch( - DataType::Struct(std::sync::Arc::new(vec![ - Field { - name: "visible".to_owned(), - data_type: DataType::Boolean, - is_nullable: false, - metadata: [].into(), - }, - Field { - name: "location".to_owned(), - data_type: DataType::UInt8, - is_nullable: true, - metadata: [].into(), - }, - ])), - arrow_data.data_type().clone(), - ) + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.Legend")?; + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary")?; if arrow_data.is_empty() { Vec::new() } else { @@ -203,66 +181,66 @@ impl ::re_types_core::Loggable for Legend { .map(|field| field.name.as_str()) .zip(arrow_data_arrays) .collect(); - let visible = { - if !arrays_by_name.contains_key("visible") { + let kind = { + if !arrays_by_name.contains_key("kind") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "visible", + "kind", )) - .with_context("rerun.blueprint.datatypes.Legend"); + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary"); } - let arrow_data = &**arrays_by_name["visible"]; - arrow_data - .as_any() - .downcast_ref::() - .ok_or_else(|| { - DeserializationError::datatype_mismatch( - DataType::Boolean, - arrow_data.data_type().clone(), - ) - }) - .with_context("rerun.blueprint.datatypes.Legend#visible")? - .into_iter() + let arrow_data = &**arrays_by_name["kind"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary#kind")? + .into_iter() }; - let location = { - if !arrays_by_name.contains_key("location") { + let time = { + if !arrays_by_name.contains_key("time") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "location", + "time", )) - .with_context("rerun.blueprint.datatypes.Legend"); + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary"); } - let arrow_data = &**arrays_by_name["location"]; + let arrow_data = &**arrays_by_name["time"]; arrow_data .as_any() - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| { - DeserializationError::datatype_mismatch( - DataType::UInt8, - arrow_data.data_type().clone(), - ) + let expected = DataType::Int64; + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.Legend#location")? + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary#time")? .into_iter() .map(|opt| opt.copied()) + .map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::TimeInt(v))) }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(visible, location), + ::itertools::izip!(kind, time), arrow_data.validity(), ) .map(|opt| { - opt.map(|(visible, location)| { + opt.map(|(kind, time)| { Ok(Self { - visible: visible + kind: kind + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRangeBoundary#kind", + )?, + time: time .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.datatypes.Legend#visible")?, - location, + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRangeBoundary#time", + )?, }) }) .transpose() }) .collect::>>() - .with_context("rerun.blueprint.datatypes.Legend")? + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary")? } }) } diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs new file mode 100644 index 000000000000..a93c32dce2be --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs @@ -0,0 +1,47 @@ +use super::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}; +use re_types_core::datatypes::TimeInt; + +impl VisibleTimeRangeBoundary { + pub const AT_CURSOR: Self = Self { + kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, + time: TimeInt(0), + }; + + pub const INFINITE: Self = Self { + kind: VisibleTimeRangeBoundaryKind::Infinite, + time: TimeInt(0), + }; + + /// Returns the time assuming this boundary is a start boundary. + pub fn start_boundary_time(&self, cursor: TimeInt) -> TimeInt { + match self.kind { + VisibleTimeRangeBoundaryKind::Absolute => self.time, + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => TimeInt(cursor.0 + self.time.0), + VisibleTimeRangeBoundaryKind::Infinite => TimeInt::MIN, + } + } + + /// Returns the correct time assuming this boundary is an end boundary. + pub fn end_boundary_time(&self, cursor: TimeInt) -> TimeInt { + match self.kind { + VisibleTimeRangeBoundaryKind::Absolute => self.time, + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => TimeInt(cursor.0 + self.time.0), + VisibleTimeRangeBoundaryKind::Infinite => TimeInt::MAX, + } + } +} + +impl PartialEq for VisibleTimeRangeBoundary { + fn eq(&self, other: &Self) -> bool { + match self.kind { + VisibleTimeRangeBoundaryKind::Absolute + | VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { + other.kind == self.kind && other.time == self.time + } + // Ignore the time value for infinite boundaries. + VisibleTimeRangeBoundaryKind::Infinite => other.kind == self.kind, + } + } +} + +impl Eq for VisibleTimeRangeBoundary {} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs new file mode 100644 index 000000000000..46b3d8f37750 --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs @@ -0,0 +1,166 @@ +// 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/datatypes/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![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**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum VisibleTimeRangeBoundaryKind { + /// Boundary is a value relative to the time cursor. + RelativeToTimeCursor = 1, + + /// Boundary is an absolute value. + Absolute = 2, + + /// The boundary extends to infinity. + Infinite = 3, +} + +impl VisibleTimeRangeBoundaryKind { + /// All the different enum variants. + pub const ALL: [Self; 3] = [Self::RelativeToTimeCursor, Self::Absolute, Self::Infinite]; +} + +impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundaryKind { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl std::fmt::Display for VisibleTimeRangeBoundaryKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::RelativeToTimeCursor => write!(f, "RelativeToTimeCursor"), + Self::Absolute => write!(f, "Absolute"), + Self::Infinite => write!(f, "Infinite"), + } + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRangeBoundaryKind); + +impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Union( + std::sync::Arc::new(vec![ + Field::new("_null_markers", DataType::Null, true), + Field::new("RelativeToTimeCursor", DataType::Null, true), + Field::new("Absolute", DataType::Null, true), + Field::new("Infinite", DataType::Null, true), + ]), + Some(std::sync::Arc::new(vec![0i32, 1i32, 2i32, 3i32])), + UnionMode::Sparse, + ) + } + + #[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 data: Vec<_> = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + datum + }) + .collect(); + let num_variants = 3usize; + let types = data + .iter() + .map(|a| match a.as_deref() { + None => 0, + Some(value) => *value as i8, + }) + .collect(); + let fields: Vec<_> = + std::iter::repeat(NullArray::new(DataType::Null, data.len()).boxed()) + .take(1 + num_variants) + .collect(); + UnionArray::new( + ::arrow_datatype(), + types, + fields, + None, + ) + .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.blueprint.datatypes.VisibleTimeRangeBoundaryKind")?; + let arrow_data_types = arrow_data.types(); + arrow_data_types + .iter() + .map(|typ| match typ { + 0 => Ok(None), + 1 => Ok(Some(VisibleTimeRangeBoundaryKind::RelativeToTimeCursor)), + 2 => Ok(Some(VisibleTimeRangeBoundaryKind::Absolute)), + 3 => Ok(Some(VisibleTimeRangeBoundaryKind::Infinite)), + _ => Err(DeserializationError::missing_union_arm( + Self::arrow_datatype(), + "", + *typ as _, + )), + }) + .collect::>>() + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind")? + }) + } +} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs new file mode 100644 index 000000000000..d558b143e343 --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs @@ -0,0 +1,17 @@ +use super::{VisibleTimeRange, VisibleTimeRangeBoundary}; + +impl VisibleTimeRange { + pub const EMPTY: Self = Self { + from_sequence: VisibleTimeRangeBoundary::AT_CURSOR, + to_sequence: VisibleTimeRangeBoundary::AT_CURSOR, + from_time: VisibleTimeRangeBoundary::AT_CURSOR, + to_time: VisibleTimeRangeBoundary::AT_CURSOR, + }; + + pub const EVERYTHING: Self = Self { + from_sequence: VisibleTimeRangeBoundary::INFINITE, + to_sequence: VisibleTimeRangeBoundary::INFINITE, + from_time: VisibleTimeRangeBoundary::INFINITE, + to_time: VisibleTimeRangeBoundary::INFINITE, + }; +} diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index 41769667124e..d9dd3d71402a 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -587,7 +587,7 @@ fn code_for_struct( if obj.is_delegating_component() { let delegate = obj.delegate_datatype(objects).unwrap(); let scope = match delegate.scope() { - Some(scope) => format!("{scope}."), + Some(scope) => format!("{scope}_"), None => String::new(), }; superclasses.push(format!( diff --git a/crates/re_types_core/src/datatypes/.gitattributes b/crates/re_types_core/src/datatypes/.gitattributes index 5d1c22973176..8d8025b30391 100644 --- a/crates/re_types_core/src/datatypes/.gitattributes +++ b/crates/re_types_core/src/datatypes/.gitattributes @@ -4,6 +4,7 @@ entity_path.rs linguist-generated=true float32.rs linguist-generated=true mod.rs linguist-generated=true +time_int.rs linguist-generated=true uint32.rs linguist-generated=true uint64.rs linguist-generated=true utf8.rs linguist-generated=true diff --git a/crates/re_types_core/src/datatypes/mod.rs b/crates/re_types_core/src/datatypes/mod.rs index dd64cf5f950c..b3afd8508146 100644 --- a/crates/re_types_core/src/datatypes/mod.rs +++ b/crates/re_types_core/src/datatypes/mod.rs @@ -2,6 +2,8 @@ mod entity_path; mod float32; +mod time_int; +mod time_int_ext; mod uint32; mod uint64; mod utf8; @@ -9,6 +11,7 @@ mod utf8_ext; pub use self::entity_path::EntityPath; pub use self::float32::Float32; +pub use self::time_int::TimeInt; pub use self::uint32::UInt32; pub use self::uint64::UInt64; pub use self::utf8::Utf8; diff --git a/crates/re_types_core/src/datatypes/time_int.rs b/crates/re_types_core/src/datatypes/time_int.rs new file mode 100644 index 000000000000..1f488806ca0d --- /dev/null +++ b/crates/re_types_core/src/datatypes/time_int.rs @@ -0,0 +1,131 @@ +// 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/time_int.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![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 crate::external::arrow2; +use crate::ComponentName; +use crate::SerializationResult; +use crate::{ComponentBatch, MaybeOwnedComponentBatch}; +use crate::{DeserializationError, DeserializationResult}; + +/// **Datatype**: A 64-bit number describing either nanoseconds OR sequence numbers. +#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct TimeInt(pub i64); + +impl crate::SizeBytes for TimeInt { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl From for TimeInt { + #[inline] + fn from(value: i64) -> Self { + Self(value) + } +} + +impl From for i64 { + #[inline] + fn from(value: TimeInt) -> Self { + value.0 + } +} + +crate::macros::impl_into_cow!(TimeInt); + +impl crate::Loggable for TimeInt { + type Name = crate::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.datatypes.TimeInt".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Int64 + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use crate::{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()) + }; + PrimitiveArray::new( + Self::arrow_datatype(), + data0.into_iter().map(|v| v.unwrap_or_default()).collect(), + data0_bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use crate::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok(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.TimeInt#value")? + .into_iter() + .map(|opt| opt.copied()) + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.datatypes.TimeInt#value") + .with_context("rerun.datatypes.TimeInt")?) + } +} diff --git a/crates/re_types_core/src/datatypes/time_int_ext.rs b/crates/re_types_core/src/datatypes/time_int_ext.rs new file mode 100644 index 000000000000..511f0efc2676 --- /dev/null +++ b/crates/re_types_core/src/datatypes/time_int_ext.rs @@ -0,0 +1,6 @@ +use super::TimeInt; + +impl TimeInt { + pub const MIN: Self = Self(i64::MIN); + pub const MAX: Self = Self(i64::MAX); +} diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index e33d2eb05e11..032557e39f0a 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -15,6 +15,7 @@ pub use re_types::blueprint::components::SpaceViewClass; pub use re_types::blueprint::components::SpaceViewOrigin; pub use re_types::blueprint::components::ViewerRecommendationHash; pub use re_types::blueprint::components::Visible; +pub use re_types::blueprint::components::VisibleTimeRange; pub use re_viewport::blueprint::components::AutoLayout; pub use re_viewport::blueprint::components::AutoSpaceViews; pub use re_viewport::blueprint::components::ContainerKind; @@ -48,4 +49,5 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) + && validate_component::(blueprint) } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 7368804694ba..9dd09ffad9e8 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -26,9 +26,9 @@ use re_viewport::{ }; use crate::ui::override_ui::override_ui; -use crate::ui::{override_ui::override_visualizer_ui, visible_history::visible_history_ui}; +use crate::ui::override_ui::override_visualizer_ui; -use super::selection_history_ui::SelectionHistoryUi; +use super::{selection_history_ui::SelectionHistoryUi, visible_history::visual_time_range_ui}; // --- @@ -837,34 +837,42 @@ fn blueprint_ui_for_space_view( ui.add_space(ui.spacing().item_spacing.y / 2.0); if let Some(space_view) = viewport.blueprint.space_view(space_view_id) { - let space_view_class = *space_view.class_identifier(); + let class_identifier = *space_view.class_identifier(); let space_view_state = viewport.state.space_view_state_mut( ctx.space_view_class_registry, space_view.id, - space_view.class_identifier(), + &class_identifier, ); // Space View don't inherit properties. let root_data_result = space_view.root_data_result(ctx.store_context, ctx.blueprint_query); - let mut props = root_data_result - .individual_properties() - .cloned() - .unwrap_or_default(); + let query_result = ctx.lookup_query_result(space_view.id); + let Some(data_result) = query_result + .tree + .root_handle() + .and_then(|root| query_result.tree.lookup_result(root)) + else { + re_log::error!("Could not find root data result for Space View {space_view_id:?}"); + return; + }; - visible_history_ui( + visual_time_range_ui( ctx, ui, - &space_view_class, + &query_result.tree, + data_result, + class_identifier, true, - None, - &mut props.visible_history, - &root_data_result.accumulated_properties().visible_history, ); - let space_view_class = space_view.class(ctx.space_view_class_registry); + let mut props = root_data_result + .individual_properties() + .cloned() + .unwrap_or_default(); + let space_view_class = space_view.class(ctx.space_view_class_registry); if let Err(err) = space_view_class.selection_ui( ctx, ui, @@ -880,7 +888,7 @@ fn blueprint_ui_for_space_view( ); } - root_data_result.save_individual_override(Some(props), ctx); + root_data_result.save_individual_override_properties(ctx, Some(props)); } } @@ -915,9 +923,8 @@ fn blueprint_ui_for_data_result( &space_view_class, entity_path, &mut props, - data_result.accumulated_properties(), ); - data_result.save_individual_override(Some(props), ctx); + data_result.save_individual_override_properties(ctx, Some(props)); } } } @@ -1073,7 +1080,6 @@ fn entity_props_ui( space_view_class: &SpaceViewClassIdentifier, entity_path: &EntityPath, entity_props: &mut EntityProperties, - resolved_entity_props: &EntityProperties, ) { use re_types::blueprint::components::Visible; use re_types::Loggable as _; @@ -1112,14 +1118,13 @@ fn entity_props_ui( .checkbox(ui, &mut entity_props.interactive, "Interactive") .on_hover_text("If disabled, the entity will not react to any mouse interaction"); - visible_history_ui( + visual_time_range_ui( ctx, ui, - space_view_class, + &query_result.tree, + data_result, + *space_view_class, false, - Some(entity_path), - &mut entity_props.visible_history, - &resolved_entity_props.visible_history, ); egui::Grid::new("entity_properties") diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index 831f2f4fd4ee..f223f3eca65d 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -3,11 +3,16 @@ use std::ops::RangeInclusive; use egui::{NumExt as _, Response, Ui}; -use re_entity_db::{ExtraQueryHistory, TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; +use re_entity_db::{TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; use re_log_types::{EntityPath, TimeType, TimeZone}; +use re_space_view::{ + default_time_range, time_range_boundary_to_visible_history_boundary, + visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, +}; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; -use re_types_core::ComponentName; +use re_types::blueprint::components::VisibleTimeRange; +use re_types_core::{ComponentName, Loggable as _}; use re_ui::{markdown_ui, ReUi}; use re_viewer_context::{SpaceViewClass, SpaceViewClassIdentifier, TimeControl, ViewerContext}; @@ -44,45 +49,37 @@ static VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES: once_cell::sync::Lazy bool { + VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(&space_view_class) +} + +fn entity_with_visible_history( ctx: &ViewerContext<'_>, time_ctrl: &TimeControl, - space_view_class: &SpaceViewClassIdentifier, - entity_path: Option<&EntityPath>, + entity_path: &EntityPath, ) -> bool { - if !VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(space_view_class) { - return false; - } - - if let Some(entity_path) = entity_path { - let store = ctx.entity_db.store(); - let component_names = store.all_components(time_ctrl.timeline(), entity_path); - if let Some(component_names) = component_names { - if !component_names - .iter() - .any(|name| VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES.contains(name)) - { - return false; - } - } else { - return false; - } - } - - true + let store = ctx.entity_db.store(); + let component_names = store.all_components(time_ctrl.timeline(), entity_path); + component_names + .iter() + .flatten() + .any(|name| VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES.contains(name)) } -pub fn visible_history_ui( +pub fn visual_time_range_ui( ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - space_view_class: &SpaceViewClassIdentifier, + ui: &mut Ui, + data_result_tree: &re_viewer_context::DataResultTree, + data_result: &re_viewer_context::DataResult, + space_view_class: SpaceViewClassIdentifier, is_space_view: bool, - entity_path: Option<&EntityPath>, - visible_history_prop: &mut ExtraQueryHistory, - resolved_visible_history_prop: &ExtraQueryHistory, ) { let time_ctrl = ctx.rec_cfg.time_ctrl.read().clone(); - if !has_visible_history(ctx, &time_ctrl, space_view_class, entity_path) { + + if is_space_view && !space_view_with_visible_history(space_view_class) { + return; + } + if !is_space_view && !entity_with_visible_history(ctx, &time_ctrl, &data_result.entity_path) { return; } @@ -92,24 +89,33 @@ pub fn visible_history_ui( let mut interacting_with_controls = false; + let mut resolved_range = data_result + .lookup_override::(ctx) + .unwrap_or(default_time_range(space_view_class)); + let mut has_individual_range = data_result + .component_override_source(data_result_tree, &VisibleTimeRange::name()) + .as_ref() + == Some(&data_result.entity_path); + let collapsing_response = re_ui.collapsing_header(ui, "Visible time range", false, |ui| { + let has_individual_range_before = has_individual_range; + let resolved_range_before = resolved_range.clone(); + ui.horizontal(|ui| { re_ui - .radio_value(ui, &mut visible_history_prop.enabled, false, "Default") + .radio_value(ui, &mut has_individual_range, false, "Default") .on_hover_text(if is_space_view { "Default visible time range settings for this kind of Space View" } else { - "Visible time range settings inherited from parent Group(s) or enclosing \ + "Visible time range settings inherited from parent Entity or enclosing \ Space View" }); re_ui - .radio_value(ui, &mut visible_history_prop.enabled, true, "Override") + .radio_value(ui, &mut has_individual_range, true, "Override") .on_hover_text(if is_space_view { "Set visible time range settings for the contents of this Space View" - } else if entity_path.is_some() { - "Set visible time range settings for this entity" } else { - "Set visible time range settings for he contents of this Group" + "Set visible time range settings for this entity" }); }); @@ -125,22 +131,29 @@ pub fn visible_history_ui( .unwrap_or_default() .at_least(*timeline_spec.range.start()); // accounts for timeless time (TimeInt::BEGINNING) - let (resolved_visible_history, visible_history) = match time_type { + // pick right from/to depending on the timeline type. + let (from, to) = match time_type { TimeType::Time => ( - &resolved_visible_history_prop.nanos, - &mut visible_history_prop.nanos, + &mut resolved_range.0.from_time, + &mut resolved_range.0.to_time, ), TimeType::Sequence => ( - &resolved_visible_history_prop.sequences, - &mut visible_history_prop.sequences, + &mut resolved_range.0.from_sequence, + &mut resolved_range.0.to_sequence, ), }; - if visible_history_prop.enabled { - let current_low_boundary = visible_history + // Convert to legacy visual history type. + let mut visible_history = VisibleHistory { + from: time_range_boundary_to_visible_history_boundary(from), + to: time_range_boundary_to_visible_history_boundary(to), + }; + + if has_individual_range { + let current_from = visible_history .range_start_from_cursor(current_time.into()) .as_i64(); - let current_high_boundary = visible_history + let current_to = visible_history .range_end_from_cursor(current_time.into()) .as_i64(); @@ -156,7 +169,7 @@ pub fn visible_history_ui( current_time, &timeline_spec, true, - current_high_boundary, + current_to, ) }) .inner; @@ -173,23 +186,23 @@ pub fn visible_history_ui( current_time, &timeline_spec, false, - current_low_boundary, + current_from, ) }) .inner; ui.end_row(); }); - current_range_ui(ctx, ui, current_time, time_type, visible_history); + current_range_ui(ctx, ui, current_time, time_type, &visible_history); } else { // Show the resolved visible range as labels (user can't edit them): - if resolved_visible_history.from == VisibleHistoryBoundary::Infinite - && resolved_visible_history.to == VisibleHistoryBoundary::Infinite + if visible_history.from == VisibleHistoryBoundary::Infinite + && visible_history.to == VisibleHistoryBoundary::Infinite { ui.label("Entire timeline"); - } else if resolved_visible_history.from == VisibleHistoryBoundary::AT_CURSOR - && resolved_visible_history.to == VisibleHistoryBoundary::AT_CURSOR + } else if visible_history.from == VisibleHistoryBoundary::AT_CURSOR + && visible_history.to == VisibleHistoryBoundary::AT_CURSOR { let current_time = time_type.format(current_time.into(), ctx.app_options.time_zone); match time_type { @@ -206,7 +219,7 @@ pub fn visible_history_ui( resolved_visible_history_boundary_ui( ctx, ui, - &resolved_visible_history.from, + &visible_history.from, time_type, true, ); @@ -216,14 +229,31 @@ pub fn visible_history_ui( resolved_visible_history_boundary_ui( ctx, ui, - &resolved_visible_history.to, + &visible_history.to, time_type, false, ); ui.end_row(); }); - current_range_ui(ctx, ui, current_time, time_type, resolved_visible_history); + current_range_ui(ctx, ui, current_time, time_type, &visible_history); + } + } + + // Convert back from visual history type. + *from = visible_history_boundary_to_time_range_boundary(&visible_history.from); + *to = visible_history_boundary_to_time_range_boundary(&visible_history.to); + + // Save to blueprint store if anything has changed. + if has_individual_range != has_individual_range_before + || resolved_range != resolved_range_before + { + if has_individual_range { + re_log::debug!("override!"); + data_result.save_recursive_override(ctx, &resolved_range); + } else { + re_log::debug!("clear!"); + data_result.clear_recursive_override::(ctx); } } }); @@ -251,22 +281,15 @@ pub fn visible_history_ui( if should_display_visible_history { if let Some(current_time) = time_ctrl.time_int() { - let visible_history = match (visible_history_prop.enabled, time_type) { - (true, TimeType::Sequence) => visible_history_prop.sequences, - (true, TimeType::Time) => visible_history_prop.nanos, - (false, TimeType::Sequence) => resolved_visible_history_prop.sequences, - (false, TimeType::Time) => resolved_visible_history_prop.nanos, - }; - - ctx.rec_cfg.time_ctrl.write().highlighted_range = - Some(visible_history.time_range(current_time)); + let range = visible_time_range_to_time_range(&resolved_range, time_type, current_time); + ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); } } let markdown = format!("# Visible time range\n This feature controls the time range used to display data in the Space View. -The settings are inherited from parent Group(s) or enclosing Space View if not overridden. +The settings are inherited from the parent Entity or enclosing Space View if not overridden. Visible time range properties are stored separately for each _type_ of timelines. They may differ depending on \ whether the current timeline is temporal or a sequence. The current settings apply to all _{}_ timelines. diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 9847cc516536..24a2ebcd15ad 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -171,17 +171,57 @@ impl DataResult { } } + /// Saves a recursive override, does not take into current or default values. + /// + /// Ignores individual overrides and current value. + pub fn save_recursive_override( + &self, + ctx: &ViewerContext<'_>, + desired_override: &C, + ) { + re_tracing::profile_function!(); + + // TODO(jleibs): Make it impossible for this to happen with different type structure + // This should never happen unless we're doing something with a partially processed + // query. + let Some(recursive_override_path) = self.recursive_override_path() else { + re_log::warn!( + "Tried to save override for {:?} but it has no override path", + self.entity_path + ); + return; + }; + + ctx.save_blueprint_component(recursive_override_path, desired_override); + } + + /// Clears the recursive override for a given component + pub fn clear_recursive_override(&self, ctx: &ViewerContext<'_>) { + // TODO(jleibs): Make it impossible for this to happen with different type structure + // This should never happen unless we're doing something with a partially processed + // query. + let Some(recursive_override_path) = self.recursive_override_path() else { + re_log::warn!( + "Tried to save override for {:?} but it has no override path", + self.entity_path + ); + return; + }; + + ctx.save_empty_blueprint_component::(recursive_override_path); + } + /// Write the [`EntityProperties`] for this result back to the Blueprint store on the recursive override. /// /// Setting `new_recursive_props` to `None` will always clear the override. /// Otherwise, writes only if the recursive properties aren't already the same value. /// (does *not* take into account what the accumulated properties are which are a combination of recursive and individual overwrites) - pub fn save_recursive_override( + pub fn save_recursive_override_properties( &self, ctx: &ViewerContext<'_>, new_recursive_props: Option, ) { - self.save_override_internal( + self.save_override_properties_internal( ctx, new_recursive_props, self.recursive_override_path(), @@ -194,12 +234,12 @@ impl DataResult { /// Setting `new_individual_props` to `None` will always clear the override. /// Otherwise, writes only if the individual properties aren't already the same value. /// (does *not* take into account what the accumulated properties are which are a combination of recursive and individual overwrites) - pub fn save_individual_override( + pub fn save_individual_override_properties( &self, - new_individual_props: Option, ctx: &ViewerContext<'_>, + new_individual_props: Option, ) { - self.save_override_internal( + self.save_override_properties_internal( ctx, new_individual_props, self.individual_override_path(), @@ -207,7 +247,7 @@ impl DataResult { ); } - fn save_override_internal( + fn save_override_properties_internal( &self, ctx: &ViewerContext<'_>, new_individual_props: Option, diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 57ab7ca7b854..95daf97ca8f7 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -29,6 +29,7 @@ Data types are the lowest layer of the data model hierarchy * [`TensorBuffer`](datatypes/tensor_buffer.md) * [`TensorData`](datatypes/tensor_data.md) * [`TensorDimension`](datatypes/tensor_dimension.md) +* [`TimeInt`](datatypes/time_int.md) * [`Transform3D`](datatypes/transform3d.md) * [`TranslationAndMat3x3`](datatypes/translation_and_mat3x3.md) * [`TranslationRotationScale3D`](datatypes/translation_rotation_scale3d.md) diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index 6e766a712369..1ef35ab8e55a 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -23,6 +23,7 @@ scale3d.md linguist-generated=true tensor_buffer.md linguist-generated=true tensor_data.md linguist-generated=true tensor_dimension.md linguist-generated=true +time_int.md linguist-generated=true transform3d.md linguist-generated=true translation_and_mat3x3.md linguist-generated=true translation_rotation_scale3d.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/time_int.md b/docs/content/reference/types/datatypes/time_int.md new file mode 100644 index 000000000000..de6030538958 --- /dev/null +++ b/docs/content/reference/types/datatypes/time_int.md @@ -0,0 +1,16 @@ +--- +title: "TimeInt" +--- + +A 64-bit number describing either nanoseconds OR sequence numbers. + +## Fields + +* value: `i64` + +## Links + * 🌊 [C++ API docs for `TimeInt`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeInt.html?speculative-link) + * 🐍 [Python API docs for `TimeInt`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.TimeInt) + * 🦀 [Rust API docs for `TimeInt`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeInt.html?speculative-link) + + diff --git a/rerun_cpp/src/rerun/blueprint/.gitattributes b/rerun_cpp/src/rerun/blueprint/.gitattributes index 0661cd67c5ea..435e1f8fe40d 100644 --- a/rerun_cpp/src/rerun/blueprint/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/.gitattributes @@ -3,3 +3,4 @@ .gitattributes linguist-generated=true archetypes.hpp linguist-generated=true components.hpp linguist-generated=true +datatypes.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index fc45185e5696..715845efe9dd 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -23,3 +23,4 @@ #include "blueprint/components/space_view_origin.hpp" #include "blueprint/components/viewer_recommendation_hash.hpp" #include "blueprint/components/visible.hpp" +#include "blueprint/components/visible_time_range.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index c013fc7cd820..7b4380fbe687 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -33,3 +33,4 @@ space_view_origin.hpp linguist-generated=true viewer_recommendation_hash.hpp linguist-generated=true visible.cpp linguist-generated=true visible.hpp linguist-generated=true +visible_time_range.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp new file mode 100644 index 000000000000..f55840689b09 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp @@ -0,0 +1,60 @@ +// 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/components/visible_time_range.fbs". + +#pragma once + +#include "../../blueprint/datatypes/visible_time_range.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: The range of values that will be included in a Space View query. + struct VisibleTimeRange { + rerun::blueprint::datatypes::VisibleTimeRange value; + + public: + VisibleTimeRange() = default; + + VisibleTimeRange(rerun::blueprint::datatypes::VisibleTimeRange value_) : value(value_) {} + + VisibleTimeRange& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { + value = value_; + return *this; + } + + /// Cast to the underlying VisibleTimeRange datatype + operator rerun::blueprint::datatypes::VisibleTimeRange() const { + return value; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert( + sizeof(rerun::blueprint::datatypes::VisibleTimeRange) == + sizeof(blueprint::components::VisibleTimeRange) + ); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.VisibleTimeRange"; + + /// 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::VisibleTimeRange` into an arrow array. + static Result> to_arrow( + const blueprint::components::VisibleTimeRange* instances, size_t num_instances + ) { + return Loggable::to_arrow( + &instances->value, + num_instances + ); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes.hpp b/rerun_cpp/src/rerun/blueprint/datatypes.hpp new file mode 100644 index 000000000000..361e00061d0e --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes.hpp @@ -0,0 +1,7 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs + +#pragma once + +#include "blueprint/datatypes/visible_time_range.hpp" +#include "blueprint/datatypes/visible_time_range_boundary.hpp" +#include "blueprint/datatypes/visible_time_range_boundary_kind.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes index da03d4b96e87..06328369afaa 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes @@ -1,5 +1,9 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -legend.cpp linguist-generated=true -legend.hpp linguist-generated=true +visible_time_range.cpp linguist-generated=true +visible_time_range.hpp linguist-generated=true +visible_time_range_boundary.cpp linguist-generated=true +visible_time_range_boundary.hpp linguist-generated=true +visible_time_range_boundary_kind.cpp linguist-generated=true +visible_time_range_boundary_kind.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp deleted file mode 100644 index 948dd620e8bc..000000000000 --- a/rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// 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/datatypes/legend.fbs". - -#include "legend.hpp" - -#include -#include - -namespace rerun::blueprint::datatypes {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype( - ) { - static const auto datatype = arrow::struct_({ - arrow::field("visible", arrow::boolean(), false), - arrow::field("location", arrow::uint8(), true), - }); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const blueprint::datatypes::Legend* 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)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - ARROW_RETURN_NOT_OK(field_builder->Append(elements[elem_idx].visible)); - } - } - { - auto field_builder = static_cast(builder->field_builder(1)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - const auto& element = elements[elem_idx]; - if (element.location.has_value()) { - ARROW_RETURN_NOT_OK(field_builder->Append(element.location.value())); - } else { - ARROW_RETURN_NOT_OK(field_builder->AppendNull()); - } - } - } - ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const blueprint::datatypes::Legend* 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; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp new file mode 100644 index 000000000000..36f9e1bdaa5b --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp @@ -0,0 +1,124 @@ +// 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/datatypes/visible_time_range.fbs". + +#include "visible_time_range.hpp" + +#include "visible_time_range_boundary.hpp" + +#include +#include + +namespace rerun::blueprint::datatypes {} + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::struct_({ + arrow::field( + "from_sequence", + Loggable::arrow_datatype(), + false + ), + arrow::field( + "to_sequence", + Loggable::arrow_datatype(), + false + ), + arrow::field( + "from_time", + Loggable::arrow_datatype(), + false + ), + arrow::field( + "to_time", + Loggable::arrow_datatype(), + false + ), + }); + return datatype; + } + + Result> + Loggable::to_arrow( + const blueprint::datatypes::VisibleTimeRange* 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 blueprint::datatypes::VisibleTimeRange* 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)); + 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].from_sequence, + 1 + )); + } + } + { + auto field_builder = static_cast(builder->field_builder(1)); + 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].to_sequence, 1) + ); + } + } + { + auto field_builder = static_cast(builder->field_builder(2)); + 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].from_time, 1) + ); + } + } + { + auto field_builder = static_cast(builder->field_builder(3)); + 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].to_time, 1) + ); + } + } + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp new file mode 100644 index 000000000000..6a0dc250edf7 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp @@ -0,0 +1,61 @@ +// 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/datatypes/visible_time_range.fbs". + +#pragma once + +#include "../../result.hpp" +#include "visible_time_range_boundary.hpp" + +#include +#include + +namespace arrow { + class Array; + class DataType; + class StructBuilder; +} // namespace arrow + +namespace rerun::blueprint::datatypes { + /// **Datatype**: Visible time range bounds. + struct VisibleTimeRange { + /// Low time boundary for sequence timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary from_sequence; + + /// High time boundary for sequence timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary to_sequence; + + /// Low time boundary for time timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary from_time; + + /// High time boundary for time timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary to_time; + + public: + VisibleTimeRange() = default; + }; +} // namespace rerun::blueprint::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.datatypes.VisibleTimeRange"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRange` into an arrow array. + static Result> to_arrow( + const blueprint::datatypes::VisibleTimeRange* 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 blueprint::datatypes::VisibleTimeRange* elements, + size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp new file mode 100644 index 000000000000..6e4820a69c1f --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.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/blueprint/datatypes/visible_time_range.fbs". + +#include "visible_time_range_boundary.hpp" + +#include "../../datatypes/time_int.hpp" +#include "visible_time_range_boundary_kind.hpp" + +#include +#include + +namespace rerun::blueprint::datatypes {} + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::struct_({ + arrow::field( + "kind", + Loggable::arrow_datatype( + ), + false + ), + arrow::field("time", Loggable::arrow_datatype(), false), + }); + return datatype; + } + + Result> + Loggable::to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundary* 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 blueprint::datatypes::VisibleTimeRangeBoundary* 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)); + 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].kind, 1) + ); + } + } + { + auto field_builder = static_cast(builder->field_builder(1)); + 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].time, + 1 + )); + } + } + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/legend.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp similarity index 55% rename from rerun_cpp/src/rerun/blueprint/datatypes/legend.hpp rename to rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp index b8efd53df620..317bf804ec91 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/legend.hpp +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp @@ -1,13 +1,14 @@ // 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/datatypes/legend.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". #pragma once +#include "../../datatypes/time_int.hpp" #include "../../result.hpp" +#include "visible_time_range_boundary_kind.hpp" #include #include -#include namespace arrow { class Array; @@ -16,22 +17,16 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::datatypes { - /// **Datatype**: Configuration for the legend of a plot. - struct Legend { - /// Whether or not the legend should be displayed. - bool visible; - - /// Where should the legend be located. - /// - /// Allowed values: - /// - LeftTop = 1, - /// - RightTop = 2, - /// - LeftBottom = 3, - /// - RightBottom = 4 - std::optional location; + /// **Datatype**: Type of boundary for visible history. + struct VisibleTimeRangeBoundary { + /// Type of the boundary. + rerun::blueprint::datatypes::VisibleTimeRangeBoundaryKind kind; + + /// Value of the boundary (ignored for `Infinite` type). + rerun::datatypes::TimeInt time; public: - Legend() = default; + VisibleTimeRangeBoundary() = default; }; } // namespace rerun::blueprint::datatypes @@ -41,21 +36,21 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.datatypes.Legend"; + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.datatypes.VisibleTimeRangeBoundary"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const blueprint::datatypes::Legend* elements, - size_t num_elements + /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRangeBoundary` into an arrow array. + static Result> to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances ); - /// Serializes an array of `rerun::blueprint:: datatypes::Legend` into an arrow array. - static Result> to_arrow( - const blueprint::datatypes::Legend* 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 blueprint::datatypes::VisibleTimeRangeBoundary* elements, size_t num_elements ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp new file mode 100644 index 000000000000..08a67a5061bf --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp @@ -0,0 +1,67 @@ +// 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/datatypes/visible_time_range.fbs". + +#include "visible_time_range_boundary_kind.hpp" + +#include +#include + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::sparse_union({ + arrow::field("_null_markers", arrow::null(), true, nullptr), + arrow::field("RelativeToTimeCursor", arrow::null(), true), + arrow::field("Absolute", arrow::null(), true), + arrow::field("Infinite", arrow::null(), true), + }); + return datatype; + } + + Result> + Loggable::to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* 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::SparseUnionBuilder* builder, + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* 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." + ); + } + + ARROW_RETURN_NOT_OK(builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + const auto variant = elements[elem_idx]; + ARROW_RETURN_NOT_OK(builder->Append(static_cast(variant))); + } + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp new file mode 100644 index 000000000000..59025d01da86 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp @@ -0,0 +1,57 @@ +// 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/datatypes/visible_time_range.fbs". + +#pragma once + +#include "../../result.hpp" + +#include +#include + +namespace arrow { + class Array; + class DataType; + class SparseUnionBuilder; +} // namespace arrow + +namespace rerun::blueprint::datatypes { + /// **Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. + enum class VisibleTimeRangeBoundaryKind : uint8_t { + + /// Boundary is a value relative to the time cursor. + RelativeToTimeCursor = 1, + + /// Boundary is an absolute value. + Absolute = 2, + + /// The boundary extends to infinity. + Infinite = 3, + }; +} // namespace rerun::blueprint::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = + "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRangeBoundaryKind` into an arrow array. + static Result> to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* instances, + size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* elements, size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 7f33e559abe9..81c850bdde6f 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -24,6 +24,7 @@ #include "datatypes/tensor_buffer.hpp" #include "datatypes/tensor_data.hpp" #include "datatypes/tensor_dimension.hpp" +#include "datatypes/time_int.hpp" #include "datatypes/transform3d.hpp" #include "datatypes/translation_and_mat3x3.hpp" #include "datatypes/translation_rotation_scale3d.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 5c61073231da..83fde1441f4b 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -45,6 +45,8 @@ tensor_data.cpp linguist-generated=true tensor_data.hpp linguist-generated=true tensor_dimension.cpp linguist-generated=true tensor_dimension.hpp linguist-generated=true +time_int.cpp linguist-generated=true +time_int.hpp linguist-generated=true transform3d.cpp linguist-generated=true transform3d.hpp linguist-generated=true translation_and_mat3x3.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/time_int.cpp b/rerun_cpp/src/rerun/datatypes/time_int.cpp new file mode 100644 index 000000000000..7b368b716fcd --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/time_int.cpp @@ -0,0 +1,57 @@ +// 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/time_int.fbs". + +#include "time_int.hpp" + +#include +#include + +namespace rerun::datatypes {} + +namespace rerun { + const std::shared_ptr& Loggable::arrow_datatype() { + static const auto datatype = arrow::int64(); + return datatype; + } + + Result> Loggable::to_arrow( + const datatypes::TimeInt* 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::Int64Builder* builder, const datatypes::TimeInt* 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." + ); + } + + static_assert(sizeof(*elements) == sizeof(elements->value)); + ARROW_RETURN_NOT_OK( + builder->AppendValues(&elements->value, static_cast(num_elements)) + ); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/time_int.hpp b/rerun_cpp/src/rerun/datatypes/time_int.hpp new file mode 100644 index 000000000000..75b090690811 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/time_int.hpp @@ -0,0 +1,61 @@ +// 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/time_int.fbs". + +#pragma once + +#include "../result.hpp" + +#include +#include + +namespace arrow { + /// \private + template + class NumericBuilder; + + class Array; + class DataType; + class Int64Type; + using Int64Builder = NumericBuilder; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: A 64-bit number describing either nanoseconds OR sequence numbers. + struct TimeInt { + int64_t value; + + public: + TimeInt() = default; + + TimeInt(int64_t value_) : value(value_) {} + + TimeInt& operator=(int64_t value_) { + value = value_; + return *this; + } + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.TimeInt"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::datatypes::TimeInt` into an arrow array. + static Result> to_arrow( + const datatypes::TimeInt* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::Int64Builder* builder, const datatypes::TimeInt* elements, size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index 2ad52015791a..a8e9e72f9c7e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -23,3 +23,4 @@ space_view_maximized.py linguist-generated=true space_view_origin.py linguist-generated=true viewer_recommendation_hash.py linguist-generated=true visible.py linguist-generated=true +visible_time_range.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 94f3b1e26008..1dbd8f8d98c3 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -57,6 +57,7 @@ ViewerRecommendationHashType, ) from .visible import Visible, VisibleArrayLike, VisibleBatch, VisibleLike, VisibleType +from .visible_time_range import VisibleTimeRange, VisibleTimeRangeBatch, VisibleTimeRangeType __all__ = [ "ActiveTab", @@ -143,5 +144,8 @@ "VisibleArrayLike", "VisibleBatch", "VisibleLike", + "VisibleTimeRange", + "VisibleTimeRangeBatch", + "VisibleTimeRangeType", "VisibleType", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py new file mode 100644 index 000000000000..7ffed4d09f56 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.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/blueprint/components/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". + +from __future__ import annotations + +from ..._baseclasses import ComponentBatchMixin +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = ["VisibleTimeRange", "VisibleTimeRangeBatch", "VisibleTimeRangeType"] + + +class VisibleTimeRange(blueprint_datatypes.VisibleTimeRange): + """**Component**: The range of values that will be included in a Space View query.""" + + # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py + + # Note: there are no fields here because VisibleTimeRange delegates to datatypes.VisibleTimeRange + pass + + +class VisibleTimeRangeType(blueprint_datatypes.VisibleTimeRangeType): + _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRange" + + +class VisibleTimeRangeBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): + _ARROW_TYPE = VisibleTimeRangeType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes index d7d100d86518..5f25eb77dacd 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes @@ -2,4 +2,6 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true -legend.py linguist-generated=true +visible_time_range.py linguist-generated=true +visible_time_range_boundary.py linguist-generated=true +visible_time_range_boundary_kind.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py index e18ca0758275..cfcebd2abc65 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py @@ -1,7 +1,43 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python.rs +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs from __future__ import annotations -from .legend import Legend, LegendArrayLike, LegendBatch, LegendLike, LegendType +from .visible_time_range import ( + VisibleTimeRange, + VisibleTimeRangeArrayLike, + VisibleTimeRangeBatch, + VisibleTimeRangeLike, + VisibleTimeRangeType, +) +from .visible_time_range_boundary import ( + VisibleTimeRangeBoundary, + VisibleTimeRangeBoundaryArrayLike, + VisibleTimeRangeBoundaryBatch, + VisibleTimeRangeBoundaryLike, + VisibleTimeRangeBoundaryType, +) +from .visible_time_range_boundary_kind import ( + VisibleTimeRangeBoundaryKind, + VisibleTimeRangeBoundaryKindArrayLike, + VisibleTimeRangeBoundaryKindBatch, + VisibleTimeRangeBoundaryKindLike, + VisibleTimeRangeBoundaryKindType, +) -__all__ = ["Legend", "LegendArrayLike", "LegendBatch", "LegendLike", "LegendType"] +__all__ = [ + "VisibleTimeRange", + "VisibleTimeRangeArrayLike", + "VisibleTimeRangeBatch", + "VisibleTimeRangeBoundary", + "VisibleTimeRangeBoundaryArrayLike", + "VisibleTimeRangeBoundaryBatch", + "VisibleTimeRangeBoundaryKind", + "VisibleTimeRangeBoundaryKindArrayLike", + "VisibleTimeRangeBoundaryKindBatch", + "VisibleTimeRangeBoundaryKindLike", + "VisibleTimeRangeBoundaryKindType", + "VisibleTimeRangeBoundaryLike", + "VisibleTimeRangeBoundaryType", + "VisibleTimeRangeLike", + "VisibleTimeRangeType", +] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py deleted file mode 100644 index 3c462c99938f..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py +++ /dev/null @@ -1,92 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python.rs -# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/legend.fbs". - -# You can extend this class by creating a "LegendExt" class in "legend_ext.py". - -from __future__ import annotations - -from typing import Any, Sequence, Union - -import pyarrow as pa -from attrs import define, field - -from ..._baseclasses import BaseBatch, BaseExtensionType -from ..._converters import ( - int_or_none, -) - -__all__ = ["Legend", "LegendArrayLike", "LegendBatch", "LegendLike", "LegendType"] - - -@define(init=False) -class Legend: - """**Datatype**: Configuration for the legend of a plot.""" - - def __init__(self: Any, visible: bool, location: int | None = None): - """ - Create a new instance of the Legend datatype. - - Parameters - ---------- - visible: - Whether or not the legend should be displayed. - location: - Where should the legend be located. - - Allowed values: - - LeftTop = 1, - - RightTop = 2, - - LeftBottom = 3, - - RightBottom = 4 - - """ - - # You can define your own __init__ function as a member of LegendExt in legend_ext.py - self.__attrs_init__(visible=visible, location=location) - - visible: bool = field(converter=bool) - # Whether or not the legend should be displayed. - # - # (Docstring intentionally commented out to hide this field from the docs) - - location: int | None = field(default=None, converter=int_or_none) - # Where should the legend be located. - # - # Allowed values: - # - LeftTop = 1, - # - RightTop = 2, - # - LeftBottom = 3, - # - RightBottom = 4 - # - # (Docstring intentionally commented out to hide this field from the docs) - - -LegendLike = Legend -LegendArrayLike = Union[ - Legend, - Sequence[LegendLike], -] - - -class LegendType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.datatypes.Legend" - - def __init__(self) -> None: - pa.ExtensionType.__init__( - self, - pa.struct( - [ - pa.field("visible", pa.bool_(), nullable=False, metadata={}), - pa.field("location", pa.uint8(), nullable=True, metadata={}), - ] - ), - self._TYPE_NAME, - ) - - -class LegendBatch(BaseBatch[LegendArrayLike]): - _ARROW_TYPE = LegendType() - - @staticmethod - def _native_to_pa_array(data: LegendArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in legend_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py new file mode 100644 index 000000000000..735c720b7a47 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py @@ -0,0 +1,194 @@ +# 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/datatypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from ..._baseclasses import BaseBatch, BaseExtensionType +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = [ + "VisibleTimeRange", + "VisibleTimeRangeArrayLike", + "VisibleTimeRangeBatch", + "VisibleTimeRangeLike", + "VisibleTimeRangeType", +] + + +@define(init=False) +class VisibleTimeRange: + """**Datatype**: Visible time range bounds.""" + + def __init__( + self: Any, + from_sequence: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + to_sequence: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + from_time: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + to_time: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + ): + """ + Create a new instance of the VisibleTimeRange datatype. + + Parameters + ---------- + from_sequence: + Low time boundary for sequence timeline. + to_sequence: + High time boundary for sequence timeline. + from_time: + Low time boundary for time timeline. + to_time: + High time boundary for time timeline. + + """ + + # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py + self.__attrs_init__(from_sequence=from_sequence, to_sequence=to_sequence, from_time=from_time, to_time=to_time) + + from_sequence: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # Low time boundary for sequence timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + to_sequence: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # High time boundary for sequence timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + from_time: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # Low time boundary for time timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + to_time: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # High time boundary for time timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + +VisibleTimeRangeLike = VisibleTimeRange +VisibleTimeRangeArrayLike = Union[ + VisibleTimeRange, + Sequence[VisibleTimeRangeLike], +] + + +class VisibleTimeRangeType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRange" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct( + [ + pa.field( + "from_sequence", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field( + "to_sequence", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field( + "from_time", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field( + "to_time", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + ] + ), + self._TYPE_NAME, + ) + + +class VisibleTimeRangeBatch(BaseBatch[VisibleTimeRangeArrayLike]): + _ARROW_TYPE = VisibleTimeRangeType() + + @staticmethod + def _native_to_pa_array(data: VisibleTimeRangeArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in visible_time_range_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py new file mode 100644 index 000000000000..7d94422c9c4e --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py @@ -0,0 +1,104 @@ +# 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/datatypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeBoundaryExt" class in "visible_time_range_boundary_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import BaseBatch, BaseExtensionType +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = [ + "VisibleTimeRangeBoundary", + "VisibleTimeRangeBoundaryArrayLike", + "VisibleTimeRangeBoundaryBatch", + "VisibleTimeRangeBoundaryLike", + "VisibleTimeRangeBoundaryType", +] + + +def _visible_time_range_boundary__time__special_field_converter_override(x: datatypes.TimeIntLike) -> datatypes.TimeInt: + if isinstance(x, datatypes.TimeInt): + return x + else: + return datatypes.TimeInt(x) + + +@define(init=False) +class VisibleTimeRangeBoundary: + """**Datatype**: Type of boundary for visible history.""" + + def __init__(self: Any, kind: blueprint_datatypes.VisibleTimeRangeBoundaryKindLike, time: datatypes.TimeIntLike): + """ + Create a new instance of the VisibleTimeRangeBoundary datatype. + + Parameters + ---------- + kind: + Type of the boundary. + time: + Value of the boundary (ignored for `Infinite` type). + + """ + + # You can define your own __init__ function as a member of VisibleTimeRangeBoundaryExt in visible_time_range_boundary_ext.py + self.__attrs_init__(kind=kind, time=time) + + kind: blueprint_datatypes.VisibleTimeRangeBoundaryKind = field() + # Type of the boundary. + # + # (Docstring intentionally commented out to hide this field from the docs) + + time: datatypes.TimeInt = field(converter=_visible_time_range_boundary__time__special_field_converter_override) + # Value of the boundary (ignored for `Infinite` type). + # + # (Docstring intentionally commented out to hide this field from the docs) + + +VisibleTimeRangeBoundaryLike = VisibleTimeRangeBoundary +VisibleTimeRangeBoundaryArrayLike = Union[ + VisibleTimeRangeBoundary, + Sequence[VisibleTimeRangeBoundaryLike], +] + + +class VisibleTimeRangeBoundaryType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRangeBoundary" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + self._TYPE_NAME, + ) + + +class VisibleTimeRangeBoundaryBatch(BaseBatch[VisibleTimeRangeBoundaryArrayLike]): + _ARROW_TYPE = VisibleTimeRangeBoundaryType() + + @staticmethod + def _native_to_pa_array(data: VisibleTimeRangeBoundaryArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in visible_time_range_boundary_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py new file mode 100644 index 000000000000..e179602b070d --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py @@ -0,0 +1,105 @@ +# 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/datatypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeBoundaryKindExt" class in "visible_time_range_boundary_kind_ext.py". + +from __future__ import annotations + +from typing import Sequence, Union + +import pyarrow as pa + +from ..._baseclasses import BaseBatch, BaseExtensionType + +__all__ = [ + "VisibleTimeRangeBoundaryKind", + "VisibleTimeRangeBoundaryKindArrayLike", + "VisibleTimeRangeBoundaryKindBatch", + "VisibleTimeRangeBoundaryKindLike", + "VisibleTimeRangeBoundaryKindType", +] + + +from enum import Enum + + +class VisibleTimeRangeBoundaryKind(Enum): + """**Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`.""" + + RelativeToTimeCursor = 1 + """Boundary is a value relative to the time cursor.""" + + Absolute = 2 + """Boundary is an absolute value.""" + + Infinite = 3 + """The boundary extends to infinity.""" + + +VisibleTimeRangeBoundaryKindLike = Union[VisibleTimeRangeBoundaryKind, str] +VisibleTimeRangeBoundaryKindArrayLike = Union[ + VisibleTimeRangeBoundaryKindLike, Sequence[VisibleTimeRangeBoundaryKindLike] +] + + +class VisibleTimeRangeBoundaryKindType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + self._TYPE_NAME, + ) + + +class VisibleTimeRangeBoundaryKindBatch(BaseBatch[VisibleTimeRangeBoundaryKindArrayLike]): + _ARROW_TYPE = VisibleTimeRangeBoundaryKindType() + + @staticmethod + def _native_to_pa_array(data: VisibleTimeRangeBoundaryKindArrayLike, data_type: pa.DataType) -> pa.Array: + if isinstance(data, (VisibleTimeRangeBoundaryKind, int, str)): + data = [data] + + types: list[int] = [] + + for value in data: + if value is None: + types.append(0) + elif isinstance(value, VisibleTimeRangeBoundaryKind): + types.append(value.value) # Actual enum value + elif isinstance(value, int): + types.append(value) # By number + elif isinstance(value, str): + if hasattr(VisibleTimeRangeBoundaryKind, value): + types.append(VisibleTimeRangeBoundaryKind[value].value) # fast path + elif value.lower() == "relativetotimecursor": + types.append(VisibleTimeRangeBoundaryKind.RelativeToTimeCursor.value) + elif value.lower() == "absolute": + types.append(VisibleTimeRangeBoundaryKind.Absolute.value) + elif value.lower() == "infinite": + types.append(VisibleTimeRangeBoundaryKind.Infinite.value) + else: + raise ValueError(f"Unknown VisibleTimeRangeBoundaryKind kind: {value}") + else: + raise ValueError(f"Unknown VisibleTimeRangeBoundaryKind kind: {value}") + + buffers = [ + None, + pa.array(types, type=pa.int8()).buffers()[1], + ] + children = (1 + 3) * [pa.nulls(len(data))] + + return pa.UnionArray.from_buffers( + type=data_type, + length=len(data), + buffers=buffers, + children=children, + ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 02728bf929d2..74fd88d4d968 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -24,6 +24,7 @@ scale3d.py linguist-generated=true tensor_buffer.py linguist-generated=true tensor_data.py linguist-generated=true tensor_dimension.py linguist-generated=true +time_int.py linguist-generated=true transform3d.py linguist-generated=true translation_and_mat3x3.py linguist-generated=true translation_rotation_scale3d.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 36fcb289aa61..31fb9e4f05e4 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -60,6 +60,7 @@ TensorDimensionLike, TensorDimensionType, ) +from .time_int import TimeInt, TimeIntArrayLike, TimeIntBatch, TimeIntLike, TimeIntType from .transform3d import Transform3D, Transform3DArrayLike, Transform3DBatch, Transform3DLike, Transform3DType from .translation_and_mat3x3 import ( TranslationAndMat3x3, @@ -197,6 +198,11 @@ "TensorDimensionBatch", "TensorDimensionLike", "TensorDimensionType", + "TimeInt", + "TimeIntArrayLike", + "TimeIntBatch", + "TimeIntLike", + "TimeIntType", "Transform3D", "Transform3DArrayLike", "Transform3DBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/time_int.py b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py new file mode 100644 index 000000000000..56b224544a7c --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py @@ -0,0 +1,59 @@ +# 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/time_int.fbs". + +# You can extend this class by creating a "TimeIntExt" class in "time_int_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 + +__all__ = ["TimeInt", "TimeIntArrayLike", "TimeIntBatch", "TimeIntLike", "TimeIntType"] + + +@define(init=False) +class TimeInt: + """**Datatype**: A 64-bit number describing either nanoseconds OR sequence numbers.""" + + def __init__(self: Any, value: TimeIntLike): + """Create a new instance of the TimeInt datatype.""" + + # You can define your own __init__ function as a member of TimeIntExt in time_int_ext.py + self.__attrs_init__(value=value) + + value: int = field(converter=int) + + def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: + # You can define your own __array__ function as a member of TimeIntExt in time_int_ext.py + return np.asarray(self.value, dtype=dtype) + + def __int__(self) -> int: + return int(self.value) + + +TimeIntLike = TimeInt +TimeIntArrayLike = Union[ + TimeInt, + Sequence[TimeIntLike], +] + + +class TimeIntType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.TimeInt" + + def __init__(self) -> None: + pa.ExtensionType.__init__(self, pa.int64(), self._TYPE_NAME) + + +class TimeIntBatch(BaseBatch[TimeIntArrayLike]): + _ARROW_TYPE = TimeIntType() + + @staticmethod + def _native_to_pa_array(data: TimeIntArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in time_int_ext.py