Skip to main content

lgui_core/core/component/
context.rs

1use super::{
2    AnimProperty, AnimationRegistry, ComponentId, ComponentState, ComponentStateStore,
3    ComponentTree, CompositingLayerAnimation, CompositingLayerSpec, ContextRegistry,
4    EffectRegistry, HookId, HookSlotKind, HookStateStore, InteractionFlags, UiId,
5    UiInteractionState, UiRect, UiScale, UiScope, UiTaskSpawner, UiUpdateQueue,
6};
7use std::sync::Arc;
8
9#[derive(Clone, Copy)]
10pub struct UiRenderContext<'a> {
11    interaction: &'a UiInteractionState,
12    animations: &'a AnimationRegistry,
13    component_states: &'a ComponentStateStore,
14    component_tree: &'a ComponentTree,
15    contexts: &'a ContextRegistry,
16    hook_states: &'a HookStateStore,
17    hook_updates: &'a Arc<UiUpdateQueue>,
18    task_spawner: Option<&'a UiTaskSpawner>,
19    effects: &'a EffectRegistry,
20    viewport: UiRect,
21    scale: UiScale,
22}
23
24impl<'a> UiRenderContext<'a> {
25    pub fn new(
26        interaction: &'a UiInteractionState,
27        animations: &'a AnimationRegistry,
28        component_states: &'a ComponentStateStore,
29        component_tree: &'a ComponentTree,
30        contexts: &'a ContextRegistry,
31        hook_states: &'a HookStateStore,
32        hook_updates: &'a Arc<UiUpdateQueue>,
33        task_spawner: Option<&'a UiTaskSpawner>,
34        effects: &'a EffectRegistry,
35        viewport: UiRect,
36        scale: UiScale,
37    ) -> Self {
38        Self {
39            interaction,
40            animations,
41            component_states,
42            component_tree,
43            contexts,
44            hook_states,
45            hook_updates,
46            task_spawner,
47            effects,
48            viewport,
49            scale,
50        }
51    }
52
53    pub fn viewport(&self) -> UiRect {
54        self.viewport
55    }
56
57    pub fn scale(&self) -> UiScale {
58        self.scale
59    }
60
61    pub fn interaction_flags(&self, id: &UiId) -> InteractionFlags {
62        self.interaction.flags_for(id)
63    }
64
65    pub fn animation_value(&self, id: &UiId, property: AnimProperty) -> f32 {
66        self.animations.value(id.clone(), property)
67    }
68
69    pub fn component_state_mut<T, R>(&self, id: &UiId, f: impl FnOnce(&mut T) -> R) -> R
70    where
71        T: ComponentState + Clone + Default + 'static,
72    {
73        self.component_states.with_mut(id, f)
74    }
75
76    pub(crate) fn component_state_mut_for_component<T, R>(
77        &self,
78        id: &UiId,
79        owner: ComponentId,
80        invalidation_id: UiId,
81        f: impl FnOnce(&mut T) -> R,
82    ) -> R
83    where
84        T: ComponentState + Clone + Default + 'static,
85    {
86        self.component_states
87            .with_mut_for_component(id, owner, invalidation_id, f)
88    }
89
90    pub(crate) fn compositing_layer_animation_mut<T, R>(
91        &self,
92        id: &UiId,
93        f: impl FnOnce(&mut T) -> R,
94    ) -> (R, CompositingLayerSpec, bool)
95    where
96        T: CompositingLayerAnimation,
97    {
98        self.component_states
99            .with_mut_for_compositing_layer(id, id.clone(), f)
100    }
101
102    pub fn preserve_component_state_scope(&self, scope: &UiScope) {
103        self.component_states.preserve_scope(scope);
104    }
105
106    pub fn component_tree(&self) -> &ComponentTree {
107        self.component_tree
108    }
109
110    pub fn contexts(&self) -> &ContextRegistry {
111        self.contexts
112    }
113
114    pub fn hook_state<T>(&self, id: HookId, initial: impl FnOnce() -> T) -> T
115    where
116        T: Clone + 'static,
117    {
118        self.hook_states.value(id, initial)
119    }
120
121    pub fn hook_updates(&self) -> Arc<UiUpdateQueue> {
122        Arc::clone(self.hook_updates)
123    }
124
125    pub fn task_spawner(&self) -> Option<UiTaskSpawner> {
126        self.task_spawner.cloned()
127    }
128
129    pub fn effect<D, F, R>(&self, id: HookId, deps: D, effect: F)
130    where
131        D: Clone + PartialEq + 'static,
132        F: FnOnce() -> R + 'static,
133        R: super::IntoEffectCleanup,
134    {
135        self.effects.register(id, deps, effect);
136    }
137
138    #[doc(hidden)]
139    pub fn element_effect<D, F, R>(&self, parent: ComponentId, owner: UiId, deps: D, effect: F)
140    where
141        D: Clone + PartialEq + 'static,
142        F: FnOnce() -> R + 'static,
143        R: super::IntoEffectCleanup,
144    {
145        let component = self.component_tree.element_effect_child(parent, &owner);
146        self.component_tree.begin_component_execution(component);
147        self.component_tree
148            .record_hook(component, HookSlotKind::Effect);
149        self.effects.register(
150            HookId::new(component, 0, HookSlotKind::Effect),
151            deps,
152            effect,
153        );
154        self.component_tree.finish_component(component);
155    }
156}