diff --git a/crates/re_space_view_bar_chart/src/space_view_class.rs b/crates/re_space_view_bar_chart/src/space_view_class.rs index 99afebef569e..1e61cb4cc75c 100644 --- a/crates/re_space_view_bar_chart/src/space_view_class.rs +++ b/crates/re_space_view_bar_chart/src/space_view_class.rs @@ -50,9 +50,9 @@ impl SpaceViewClass for BarChartSpaceView { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index cc74936141d3..868512bb3eae 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -40,9 +40,9 @@ impl SpaceViewClass for DataframeSpaceView { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { diff --git a/crates/re_space_view_spatial/src/contexts/mod.rs b/crates/re_space_view_spatial/src/contexts/mod.rs index 9bbb50145198..bbb0e34715d5 100644 --- a/crates/re_space_view_spatial/src/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/contexts/mod.rs @@ -60,7 +60,7 @@ impl ViewContextSystem for PrimitiveCounter { } pub fn register_spatial_contexts( - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { system_registry.register_context_system::()?; system_registry.register_context_system::()?; diff --git a/crates/re_space_view_spatial/src/heuristics.rs b/crates/re_space_view_spatial/src/heuristics.rs index 867c00717de0..11642823525a 100644 --- a/crates/re_space_view_spatial/src/heuristics.rs +++ b/crates/re_space_view_spatial/src/heuristics.rs @@ -22,7 +22,7 @@ use crate::{ }; pub fn auto_spawn_heuristic( - class: &SpaceViewClassIdentifier, + class: SpaceViewClassIdentifier, ctx: &ViewerContext<'_>, per_system_entities: &PerSystemEntities, view_kind: SpatialSpaceViewKind, @@ -31,10 +31,7 @@ pub fn auto_spawn_heuristic( let mut score = 0.0; - let parts = ctx - .space_view_class_registry - .get_system_registry_or_log_error(class) - .new_part_collection(); + let parts = ctx.space_view_class_registry.new_part_collection(class); // Gather all systems that advertise a "preferred view kind" matching the passed in kind. let system_names_with_matching_view_kind = parts diff --git a/crates/re_space_view_spatial/src/parts/mod.rs b/crates/re_space_view_spatial/src/parts/mod.rs index 71c76a43779c..ea2ded62b542 100644 --- a/crates/re_space_view_spatial/src/parts/mod.rs +++ b/crates/re_space_view_spatial/src/parts/mod.rs @@ -33,7 +33,7 @@ use re_types::datatypes::{KeypointId, KeypointPair}; use re_types::Archetype; use re_viewer_context::SpaceViewClassRegistryError; use re_viewer_context::{ - auto_color, Annotations, DefaultColor, ResolvedAnnotationInfos, SpaceViewSystemRegistry, + auto_color, Annotations, DefaultColor, ResolvedAnnotationInfos, SpaceViewSystemRegistrator, ViewPartCollection, ViewQuery, }; @@ -46,39 +46,39 @@ pub const SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES: f32 = 1.5; pub const SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES: f32 = 2.5; pub fn register_2d_spatial_parts( - system_registry: &mut SpaceViewSystemRegistry, + system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { // Note: 2D spatial systems don't include cameras as this // part only shows a 2D projection WITHIN a 3D view. - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; Ok(()) } pub fn register_3d_spatial_parts( - system_registry: &mut SpaceViewSystemRegistry, + system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; - system_registry.register_part_system::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; + system_registry.register_visualizer::()?; Ok(()) } diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index a4e6301cc6bc..4dd1a4f24707 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -32,7 +32,7 @@ impl SpaceViewClass for SpatialSpaceView2D { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { register_spatial_contexts(system_registry)?; register_2d_spatial_parts(system_registry)?; @@ -72,7 +72,7 @@ impl SpaceViewClass for SpatialSpaceView2D { per_system_entities: &PerSystemEntities, ) -> AutoSpawnHeuristic { let mut score = auto_spawn_heuristic( - &self.identifier(), + self.identifier(), ctx, per_system_entities, SpatialSpaceViewKind::TwoD, @@ -92,8 +92,7 @@ impl SpaceViewClass for SpatialSpaceView2D { if space_origin.is_root() { let parts = ctx .space_view_class_registry - .get_system_registry_or_log_error(&self.identifier()) - .new_part_collection(); + .new_part_collection(self.identifier()); for part in per_system_entities.keys() { if let Ok(part) = parts.get_by_identifier(*part) { diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index e95ff65af6c9..b30f120993cd 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -33,7 +33,7 @@ impl SpaceViewClass for SpatialSpaceView3D { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { register_spatial_contexts(system_registry)?; register_3d_spatial_parts(system_registry)?; @@ -56,7 +56,7 @@ impl SpaceViewClass for SpatialSpaceView3D { per_system_entities: &PerSystemEntities, ) -> AutoSpawnHeuristic { let score = auto_spawn_heuristic( - &self.identifier(), + self.identifier(), ctx, per_system_entities, SpatialSpaceViewKind::ThreeD, diff --git a/crates/re_space_view_tensor/src/space_view_class.rs b/crates/re_space_view_tensor/src/space_view_class.rs index 1e7f0993f6a6..d79170566ab8 100644 --- a/crates/re_space_view_tensor/src/space_view_class.rs +++ b/crates/re_space_view_tensor/src/space_view_class.rs @@ -149,9 +149,9 @@ impl SpaceViewClass for TensorSpaceView { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { diff --git a/crates/re_space_view_text_document/src/space_view_class.rs b/crates/re_space_view_text_document/src/space_view_class.rs index f9cb06b88b42..9c8c5f371e92 100644 --- a/crates/re_space_view_text_document/src/space_view_class.rs +++ b/crates/re_space_view_text_document/src/space_view_class.rs @@ -61,9 +61,9 @@ impl SpaceViewClass for TextDocumentSpaceView { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn layout_priority(&self) -> re_viewer_context::SpaceViewClassLayoutPriority { diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index dc4d2d26fae9..baa257cd0a77 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -55,9 +55,9 @@ impl SpaceViewClass for TextSpaceView { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 93e3602d8423..572045c4c9c2 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -80,9 +80,9 @@ impl SpaceViewClass for TimeSeriesSpaceView { fn on_register( &self, - system_registry: &mut re_viewer_context::SpaceViewSystemRegistry, + system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 34afff8d9759..aac2b9a87983 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -45,9 +45,9 @@ pub use space_view::{ HeuristicFilterContext, IdentifiedViewSystem, PerSystemDataResults, PerSystemEntities, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, - SpaceViewOutlineMasks, SpaceViewState, SpaceViewSystemExecutionError, SpaceViewSystemRegistry, - SystemExecutionOutput, ViewContextCollection, ViewContextSystem, ViewPartCollection, - ViewPartSystem, ViewQuery, ViewSystemIdentifier, + SpaceViewOutlineMasks, SpaceViewState, SpaceViewSystemExecutionError, + SpaceViewSystemRegistrator, SystemExecutionOutput, ViewContextCollection, ViewContextSystem, + ViewPartCollection, ViewPartSystem, ViewQuery, ViewSystemIdentifier, }; pub use store_context::StoreContext; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; diff --git a/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs b/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs index 6608eab42672..efa0728492a7 100644 --- a/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs @@ -4,7 +4,7 @@ use re_types::ComponentName; use crate::{ AutoSpawnHeuristic, PerSystemEntities, SpaceViewClassRegistryError, SpaceViewId, - SpaceViewSystemRegistry, SystemExecutionOutput, ViewQuery, ViewerContext, + SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, ViewerContext, }; re_string_interner::declare_new_type!( @@ -71,7 +71,7 @@ pub trait DynSpaceViewClass: Send + Sync { /// This can be used to register all built-in [`crate::ViewContextSystem`] and [`crate::ViewPartSystem`]. fn on_register( &self, - system_registry: &mut SpaceViewSystemRegistry, + system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError>; /// Called once for every new space view instance of this class. diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 7e022f2e9de1..ea00772759e9 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -24,7 +24,7 @@ pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOut pub use named_system::{IdentifiedViewSystem, PerSystemEntities, ViewSystemIdentifier}; pub use space_view_class::SpaceViewClass; pub use space_view_class_registry::{ - SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewSystemRegistry, + SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewSystemRegistrator, }; pub use system_execution_output::SystemExecutionOutput; pub use view_context_system::{ViewContextCollection, ViewContextSystem}; diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 23b313e37837..d042237f930c 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -5,7 +5,7 @@ use re_types::ComponentName; use crate::{ AutoSpawnHeuristic, DynSpaceViewClass, PerSystemEntities, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, SpaceViewSystemExecutionError, - SpaceViewSystemRegistry, SystemExecutionOutput, ViewQuery, ViewerContext, + SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, ViewerContext, }; /// Defines a class of space view. @@ -50,7 +50,7 @@ pub trait SpaceViewClass: std::marker::Sized + Send + Sync { /// This can be used to register all built-in [`crate::ViewContextSystem`] and [`crate::ViewPartSystem`]. fn on_register( &self, - system_registry: &mut SpaceViewSystemRegistry, + system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError>; /// Preferred aspect ratio for the ui tiles of this space view. @@ -159,7 +159,7 @@ impl DynSpaceViewClass for T { fn on_register( &self, - system_registry: &mut SpaceViewSystemRegistry, + system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { self.on_register(system_registry) } diff --git a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs index 8b8c862404f4..654a28826c0f 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs @@ -1,6 +1,6 @@ use crate::{ SpaceViewClass, SpaceViewClassRegistryError, SpaceViewSystemExecutionError, - SpaceViewSystemRegistry, SystemExecutionOutput, ViewQuery, ViewerContext, + SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, ViewerContext, }; use re_data_store::EntityProperties; @@ -24,7 +24,7 @@ impl SpaceViewClass for SpaceViewClassPlaceholder { fn on_register( &self, - _system_registry: &mut SpaceViewSystemRegistry, + _system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { Ok(()) } diff --git a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs index 1746bed7a107..d7b3bd4985ba 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs @@ -1,4 +1,4 @@ -use ahash::HashMap; +use ahash::{HashMap, HashSet}; use crate::{ DynSpaceViewClass, IdentifiedViewSystem, SpaceViewClassIdentifier, ViewContextCollection, @@ -17,43 +17,50 @@ pub enum SpaceViewClassRegistryError { IdentifierAlreadyInUseForContextSystem(&'static str), #[error("A View Part System with identifier {0:?} was already registered.")] - IdentifierAlreadyInUseForViewSystem(&'static str), + IdentifierAlreadyInUseForVisualizer(&'static str), #[error("Space View with class identifier {0:?} was not registered.")] UnknownClassIdentifier(SpaceViewClassIdentifier), } -/// System registry for a space view class. -/// -/// All context & part systems that are registered here will be created and executed every frame -/// for every instance of the space view class this belongs to. -#[derive(Default)] -pub struct SpaceViewSystemRegistry { - contexts: - HashMap Box + Send + Sync>>, - parts: HashMap Box + Send + Sync>>, +/// Utility for registering space view systems, passed on to [`crate::SpaceViewClass::on_register`]. +pub struct SpaceViewSystemRegistrator<'a> { + registry: &'a mut SpaceViewClassRegistry, + identifier: SpaceViewClassIdentifier, + context_systems: HashSet, + visualizers: HashSet, } -impl SpaceViewSystemRegistry { - /// Registers a new [`ViewContextSystem`] type for this space view class that will be created and executed every frame. +impl SpaceViewSystemRegistrator<'_> { + /// Registers a new [`ViewContextSystem`] type for a space view class that will be created and executed every frame. /// - /// It is not allowed to register a given type more than once. + /// It is not allowed to register a given type more than once within the same space view class. + /// Different space view classes may however share the same [`ViewContextSystem`] type. pub fn register_context_system< T: ViewContextSystem + IdentifiedViewSystem + Default + 'static, >( &mut self, ) -> Result<(), SpaceViewClassRegistryError> { - // Name should also not overlap with part systems. - if self.parts.contains_key(&T::identifier()) { + // Name should not overlap with context systems. + if self.registry.visualizers.contains_key(&T::identifier()) { return Err( - SpaceViewClassRegistryError::IdentifierAlreadyInUseForViewSystem( + SpaceViewClassRegistryError::IdentifierAlreadyInUseForVisualizer( T::identifier().as_str(), ), ); } - if let std::collections::hash_map::Entry::Vacant(e) = self.contexts.entry(T::identifier()) { - e.insert(Box::new(|| Box::::default())); + if self.context_systems.insert(T::identifier()) { + self.registry + .context_systems + .entry(T::identifier()) + .or_insert_with(|| SystemTypeRegistryEntry { + factory_method: Box::new(|| Box::::default()), + used_by: Default::default(), + }) + .used_by + .insert(self.identifier); + Ok(()) } else { Err( @@ -64,14 +71,15 @@ impl SpaceViewSystemRegistry { } } - /// Registers a new [`ViewPartSystem`] type for this space view class that will be created and executed every frame. + /// Registers a new [`ViewPartSystem`] type for a space view class that will be created and executed every frame. /// - /// It is not allowed to register a given type more than once. - pub fn register_part_system( + /// It is not allowed to register a given type more than once within the same space view class. + /// Different space view classes may however share the same [`ViewPartSystem`] type. + pub fn register_visualizer( &mut self, ) -> Result<(), SpaceViewClassRegistryError> { - // Name should also not overlap with context systems. - if self.parts.contains_key(&T::identifier()) { + // Name should not overlap with context systems. + if self.registry.context_systems.contains_key(&T::identifier()) { return Err( SpaceViewClassRegistryError::IdentifierAlreadyInUseForContextSystem( T::identifier().as_str(), @@ -79,57 +87,33 @@ impl SpaceViewSystemRegistry { ); } - if let std::collections::hash_map::Entry::Vacant(e) = self.parts.entry(T::identifier()) { - e.insert(Box::new(|| Box::::default())); + if self.visualizers.insert(T::identifier()) { + self.registry + .visualizers + .entry(T::identifier()) + .or_insert_with(|| SystemTypeRegistryEntry { + factory_method: Box::new(|| Box::::default()), + used_by: Default::default(), + }) + .used_by + .insert(self.identifier); + Ok(()) } else { Err( - SpaceViewClassRegistryError::IdentifierAlreadyInUseForViewSystem( + SpaceViewClassRegistryError::IdentifierAlreadyInUseForVisualizer( T::identifier().as_str(), ), ) } } - - pub fn new_context_collection( - &self, - space_view_class_identifier: SpaceViewClassIdentifier, - ) -> ViewContextCollection { - re_tracing::profile_function!(); - - ViewContextCollection { - systems: self - .contexts - .iter() - .map(|(name, factory)| { - let part = factory(); - (*name, part) - }) - .collect(), - space_view_class_identifier, - } - } - - pub fn new_part_collection(&self) -> ViewPartCollection { - re_tracing::profile_function!(); - - ViewPartCollection { - systems: self - .parts - .iter() - .map(|(name, factory)| { - let part = factory(); - (*name, part) - }) - .collect(), - } - } } -/// Entry in [`SpaceViewClassRegistry`] +/// Space view class entry in [`SpaceViewClassRegistry`]. struct SpaceViewClassRegistryEntry { class: Box, - systems: SpaceViewSystemRegistry, + context_systems: HashSet, + visualizers: HashSet, } #[allow(clippy::derivable_impls)] // Clippy gets this one wrong. @@ -137,17 +121,26 @@ impl Default for SpaceViewClassRegistryEntry { fn default() -> Self { Self { class: Box::::default(), - systems: SpaceViewSystemRegistry::default(), + context_systems: Default::default(), + visualizers: Default::default(), } } } +/// System type entry in [`SpaceViewClassRegistry`]. +struct SystemTypeRegistryEntry { + factory_method: Box Box + Send + Sync>, + used_by: HashSet, +} + /// Registry of all known space view types. /// /// Expected to be populated on viewer startup. #[derive(Default)] pub struct SpaceViewClassRegistry { - registry: HashMap, + space_view_classes: HashMap, + visualizers: HashMap>, + context_systems: HashMap>, placeholder: SpaceViewClassRegistryEntry, } @@ -158,15 +151,36 @@ impl SpaceViewClassRegistry { pub fn add_class( &mut self, ) -> Result<(), SpaceViewClassRegistryError> { - let mut entry = SpaceViewClassRegistryEntry { - class: Box::::default(), - systems: SpaceViewSystemRegistry::default(), + let class = Box::::default(); + + let mut registrator = SpaceViewSystemRegistrator { + registry: self, + identifier: class.identifier(), + context_systems: Default::default(), + visualizers: Default::default(), }; - entry.class.on_register(&mut entry.systems)?; + class.on_register(&mut registrator)?; + + let SpaceViewSystemRegistrator { + registry: _, + identifier, + context_systems, + visualizers, + } = registrator; - let identifier = entry.class.identifier(); - if self.registry.insert(identifier, entry).is_some() { + if self + .space_view_classes + .insert( + identifier, + SpaceViewClassRegistryEntry { + class, + context_systems, + visualizers, + }, + ) + .is_some() + { return Err(SpaceViewClassRegistryError::DuplicateClassIdentifier( identifier, )); @@ -180,39 +194,43 @@ impl SpaceViewClassRegistry { &mut self, ) -> Result<(), SpaceViewClassRegistryError> { let identifier: SpaceViewClassIdentifier = T::identifier_str().into(); - if self.registry.remove(&identifier).is_none() { + if self.space_view_classes.remove(&identifier).is_none() { return Err(SpaceViewClassRegistryError::UnknownClassIdentifier( identifier, )); } + self.context_systems.retain(|_, context_system_entry| { + context_system_entry.used_by.remove(&identifier); + !context_system_entry.used_by.is_empty() + }); + + self.visualizers.retain(|_, visualizer_entry| { + visualizer_entry.used_by.remove(&identifier); + !visualizer_entry.used_by.is_empty() + }); + Ok(()) } /// Queries a Space View type by class name, returning `None` if it is not registered. fn get_class(&self, name: &SpaceViewClassIdentifier) -> Option<&dyn DynSpaceViewClass> { - self.registry.get(name).map(|boxed| boxed.class.as_ref()) + self.space_view_classes + .get(name) + .map(|boxed| boxed.class.as_ref()) } /// Returns the user-facing name for the given space view class. /// /// If the class is unknown, returns a placeholder name. pub fn display_name(&self, name: &SpaceViewClassIdentifier) -> &'static str { - self.registry + self.space_view_classes .get(name) .map_or("", |boxed| { boxed.class.display_name() }) } - /// Queries a Space View type's system registry by class name, returning `None` if the class is not registered. - fn get_system_registry( - &self, - name: &SpaceViewClassIdentifier, - ) -> Option<&SpaceViewSystemRegistry> { - self.registry.get(name).map(|boxed| &boxed.systems) - } - /// Queries a Space View type by class name and logs if it fails, returning a placeholder class. pub fn get_class_or_log_error( &self, @@ -226,30 +244,64 @@ impl SpaceViewClassRegistry { } } - /// Queries a Space View's system registry by class name and logs if it fails, returning a placeholder class. - pub fn get_system_registry_or_log_error( + /// Iterates over all registered Space View class types. + pub fn iter_classes(&self) -> impl Iterator { + self.space_view_classes + .values() + .map(|entry| entry.class.as_ref()) + } + + pub fn new_context_collection( &self, - name: &SpaceViewClassIdentifier, - ) -> &SpaceViewSystemRegistry { - if let Some(result) = self.get_system_registry(name) { - result - } else { - re_log::error_once!("Unknown space view class {:?}", name); - &self.placeholder.systems + space_view_class_identifier: SpaceViewClassIdentifier, + ) -> ViewContextCollection { + re_tracing::profile_function!(); + + let Some(class) = self.space_view_classes.get(&space_view_class_identifier) else { + return ViewContextCollection { + systems: Default::default(), + space_view_class_identifier, + }; + }; + + ViewContextCollection { + systems: class + .context_systems + .iter() + .filter_map(|name| { + self.context_systems.get(name).map(|entry| { + let part = (entry.factory_method)(); + (*name, part) + }) + }) + .collect(), + space_view_class_identifier, } } - /// Iterates over all registered Space View class names and their system registries. - pub fn iter_system_registries( + pub fn new_part_collection( &self, - ) -> impl Iterator { - self.registry - .iter() - .map(|(name, entry)| (name, &entry.systems)) - } + space_view_class_identifier: SpaceViewClassIdentifier, + ) -> ViewPartCollection { + re_tracing::profile_function!(); - /// Iterates over all registered Space View class types. - pub fn iter_classes(&self) -> impl Iterator { - self.registry.values().map(|entry| entry.class.as_ref()) + let Some(class) = self.space_view_classes.get(&space_view_class_identifier) else { + return ViewPartCollection { + systems: Default::default(), + }; + }; + + ViewPartCollection { + systems: class + .visualizers + .iter() + .filter_map(|name| { + self.visualizers.get(name).map(|entry| { + let part = (entry.factory_method)(); + (*name, part) + }) + }) + .collect(), + } } } diff --git a/crates/re_viewer_context/src/space_view/view_context_system.rs b/crates/re_viewer_context/src/space_view/view_context_system.rs index cfd728e247f7..c1cfb2a8d31f 100644 --- a/crates/re_viewer_context/src/space_view/view_context_system.rs +++ b/crates/re_viewer_context/src/space_view/view_context_system.rs @@ -19,7 +19,7 @@ pub trait ViewContextSystem: Send + Sync { /// Return an empty vec to specify that the system should never run automatically for any /// specific entities. /// It may still run once per frame as part of the global context if it has been registered to - /// do so, see [`crate::SpaceViewSystemRegistry`]. + /// do so, see [`crate::SpaceViewSystemRegistrator`]. fn compatible_component_sets(&self) -> Vec; /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. diff --git a/crates/re_viewport/src/space_view.rs b/crates/re_viewport/src/space_view.rs index 40bfe88d078e..595ab57ccf2b 100644 --- a/crates/re_viewport/src/space_view.rs +++ b/crates/re_viewport/src/space_view.rs @@ -11,7 +11,7 @@ use re_space_view_time_series::TimeSeriesSpaceView; use re_viewer_context::{ DataQueryId, DataResult, DynSpaceViewClass, PerSystemDataResults, PerSystemEntities, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewHighlights, SpaceViewId, SpaceViewState, - SpaceViewSystemRegistry, StoreContext, SystemExecutionOutput, ViewQuery, ViewerContext, + StoreContext, SystemExecutionOutput, ViewQuery, ViewerContext, }; use crate::system_execution::create_and_run_space_view_systems; @@ -175,13 +175,6 @@ impl SpaceViewBlueprint { space_view_class_registry.get_class_or_log_error(&self.class_identifier) } - pub fn class_system_registry<'a>( - &self, - space_view_class_registry: &'a re_viewer_context::SpaceViewClassRegistry, - ) -> &'a SpaceViewSystemRegistry { - space_view_class_registry.get_system_registry_or_log_error(&self.class_identifier) - } - pub fn on_frame_start(&mut self, ctx: &ViewerContext<'_>, view_state: &mut dyn SpaceViewState) { while ScreenshotProcessor::next_readback_result( ctx.render_ctx, @@ -287,7 +280,6 @@ impl SpaceViewBlueprint { }); } - let system_registry = self.class_system_registry(ctx.space_view_class_registry); let query = re_viewer_context::ViewQuery { space_view_id: self.id, space_origin: &self.space_origin, @@ -297,8 +289,7 @@ impl SpaceViewBlueprint { highlights, }; - let system_output = - create_and_run_space_view_systems(ctx, class.identifier(), system_registry, &query); + let system_output = create_and_run_space_view_systems(ctx, class.identifier(), &query); (query, system_output) } diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 4df0f1d8d285..c0146d1711d9 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -389,7 +389,7 @@ fn create_entity_add_info( tree.visit_children_recursively(&mut |entity_path| { let heuristic_context_per_entity = heuristic_context_per_entity.get(entity_path).copied().unwrap_or_default(); let can_add: CanAddToSpaceView = - if is_entity_processed_by_class(ctx, space_view.class_identifier(), entity_path, heuristic_context_per_entity, &ctx.current_query()) { + if is_entity_processed_by_class(ctx, *space_view.class_identifier(), entity_path, heuristic_context_per_entity, &ctx.current_query()) { match spaces_info.is_reachable_by_transform(entity_path, &space_view.space_origin) { Ok(()) => CanAddToSpaceView::Compatible { already_added: query_result.contains_any(entity_path), diff --git a/crates/re_viewport/src/space_view_heuristics.rs b/crates/re_viewport/src/space_view_heuristics.rs index 79adb089dcab..e98678ab9d7d 100644 --- a/crates/re_viewport/src/space_view_heuristics.rs +++ b/crates/re_viewport/src/space_view_heuristics.rs @@ -80,13 +80,16 @@ pub fn all_possible_space_views( // should not influence the heuristics. let entities_used_by_any_part_system_of_class: IntMap<_, _> = ctx .space_view_class_registry - .iter_system_registries() - .map(|(class_identifier, system_registry)| { - let parts = system_registry.new_part_collection(); + .iter_classes() + .map(|class| { + let class_identifier = class.identifier(); + let parts = ctx + .space_view_class_registry + .new_part_collection(class_identifier); ( - *class_identifier, + class_identifier, entities_per_system_per_class - .get(class_identifier) + .get(&class_identifier) .unwrap_or(&empty_entities_per_system) .iter() .filter(|(system, _)| parts.get_by_identifier(**system).is_ok()) @@ -457,20 +460,17 @@ pub fn reachable_entities_from_root( // TODO(andreas): Still used in a bunch of places. Should instead use the global `EntitiesPerSystemPerClass` list. pub fn is_entity_processed_by_class( ctx: &ViewerContext<'_>, - class: &SpaceViewClassIdentifier, + class: SpaceViewClassIdentifier, ent_path: &EntityPath, heuristic_ctx: HeuristicFilterContext, query: &LatestAtQuery, ) -> bool { - let parts = ctx - .space_view_class_registry - .get_system_registry_or_log_error(class) - .new_part_collection(); + let parts = ctx.space_view_class_registry.new_part_collection(class); is_entity_processed_by_part_collection( ctx.store_db.store(), &parts, ent_path, - heuristic_ctx.with_class(*class), + heuristic_ctx.with_class(class), query, ) } @@ -556,13 +556,14 @@ pub fn identify_entities_per_system_per_class( SpaceViewClassIdentifier, (ViewContextCollection, ViewPartCollection), > = space_view_class_registry - .iter_system_registries() - .map(|(class_identifier, entry)| { + .iter_classes() + .map(|class| { + let class_identifier = class.identifier(); ( - *class_identifier, + class_identifier, ( - entry.new_context_collection(*class_identifier), - entry.new_part_collection(), + space_view_class_registry.new_context_collection(class_identifier), + space_view_class_registry.new_part_collection(class_identifier), ), ) }) diff --git a/crates/re_viewport/src/system_execution.rs b/crates/re_viewport/src/system_execution.rs index 05a8d1a3a35f..72c9300ac867 100644 --- a/crates/re_viewport/src/system_execution.rs +++ b/crates/re_viewport/src/system_execution.rs @@ -4,23 +4,23 @@ use ahash::HashMap; use rayon::prelude::*; use re_viewer_context::{ - SpaceViewClassIdentifier, SpaceViewId, SpaceViewSystemRegistry, SystemExecutionOutput, - ViewQuery, ViewerContext, + SpaceViewClassIdentifier, SpaceViewId, SystemExecutionOutput, ViewQuery, ViewerContext, }; use crate::{space_view_highlights::highlights_for_space_view, SpaceViewBlueprint}; pub fn create_and_run_space_view_systems( ctx: &ViewerContext<'_>, - space_view_identifier: SpaceViewClassIdentifier, - systems: &SpaceViewSystemRegistry, + space_view_class: SpaceViewClassIdentifier, query: &ViewQuery<'_>, ) -> SystemExecutionOutput { - re_tracing::profile_function!(space_view_identifier.as_str()); + re_tracing::profile_function!(space_view_class.as_str()); let context_systems = { re_tracing::profile_wait!("ViewContextSystem::execute"); - let mut context_systems = systems.new_context_collection(space_view_identifier); + let mut context_systems = ctx + .space_view_class_registry + .new_context_collection(space_view_class); context_systems .systems .par_iter_mut() @@ -32,7 +32,9 @@ pub fn create_and_run_space_view_systems( }; re_tracing::profile_wait!("ViewPartSystem::execute"); - let mut view_systems = systems.new_part_collection(); + let mut view_systems = ctx + .space_view_class_registry + .new_part_collection(space_view_class); let draw_data = view_systems .systems .par_iter_mut() diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 1be883284722..56f240736737 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -7,7 +7,7 @@ use re_viewer::external::{ re_viewer_context::{ HoverHighlight, Item, SelectionHighlight, SpaceViewClass, SpaceViewClassLayoutPriority, SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, SpaceViewSystemExecutionError, - SpaceViewSystemRegistry, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, + SpaceViewSystemRegistrator, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, }, }; @@ -81,9 +81,9 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { /// Register all systems (contexts & parts) that the space view needs. fn on_register( &self, - system_registry: &mut SpaceViewSystemRegistry, + system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_part_system::() + system_registry.register_visualizer::() } fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option {