From 024f70d14511c279146397a19cbc6e201cf1e098 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 20 Dec 2023 18:43:56 +0100 Subject: [PATCH 1/5] Introduce VisualizerAdditionalApplicabilityFilter for custom applicability filtering --- crates/re_viewer_context/src/lib.rs | 1 + .../re_viewer_context/src/space_view/mod.rs | 1 + .../src/space_view/view_part_system.rs | 8 ++++ .../visualizer_entity_subscriber.rs | 46 +++++++++++++++++-- 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index da3045fd3afb..947848723537 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -49,6 +49,7 @@ pub use space_view::{ SpaceViewOutlineMasks, SpaceViewState, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, ViewContextCollection, ViewContextSystem, ViewPartCollection, ViewPartSystem, ViewQuery, ViewSystemIdentifier, + VisualizerAdditionalApplicabilityFilter, }; pub use store_context::StoreContext; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 2063e4efc492..48e143a1c83e 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -33,6 +33,7 @@ pub use view_part_system::{ default_heuristic_filter, HeuristicFilterContext, ViewPartCollection, ViewPartSystem, }; pub use view_query::{DataResult, PerSystemDataResults, ViewQuery}; +pub use visualizer_entity_subscriber::VisualizerAdditionalApplicabilityFilter; // --------------------------------------------------------------------------- diff --git a/crates/re_viewer_context/src/space_view/view_part_system.rs b/crates/re_viewer_context/src/space_view/view_part_system.rs index 408a65597ddd..296910365fe0 100644 --- a/crates/re_viewer_context/src/space_view/view_part_system.rs +++ b/crates/re_viewer_context/src/space_view/view_part_system.rs @@ -7,6 +7,7 @@ use re_types::ComponentNameSet; use crate::{ IdentifiedViewSystem, SpaceViewClassIdentifier, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewSystemIdentifier, ViewerContext, + VisualizerAdditionalApplicabilityFilter, }; /// This is additional context made available to the `heuristic_filter`. @@ -81,6 +82,13 @@ pub trait ViewPartSystem: Send + Sync + 'static { default_heuristic_filter(entity_components, &self.indicator_components()) } + /// Additional filter for applicability. + /// + /// If none is specified, applicability is solely determined by required components. + fn applicability_filter(&self) -> Option> { + None + } + /// Queries the data store and performs data conversions to make it ready for display. /// /// Mustn't query any data outside of the archetype. diff --git a/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs b/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs index 49b919c0d900..164ea7870e94 100644 --- a/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs +++ b/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs @@ -28,17 +28,45 @@ pub struct VisualizerEntitySubscriber { required_components_indices: IntMap, per_store_mapping: HashMap, + + /// Additional filter for applicability. + applicability_filter: Box, +} + +/// Additional filter for applicability on top of the default check for required components. +pub trait VisualizerAdditionalApplicabilityFilter: Send + Sync { + /// Updates the internal applicability filter state based on the given events. + /// + /// Called for every update no matter whether the entity is already has all required components or not. + /// + /// Returns true if the entity is now applicable to the visualizer, false otherwise. + /// Once a entity passes this filter, it can never go back to being filtered out. + /// **This implies that the filter does not _need_ to be stateful.** + /// It is perfectly fine to return `true` only if something in the diff is regarded as applicable and false otherwise. + /// (However, if necessary, the applicability filter *can* keep track of state.) + fn update_applicability(&mut self, _event: &re_arrow_store::StoreEvent) -> bool; +} + +struct DefaultVisualizerApplicabilityFilter; + +impl VisualizerAdditionalApplicabilityFilter for DefaultVisualizerApplicabilityFilter { + #[inline] + fn update_applicability(&mut self, _event: &re_arrow_store::StoreEvent) -> bool { + true + } } #[derive(Default)] struct VisualizerEntityMapping { /// For each entity, which of the required components are present. /// + /// Last bit is used for the applicability filter. + /// /// In order of `required_components`. /// If all bits are set, the entity is applicable to the visualizer. // TODO(andreas): We could just limit the number of required components to 32 or 64 and // then use a single u32/u64 as a bitmap. - required_component_bitmap_per_entity: IntMap, + required_component_and_filter_bitmap_per_entity: IntMap, /// Which entities the visualizer can be applied to. /// @@ -59,6 +87,9 @@ impl VisualizerEntitySubscriber { .map(|(i, name)| (name, i)) .collect(), per_store_mapping: Default::default(), + applicability_filter: visualizer + .applicability_filter() + .unwrap_or_else(|| Box::new(DefaultVisualizerApplicabilityFilter)), } } @@ -102,10 +133,10 @@ impl StoreSubscriber for VisualizerEntitySubscriber { .or_default(); let required_components_bitmap = store_mapping - .required_component_bitmap_per_entity + .required_component_and_filter_bitmap_per_entity .entry(event.diff.entity_path.hash()) .or_insert_with(|| { - BitVec::from_elem(self.required_components_indices.len(), false) + BitVec::from_elem(self.required_components_indices.len() + 1, false) }); if required_components_bitmap.all() { @@ -119,6 +150,15 @@ impl StoreSubscriber for VisualizerEntitySubscriber { } } + let bit_index_for_filter = self.required_components_indices.len(); + let custom_filter = required_components_bitmap[bit_index_for_filter]; + if !custom_filter { + required_components_bitmap.set( + bit_index_for_filter, + self.applicability_filter.update_applicability(event), + ); + } + if required_components_bitmap.all() { re_log::debug!( "Entity {:?} in store {:?} is now applicable to visualizer {:?}", From d1de3385a848feb1ca428a6f176b530b872e121e Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 20 Dec 2023 20:14:17 +0100 Subject: [PATCH 2/5] use new visualizer entity filter for barchart, tensor and image visualizers --- .../src/view_part_system.rs | 43 ++++++++----------- .../re_space_view_spatial/src/parts/images.rs | 40 +++++++++++------ .../src/view_part_system.rs | 42 ++++++++---------- 3 files changed, 63 insertions(+), 62 deletions(-) diff --git a/crates/re_space_view_bar_chart/src/view_part_system.rs b/crates/re_space_view_bar_chart/src/view_part_system.rs index 90b5bf2b7e27..eac8905073e4 100644 --- a/crates/re_space_view_bar_chart/src/view_part_system.rs +++ b/crates/re_space_view_bar_chart/src/view_part_system.rs @@ -6,11 +6,11 @@ use re_types::{ archetypes::{BarChart, Tensor}, components::Color, datatypes::TensorData, - Archetype, ComponentNameSet, + Archetype, ComponentNameSet, Loggable, }; use re_viewer_context::{ - default_heuristic_filter, HeuristicFilterContext, IdentifiedViewSystem, - SpaceViewSystemExecutionError, ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext, + IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewPartSystem, + ViewQuery, ViewerContext, VisualizerAdditionalApplicabilityFilter, }; /// A bar chart system, with everything needed to render it. @@ -25,6 +25,19 @@ impl IdentifiedViewSystem for BarChartViewPartSystem { } } +struct BarChartVisualizerEntityFilter; + +impl VisualizerAdditionalApplicabilityFilter for BarChartVisualizerEntityFilter { + fn update_applicability(&mut self, event: &re_arrow_store::StoreEvent) -> bool { + event.diff.cells.iter().any(|(component_name, cell)| { + component_name == &re_types::components::TensorData::name() + && re_types::components::TensorData::from_arrow(cell.as_arrow_ref()) + .map(|tensors| tensors.iter().any(|tensor| tensor.is_vector())) + .unwrap_or(false) + }) + } +} + impl ViewPartSystem for BarChartViewPartSystem { fn required_components(&self) -> ComponentNameSet { BarChart::required_components() @@ -42,28 +55,8 @@ impl ViewPartSystem for BarChartViewPartSystem { .collect() } - fn heuristic_filter( - &self, - store: &re_arrow_store::DataStore, - ent_path: &EntityPath, - _ctx: HeuristicFilterContext, - query: &LatestAtQuery, - entity_components: &ComponentNameSet, - ) -> bool { - if !default_heuristic_filter(entity_components, &self.indicator_components()) { - return false; - } - - // NOTE: We want to make sure we query at the right time, otherwise we might take into - // account a `Clear()` that actually only applies into the future, and then - // `is_vector` will righfully fail because of the empty tensor. - if let Some(tensor) = - store.query_latest_component::(ent_path, query) - { - tensor.is_vector() - } else { - false - } + fn applicability_filter(&self) -> Option> { + Some(Box::new(BarChartVisualizerEntityFilter)) } fn execute( diff --git a/crates/re_space_view_spatial/src/parts/images.rs b/crates/re_space_view_spatial/src/parts/images.rs index 6daaa56a0c8f..6b63b2da46f8 100644 --- a/crates/re_space_view_spatial/src/parts/images.rs +++ b/crates/re_space_view_spatial/src/parts/images.rs @@ -16,12 +16,12 @@ use re_types::{ archetypes::{DepthImage, Image, SegmentationImage}, components::{Color, DrawOrder, TensorData, ViewCoordinates}, tensor_data::{DecodedTensor, TensorDataMeaning}, - Archetype as _, ComponentNameSet, + Archetype as _, ComponentNameSet, Loggable as _, }; use re_viewer_context::{ default_heuristic_filter, gpu_bridge, DefaultColor, HeuristicFilterContext, SpaceViewClass, SpaceViewSystemExecutionError, TensorDecodeCache, TensorStatsCache, ViewPartSystem, ViewQuery, - ViewerContext, + ViewerContext, VisualizerAdditionalApplicabilityFilter, }; use re_viewer_context::{IdentifiedViewSystem, ViewContextCollection}; @@ -643,6 +643,23 @@ impl IdentifiedViewSystem for ImagesPart { } } +struct ImageVisualizerEntityFilter; + +impl VisualizerAdditionalApplicabilityFilter for ImageVisualizerEntityFilter { + fn update_applicability(&mut self, event: &re_arrow_store::StoreEvent) -> bool { + event.diff.cells.iter().any(|(component_name, cell)| { + component_name == &re_types::components::TensorData::name() + && re_types::components::TensorData::from_arrow(cell.as_arrow_ref()) + .map(|tensors| { + tensors + .iter() + .any(|tensor| tensor.is_shaped_like_an_image()) + }) + .unwrap_or(false) + }) + } +} + impl ViewPartSystem for ImagesPart { fn required_components(&self) -> ComponentNameSet { let image: ComponentNameSet = Image::required_components() @@ -677,12 +694,16 @@ impl ViewPartSystem for ImagesPart { .collect() } + fn applicability_filter(&self) -> Option> { + Some(Box::new(ImageVisualizerEntityFilter)) + } + fn heuristic_filter( &self, - store: &re_arrow_store::DataStore, - ent_path: &EntityPath, + _store: &re_arrow_store::DataStore, + _ent_path: &EntityPath, ctx: HeuristicFilterContext, - query: &LatestAtQuery, + _query: &LatestAtQuery, entity_components: &ComponentNameSet, ) -> bool { if !default_heuristic_filter(entity_components, &self.indicator_components()) { @@ -697,14 +718,7 @@ impl ViewPartSystem for ImagesPart { return false; } - // NOTE: We want to make sure we query at the right time, otherwise we might take into - // account a `Clear()` that actually only applies into the future, and then - // `is_shaped_like_an_image` will righfully fail because of the empty tensor. - if let Some(tensor) = store.query_latest_component::(ent_path, query) { - tensor.is_shaped_like_an_image() - } else { - false - } + true } fn execute( diff --git a/crates/re_space_view_tensor/src/view_part_system.rs b/crates/re_space_view_tensor/src/view_part_system.rs index 0ecec2745fa5..dec23295ca99 100644 --- a/crates/re_space_view_tensor/src/view_part_system.rs +++ b/crates/re_space_view_tensor/src/view_part_system.rs @@ -3,12 +3,11 @@ use re_data_store::EntityPath; use re_log_types::RowId; use re_types::{ archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor, Archetype, - ComponentNameSet, + ComponentNameSet, Loggable as _, }; use re_viewer_context::{ - default_heuristic_filter, HeuristicFilterContext, IdentifiedViewSystem, - SpaceViewSystemExecutionError, TensorDecodeCache, ViewContextCollection, ViewPartSystem, - ViewQuery, ViewerContext, + IdentifiedViewSystem, SpaceViewSystemExecutionError, TensorDecodeCache, ViewContextCollection, + ViewPartSystem, ViewQuery, ViewerContext, VisualizerAdditionalApplicabilityFilter, }; #[derive(Default)] @@ -22,6 +21,19 @@ impl IdentifiedViewSystem for TensorSystem { } } +struct TensorVisualizerEntityFilter; + +impl VisualizerAdditionalApplicabilityFilter for TensorVisualizerEntityFilter { + fn update_applicability(&mut self, event: &re_arrow_store::StoreEvent) -> bool { + event.diff.cells.iter().any(|(component_name, cell)| { + component_name == &re_types::components::TensorData::name() + && re_types::components::TensorData::from_arrow(cell.as_arrow_ref()) + .map(|tensors| tensors.iter().any(|tensor| !tensor.is_vector())) + .unwrap_or(false) + }) + } +} + impl ViewPartSystem for TensorSystem { fn required_components(&self) -> ComponentNameSet { Tensor::required_components() @@ -34,26 +46,8 @@ impl ViewPartSystem for TensorSystem { std::iter::once(Tensor::indicator().name()).collect() } - fn heuristic_filter( - &self, - store: &re_arrow_store::DataStore, - ent_path: &EntityPath, - _ctx: HeuristicFilterContext, - query: &LatestAtQuery, - entity_components: &ComponentNameSet, - ) -> bool { - if !default_heuristic_filter(entity_components, &self.indicator_components()) { - return false; - } - - // The tensor view can't display anything with less than two dimensions. - if let Some(tensor) = - store.query_latest_component::(ent_path, query) - { - !tensor.is_vector() - } else { - false - } + fn applicability_filter(&self) -> Option> { + Some(Box::new(TensorVisualizerEntityFilter)) } fn execute( From c94b9a66c393014000e5ac858746b8ef33a3312d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 20 Dec 2023 20:36:53 +0100 Subject: [PATCH 3/5] doc improvement --- .../src/space_view/visualizer_entity_subscriber.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs b/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs index 164ea7870e94..677bd0710ba2 100644 --- a/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs +++ b/crates/re_viewer_context/src/space_view/visualizer_entity_subscriber.rs @@ -39,7 +39,7 @@ pub trait VisualizerAdditionalApplicabilityFilter: Send + Sync { /// /// Called for every update no matter whether the entity is already has all required components or not. /// - /// Returns true if the entity is now applicable to the visualizer, false otherwise. + /// Returns true if the entity changed in the event is now applicable to the visualizer, false otherwise. /// Once a entity passes this filter, it can never go back to being filtered out. /// **This implies that the filter does not _need_ to be stateful.** /// It is perfectly fine to return `true` only if something in the diff is regarded as applicable and false otherwise. From 08bbe1bfd01191dad78fdd044a7ac68f53f329b2 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 21 Dec 2023 11:11:31 +0100 Subject: [PATCH 4/5] diff_component_filter utility --- Cargo.lock | 1 + crates/re_space_view/src/lib.rs | 19 +++++++++++++++++++ .../src/view_part_system.rs | 10 ++++------ .../re_space_view_spatial/src/parts/images.rs | 14 ++++---------- crates/re_space_view_tensor/Cargo.toml | 1 + .../src/view_part_system.rs | 10 ++++------ 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fab880b3ac27..5b492c665e77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5036,6 +5036,7 @@ dependencies = [ "re_log", "re_log_types", "re_renderer", + "re_space_view", "re_tracing", "re_types", "re_ui", diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 06724825d8e4..70b3aaad6e22 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -13,3 +13,22 @@ pub use data_query::{DataQuery, EntityOverrideContext, PropertyResolver}; pub use data_query_blueprint::DataQueryBlueprint; pub use screenshot::ScreenshotMode; pub use unreachable_transform_reason::UnreachableTransformReason; + +// ----------- + +use re_data_store::external::re_arrow_store; + +/// Utility for implementing [`VisualizerAdditionalApplicabilityFilter`] using on the properties of a concrete component. +#[inline] +pub fn diff_component_filter( + event: &re_arrow_store::StoreEvent, + filter: impl Fn(&T) -> bool, +) -> bool { + let filter = &filter; + event.diff.cells.iter().any(|(component_name, cell)| { + component_name == &T::name() + && T::from_arrow(cell.as_arrow_ref()) + .map(|components| components.iter().any(filter)) + .unwrap_or(false) + }) +} diff --git a/crates/re_space_view_bar_chart/src/view_part_system.rs b/crates/re_space_view_bar_chart/src/view_part_system.rs index eac8905073e4..929e63a425b4 100644 --- a/crates/re_space_view_bar_chart/src/view_part_system.rs +++ b/crates/re_space_view_bar_chart/src/view_part_system.rs @@ -2,11 +2,12 @@ use std::collections::BTreeMap; use re_arrow_store::LatestAtQuery; use re_data_store::EntityPath; +use re_space_view::diff_component_filter; use re_types::{ archetypes::{BarChart, Tensor}, components::Color, datatypes::TensorData, - Archetype, ComponentNameSet, Loggable, + Archetype, ComponentNameSet, }; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewPartSystem, @@ -29,11 +30,8 @@ struct BarChartVisualizerEntityFilter; impl VisualizerAdditionalApplicabilityFilter for BarChartVisualizerEntityFilter { fn update_applicability(&mut self, event: &re_arrow_store::StoreEvent) -> bool { - event.diff.cells.iter().any(|(component_name, cell)| { - component_name == &re_types::components::TensorData::name() - && re_types::components::TensorData::from_arrow(cell.as_arrow_ref()) - .map(|tensors| tensors.iter().any(|tensor| tensor.is_vector())) - .unwrap_or(false) + diff_component_filter(event, |tensor: &re_types::components::TensorData| { + tensor.is_vector() }) } } diff --git a/crates/re_space_view_spatial/src/parts/images.rs b/crates/re_space_view_spatial/src/parts/images.rs index 6b63b2da46f8..af200ed56fcd 100644 --- a/crates/re_space_view_spatial/src/parts/images.rs +++ b/crates/re_space_view_spatial/src/parts/images.rs @@ -12,11 +12,12 @@ use re_renderer::{ renderer::{DepthCloud, DepthClouds, RectangleOptions, TexturedRect}, Colormap, }; +use re_space_view::diff_component_filter; use re_types::{ archetypes::{DepthImage, Image, SegmentationImage}, components::{Color, DrawOrder, TensorData, ViewCoordinates}, tensor_data::{DecodedTensor, TensorDataMeaning}, - Archetype as _, ComponentNameSet, Loggable as _, + Archetype as _, ComponentNameSet, }; use re_viewer_context::{ default_heuristic_filter, gpu_bridge, DefaultColor, HeuristicFilterContext, SpaceViewClass, @@ -647,15 +648,8 @@ struct ImageVisualizerEntityFilter; impl VisualizerAdditionalApplicabilityFilter for ImageVisualizerEntityFilter { fn update_applicability(&mut self, event: &re_arrow_store::StoreEvent) -> bool { - event.diff.cells.iter().any(|(component_name, cell)| { - component_name == &re_types::components::TensorData::name() - && re_types::components::TensorData::from_arrow(cell.as_arrow_ref()) - .map(|tensors| { - tensors - .iter() - .any(|tensor| tensor.is_shaped_like_an_image()) - }) - .unwrap_or(false) + diff_component_filter(event, |tensor: &re_types::components::TensorData| { + tensor.is_shaped_like_an_image() }) } } diff --git a/crates/re_space_view_tensor/Cargo.toml b/crates/re_space_view_tensor/Cargo.toml index 0fc8aa55d132..929ce8f92f46 100644 --- a/crates/re_space_view_tensor/Cargo.toml +++ b/crates/re_space_view_tensor/Cargo.toml @@ -22,6 +22,7 @@ re_data_ui.workspace = true re_log_types.workspace = true re_log.workspace = true re_renderer.workspace = true +re_space_view.workspace = true re_tracing.workspace = true re_types.workspace = true re_ui.workspace = true diff --git a/crates/re_space_view_tensor/src/view_part_system.rs b/crates/re_space_view_tensor/src/view_part_system.rs index dec23295ca99..0a9331a3c087 100644 --- a/crates/re_space_view_tensor/src/view_part_system.rs +++ b/crates/re_space_view_tensor/src/view_part_system.rs @@ -1,9 +1,10 @@ use re_arrow_store::{LatestAtQuery, VersionedComponent}; use re_data_store::EntityPath; use re_log_types::RowId; +use re_space_view::diff_component_filter; use re_types::{ archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor, Archetype, - ComponentNameSet, Loggable as _, + ComponentNameSet, }; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, TensorDecodeCache, ViewContextCollection, @@ -25,11 +26,8 @@ struct TensorVisualizerEntityFilter; impl VisualizerAdditionalApplicabilityFilter for TensorVisualizerEntityFilter { fn update_applicability(&mut self, event: &re_arrow_store::StoreEvent) -> bool { - event.diff.cells.iter().any(|(component_name, cell)| { - component_name == &re_types::components::TensorData::name() - && re_types::components::TensorData::from_arrow(cell.as_arrow_ref()) - .map(|tensors| tensors.iter().any(|tensor| !tensor.is_vector())) - .unwrap_or(false) + diff_component_filter(event, |tensor: &re_types::components::TensorData| { + !tensor.is_vector() }) } } From a5b72a18a7c05938ec66e510aea455fc42b3608b Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 21 Dec 2023 11:30:46 +0100 Subject: [PATCH 5/5] doc link fix --- crates/re_space_view/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 70b3aaad6e22..5369feb3fe47 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -18,7 +18,7 @@ pub use unreachable_transform_reason::UnreachableTransformReason; use re_data_store::external::re_arrow_store; -/// Utility for implementing [`VisualizerAdditionalApplicabilityFilter`] using on the properties of a concrete component. +/// Utility for implementing [`re_viewer_context::VisualizerAdditionalApplicabilityFilter`] using on the properties of a concrete component. #[inline] pub fn diff_component_filter( event: &re_arrow_store::StoreEvent,