use once_cell::sync::OnceCell;
use nohash_hasher::{IntMap, IntSet};
use re_chunk_store::{
ChunkStore, ChunkStoreDiffKind, ChunkStoreEvent, ChunkStoreSubscriberHandle,
PerStoreChunkSubscriber,
};
use re_log_types::{EntityPath, EntityPathHash, StoreId};
use re_types::{Component as _, ComponentName};
#[derive(Default, Clone)]
pub struct PotentialTransformComponentSet {
pub transform3d: IntSet<ComponentName>,
pub pose3d: IntSet<ComponentName>,
pub pinhole: bool,
pub disconnected_space: bool,
}
pub struct TransformComponentTrackerStoreSubscriber {
transform_components: IntSet<ComponentName>,
pose_components: IntSet<ComponentName>,
components_per_entity: IntMap<EntityPathHash, PotentialTransformComponentSet>,
}
impl Default for TransformComponentTrackerStoreSubscriber {
#[inline]
fn default() -> Self {
use re_types::Archetype as _;
Self {
transform_components: re_types::archetypes::Transform3D::all_components()
.iter()
.map(|descr| descr.component_name)
.collect(),
pose_components: re_types::archetypes::InstancePoses3D::all_components()
.iter()
.map(|descr| descr.component_name)
.collect(),
components_per_entity: Default::default(),
}
}
}
impl TransformComponentTrackerStoreSubscriber {
pub fn subscription_handle() -> ChunkStoreSubscriberHandle {
static SUBSCRIPTION: OnceCell<ChunkStoreSubscriberHandle> = OnceCell::new();
*SUBSCRIPTION.get_or_init(ChunkStore::register_per_store_subscriber::<Self>)
}
#[inline]
pub fn access<T>(store_id: &StoreId, f: impl FnOnce(&Self) -> T) -> Option<T> {
ChunkStore::with_per_store_subscriber_once(Self::subscription_handle(), store_id, f)
}
pub fn potential_transform_components(
&self,
entity_path: &EntityPath,
) -> Option<&PotentialTransformComponentSet> {
self.components_per_entity.get(&entity_path.hash())
}
}
impl PerStoreChunkSubscriber for TransformComponentTrackerStoreSubscriber {
#[inline]
fn name() -> String {
"rerun.store_subscriber.TransformComponentTracker".into()
}
fn on_events<'a>(&mut self, events: impl Iterator<Item = &'a ChunkStoreEvent>) {
re_tracing::profile_function!();
for event in events
.filter(|e| e.kind == ChunkStoreDiffKind::Addition)
{
let entity_path_hash = event.chunk.entity_path().hash();
let contains_non_zero_component_array = |component_name| {
event
.chunk
.components()
.get(&component_name)
.map_or(false, |per_desc| {
per_desc
.values()
.any(|list_array| list_array.offsets().lengths().any(|len| len > 0))
})
};
for component_name in event.chunk.component_names() {
if self.transform_components.contains(&component_name)
&& contains_non_zero_component_array(component_name)
{
self.components_per_entity
.entry(entity_path_hash)
.or_default()
.transform3d
.insert(component_name);
}
if self.pose_components.contains(&component_name)
&& contains_non_zero_component_array(component_name)
{
self.components_per_entity
.entry(entity_path_hash)
.or_default()
.pose3d
.insert(component_name);
}
if component_name == re_types::components::PinholeProjection::name()
&& contains_non_zero_component_array(component_name)
{
self.components_per_entity
.entry(entity_path_hash)
.or_default()
.pinhole = true;
}
#[allow(deprecated)]
if component_name == re_types::components::DisconnectedSpace::name()
&& contains_non_zero_component_array(component_name)
{
self.components_per_entity
.entry(entity_path_hash)
.or_default()
.disconnected_space = true;
}
}
}
}
}