1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use ahash::HashMap;

use re_types::{ComponentNameSet, SpaceViewClassIdentifier};

use crate::{IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewQuery, ViewSystemIdentifier};

use super::view_context::ViewContext;

/// View context that can be used by view parts and ui methods to retrieve information about the scene as a whole.
///
/// Is always populated before view part systems.
pub trait ViewContextSystem: Send + Sync {
    /// Returns all the component sets that the system is compatible with.
    ///
    /// If an entity path satisfies any of these sets, then the system will automatically run for
    /// that entity path.
    ///
    /// Return an empty vec to specify that the system should never run automatically for any
    /// specific entities.
    /// It may still run once per frame as part of the global context if it has been registered to
    /// do so, see [`crate::SpaceViewSystemRegistrator`].
    fn compatible_component_sets(&self) -> Vec<ComponentNameSet>;

    /// Queries the chunk store and performs data conversions to make it ready for consumption by scene elements.
    fn execute(&mut self, ctx: &ViewContext<'_>, query: &ViewQuery<'_>);

    /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types.
    fn as_any(&self) -> &dyn std::any::Any;
}

// TODO(jleibs): This probably needs a better name now that it includes class name
pub struct ViewContextCollection {
    pub systems: HashMap<ViewSystemIdentifier, Box<dyn ViewContextSystem>>,
    pub space_view_class_identifier: SpaceViewClassIdentifier,
}

impl ViewContextCollection {
    pub fn get<T: ViewContextSystem + IdentifiedViewSystem + 'static>(
        &self,
    ) -> Result<&T, SpaceViewSystemExecutionError> {
        self.systems
            .get(&T::identifier())
            .and_then(|s| s.as_any().downcast_ref())
            .ok_or_else(|| {
                SpaceViewSystemExecutionError::ContextSystemNotFound(T::identifier().as_str())
            })
    }

    pub fn iter_with_identifiers(
        &self,
    ) -> impl Iterator<Item = (ViewSystemIdentifier, &dyn ViewContextSystem)> {
        self.systems.iter().map(|s| (*s.0, s.1.as_ref()))
    }

    pub fn space_view_class_identifier(&self) -> SpaceViewClassIdentifier {
        self.space_view_class_identifier
    }
}