Skip to main content

re_viewer_context/view/
view_context_system.rs

1use std::any::Any;
2
3use ahash::HashMap;
4use re_chunk_store::MissingChunkReporter;
5use re_sdk_types::ViewClassIdentifier;
6
7use crate::{
8    IdentifiedViewSystem, ViewContext, ViewQuery, ViewSystemExecutionError, ViewSystemIdentifier,
9    ViewerContext, VisualizerExecutionOutput,
10};
11
12pub type ViewContextSystemOncePerFrameResult = Box<dyn Any + Send + Sync>;
13
14/// View context that can be used by view parts and ui methods to retrieve information about the scene as a whole.
15///
16/// Is always populated before view part systems.
17pub trait ViewContextSystem: Send + Sync + Any {
18    /// Executes once per active _type_ of [`ViewContextSystem`], independent of the view's state, query, blueprint properties etc.
19    ///
20    /// This is run each frame once per type of view context system if the context system is used by any view.
21    /// The returned [`ViewContextSystemOncePerFrameResult`] is then passed to [`ViewContextSystem::execute`] for each view instance.
22    ///
23    /// Use this to perform any operations that are shared across all views that use this system,
24    /// independent of their state, query, blueprint properties etc.
25    fn execute_once_per_frame(_ctx: &ViewerContext<'_>) -> ViewContextSystemOncePerFrameResult
26    where
27        Self: Sized,
28    {
29        Box::new(())
30    }
31
32    /// Queries the chunk store and performs data conversions to make it ready for consumption by scene elements.
33    fn execute(
34        &mut self,
35        ctx: &ViewContext<'_>,
36        missing_chunk_reporter: &MissingChunkReporter,
37        query: &ViewQuery<'_>,
38        one_per_frame_execution_result: &ViewContextSystemOncePerFrameResult,
39    );
40}
41
42/// State stored per [`ViewContextSystem`] as a result of the last
43/// call to [`ViewContextSystem::execute`].
44#[derive(Default, Debug)]
45pub struct ViewSystemState {
46    pub any_missing_chunks: bool,
47}
48
49// TODO(jleibs): This probably needs a better name now that it includes class name
50pub struct ViewContextCollection {
51    pub systems: HashMap<ViewSystemIdentifier, (Box<dyn ViewContextSystem>, ViewSystemState)>,
52    pub view_class_identifier: ViewClassIdentifier,
53}
54
55impl ViewContextCollection {
56    /// The `output` is only there so we can report if there are any missing chunks
57    pub fn get<T: ViewContextSystem + IdentifiedViewSystem + 'static>(
58        &self,
59        output: &VisualizerExecutionOutput,
60    ) -> Result<&T, ViewSystemExecutionError> {
61        self.get_and_report_missing(output.missing_chunk_reporter())
62    }
63
64    pub fn get_and_report_missing<T: ViewContextSystem + IdentifiedViewSystem + 'static>(
65        &self,
66        missing_chunk_reporter: &MissingChunkReporter,
67    ) -> Result<&T, ViewSystemExecutionError> {
68        self.systems
69            .get(&T::identifier())
70            .and_then(|(system, state)| {
71                if state.any_missing_chunks {
72                    missing_chunk_reporter.report_missing_chunk();
73                }
74                (system.as_ref() as &dyn Any).downcast_ref()
75            })
76            .ok_or_else(|| {
77                ViewSystemExecutionError::ContextSystemNotFound(T::identifier().as_str())
78            })
79    }
80
81    pub fn iter_with_identifiers(
82        &self,
83    ) -> impl Iterator<Item = (ViewSystemIdentifier, &dyn ViewContextSystem)> {
84        self.systems
85            .iter()
86            .map(|(id, (system, _state))| (*id, system.as_ref()))
87    }
88
89    pub fn view_class_identifier(&self) -> ViewClassIdentifier {
90        self.view_class_identifier
91    }
92}