use nohash_hasher::IntSet;
use re_log_types::EntityPath;
use re_sdk_types::ViewClassIdentifier;
use re_viewer_context::{ViewClass as _, ViewerContext};
use crate::view_kind::SpatialViewKind;
use crate::visualizers::SpatialViewVisualizerData;
use crate::{SpatialView2D, SpatialView3D};
pub struct IndicatedVisualizableEntities {
pub indicated_entities: IntSet<EntityPath>,
pub excluded_entities: Vec<EntityPath>,
}
impl IndicatedVisualizableEntities {
pub fn new(
ctx: &ViewerContext<'_>,
view_class_identifier: ViewClassIdentifier,
visualizer_kind: SpatialViewKind,
include_entity: &dyn Fn(&EntityPath) -> bool,
indicate_extra: impl FnOnce(&mut IntSet<EntityPath>),
) -> Self {
let mut indicated_entities = default_visualized_entities_for_visualizer_kind(
ctx,
view_class_identifier,
visualizer_kind,
include_entity,
);
indicate_extra(&mut indicated_entities);
let excluded_entities = default_excluded_entities_for_visualizer_kind(
ctx,
visualizer_kind,
&indicated_entities,
);
Self {
indicated_entities,
excluded_entities,
}
}
}
fn default_visualized_entities_for_visualizer_kind(
ctx: &ViewerContext<'_>,
view_class_identifier: ViewClassIdentifier,
visualizer_kind: SpatialViewKind,
include_entity: &dyn Fn(&EntityPath) -> bool,
) -> IntSet<EntityPath> {
re_tracing::profile_function!();
ctx.view_class_registry()
.new_visualizer_collection(view_class_identifier)
.iter_with_identifiers()
.filter_map(|(id, visualizer)| {
let data = visualizer
.data()?
.downcast_ref::<SpatialViewVisualizerData>()?;
if data.preferred_view_kind == Some(visualizer_kind) {
let indicator_matching = ctx.indicated_entities_per_visualizer.get(&id)?;
let visualizable = ctx.visualizable_entities_per_visualizer.get(&id)?;
Some(
indicator_matching
.iter()
.filter(|e| visualizable.contains_key(e)),
)
} else {
None
}
})
.flatten()
.filter(|e| include_entity(e))
.cloned()
.collect()
}
fn default_excluded_entities_for_visualizer_kind(
ctx: &ViewerContext<'_>,
visualizer_kind: SpatialViewKind,
included_entities: &IntSet<EntityPath>,
) -> Vec<EntityPath> {
let exclude_kind = match visualizer_kind {
SpatialViewKind::TwoD => SpatialViewKind::ThreeD,
SpatialViewKind::ThreeD => SpatialViewKind::TwoD,
};
let included_ancestors = included_entities
.iter()
.flat_map(|e| {
let mut e = Some(e.clone());
std::iter::from_fn(move || {
let item = e.take();
e = item.as_ref().and_then(|e| e.parent());
item
})
})
.collect::<IntSet<_>>();
ctx.view_class_registry()
.new_visualizer_collection(match exclude_kind {
SpatialViewKind::TwoD => SpatialView2D::identifier(),
SpatialViewKind::ThreeD => SpatialView3D::identifier(),
})
.iter_with_identifiers()
.filter_map(|(id, visualizer)| {
let data = visualizer
.data()?
.downcast_ref::<SpatialViewVisualizerData>()?;
if data
.preferred_view_kind
.is_some_and(|vk| vk != visualizer_kind)
{
let indicator_matching = ctx.indicated_entities_per_visualizer.get(&id)?;
Some(indicator_matching.iter())
} else {
None
}
})
.flatten()
.filter(|e| !included_ancestors.contains(e))
.filter_map(|e| {
let mut highest = None;
let mut current = e.clone();
loop {
let Some(p) = current.parent() else {
if highest.is_none() {
highest = Some(current.clone());
}
break;
};
if included_entities.contains(&p) {
return None;
}
if highest.is_none() && included_ancestors.contains(&p) {
highest = Some(current.clone());
}
current = p.clone();
}
highest
})
.collect()
}