use std::collections::BTreeMap;
use nohash_hasher::IntSet;
use re_chunk_store::MissingChunkReporter;
use re_log_types::EntityPath;
use re_sdk_types::ViewClassIdentifier;
use vec1::Vec1;
use super::ViewContext;
use crate::{
IndicatedEntities, PerVisualizerType, PerVisualizerTypeInViewClass, QueryRange,
RecommendedMappings, SystemExecutionOutput, ViewClassRegistryError, ViewId, ViewQuery,
ViewSpawnHeuristics, ViewSystemExecutionError, ViewSystemIdentifier, ViewSystemRegistrator,
ViewerContext, VisualizableEntities,
};
#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Ord, Eq)]
pub enum ViewClassLayoutPriority {
Low,
#[default]
Medium,
High,
}
pub struct RecommendedVisualizers(
).
pub BTreeMap<ViewSystemIdentifier, Vec1<RecommendedMappings>>,
);
impl RecommendedVisualizers {
pub fn empty() -> Self {
Self(Default::default())
}
pub fn default(visualizer: ViewSystemIdentifier) -> Self {
Self(std::iter::once((visualizer, Default::default())).collect())
}
pub fn default_many(visualizers: impl IntoIterator<Item = ViewSystemIdentifier>) -> Self {
let recommended = visualizers
.into_iter()
.map(|v| (v, Default::default()))
.collect();
Self(recommended)
}
}
pub type VisualizersSectionUi<'a> = Box<dyn Fn(&mut egui::Ui, &ViewContext<'_>) + 'a>;
pub struct VisualizersSectionOutput<'a> {
pub ui: VisualizersSectionUi<'a>,
pub add_options: Vec<(EntityPath, RecommendedVisualizers)>,
}
pub trait ViewClass: Send + Sync {
fn identifier() -> ViewClassIdentifier
where
Self: Sized;
fn recommendation_order(&self) -> i32 {
0
}
fn display_name(&self) -> &'static str;
fn icon(&self) -> &'static re_ui::Icon {
&re_ui::icons::VIEW_GENERIC
}
fn help(&self, os: egui::os::OperatingSystem) -> re_ui::Help;
fn on_register(
&self,
system_registry: &mut ViewSystemRegistrator<'_>,
) -> Result<(), ViewClassRegistryError>;
fn new_state(&self) -> Box<dyn ViewState>;
fn preferred_tile_aspect_ratio(&self, _state: &dyn ViewState) -> Option<f32> {
None
}
fn layout_priority(&self) -> ViewClassLayoutPriority;
fn supports_visible_time_range(&self) -> bool {
false
}
fn default_query_range(&self, _state: &dyn ViewState) -> QueryRange {
QueryRange::LatestAt
}
fn recommended_origin_for_entities(
&self,
entities: &IntSet<EntityPath>,
_entity_db: &re_entity_db::EntityDb,
) -> Option<EntityPath> {
Some(EntityPath::common_ancestor_of(entities.iter()))
}
fn recommended_visualizers_for_entity(
&self,
entity_path: &EntityPath,
visualizable_entities_per_visualizer: &PerVisualizerTypeInViewClass<VisualizableEntities>,
indicated_entities_per_visualizer: &PerVisualizerType<IndicatedEntities>,
) -> RecommendedVisualizers {
let available_visualizers =
visualizable_entities_per_visualizer
.iter()
.filter_map(|(visualizer, ents)| {
if ents.contains_key(entity_path) {
Some(visualizer)
} else {
None
}
});
let recommended = available_visualizers
.filter_map(|visualizer| {
if indicated_entities_per_visualizer
.get(visualizer)
.is_some_and(|matching_list| matching_list.contains(entity_path))
{
Some((*visualizer, Default::default()))
} else {
None
}
})
.collect();
RecommendedVisualizers(recommended)
}
fn visualizers_section<'a>(
&'a self,
_ctx: &'a ViewContext<'a>,
) -> Option<VisualizersSectionOutput<'a>> {
None
}
#[deprecated(note = "Implement `visualizers_section` instead.", since = "0.30.1")]
#[expect(clippy::type_complexity)]
fn visualizers_ui<'a>(
&'a self,
_ctx: &'a ViewerContext<'a>,
_view_id: ViewId,
_state: &'a mut dyn ViewState,
_space_origin: &'a EntityPath,
) -> Option<Box<dyn Fn(&mut egui::Ui) + 'a>> {
None
}
fn spawn_heuristics(
&self,
ctx: &ViewerContext<'_>,
include_entity: &dyn Fn(&EntityPath) -> bool,
) -> ViewSpawnHeuristics;
#[doc(alias = "settings_ui")]
fn selection_ui(
&self,
_ctx: &ViewerContext<'_>,
_ui: &mut egui::Ui,
_state: &mut dyn ViewState,
_space_origin: &EntityPath,
_view_id: ViewId,
) -> Result<(), ViewSystemExecutionError> {
Ok(())
}
fn extra_title_bar_ui(
&self,
_ctx: &ViewerContext<'_>,
_ui: &mut egui::Ui,
_state: &mut dyn ViewState,
_space_origin: &EntityPath,
_view_id: ViewId,
) -> Result<(), ViewSystemExecutionError> {
Ok(())
}
#[doc(alias = "paint")]
#[doc(alias = "render")]
fn ui(
&self,
ctx: &ViewerContext<'_>,
missing_chunk_reporter: &MissingChunkReporter,
ui: &mut egui::Ui,
state: &mut dyn ViewState,
query: &ViewQuery<'_>,
system_output: SystemExecutionOutput,
) -> Result<(), ViewSystemExecutionError>;
}
pub trait ViewClassExt<'a>: ViewClass + 'a {
fn view_context<'b>(
&self,
viewer_ctx: &'b ViewerContext<'b>,
view_id: ViewId,
view_state: &'b dyn ViewState,
space_origin: &'b EntityPath,
) -> ViewContext<'b>;
}
impl<'a, T> ViewClassExt<'a> for T
where
T: ViewClass + 'a,
{
fn view_context<'b>(
&self,
viewer_ctx: &'b ViewerContext<'b>,
view_id: ViewId,
view_state: &'b dyn ViewState,
space_origin: &'b EntityPath,
) -> ViewContext<'b> {
ViewContext {
viewer_ctx,
view_id,
view_class_identifier: T::identifier(),
space_origin,
view_state,
query_result: viewer_ctx.lookup_query_result(view_id),
}
}
}
pub trait ViewState: std::any::Any + Sync + Send {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
fn size_bytes(&self) -> u64 {
0 }
}
impl ViewState for () {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
pub trait ViewStateExt: ViewState {
fn downcast_ref<T: ViewState>(&self) -> Result<&T, ViewSystemExecutionError> {
self.as_any()
.downcast_ref()
.ok_or(ViewSystemExecutionError::StateCastError(
std::any::type_name::<T>(),
))
}
fn downcast_mut<T: ViewState>(&mut self) -> Result<&mut T, ViewSystemExecutionError> {
self.as_any_mut()
.downcast_mut()
.ok_or(ViewSystemExecutionError::StateCastError(
std::any::type_name::<T>(),
))
}
}
impl ViewStateExt for dyn ViewState {}