spitfire_gui/
context.rs

1use crate::{interactions::GuiInteractionsEngine, prelude::GuiRenderer};
2#[cfg(target_arch = "wasm32")]
3use instant::Instant;
4use raui_core::prelude::*;
5use raui_immediate::*;
6use spitfire_draw::prelude::*;
7use spitfire_fontdue::*;
8use spitfire_glow::prelude::*;
9#[cfg(not(target_arch = "wasm32"))]
10use std::time::Instant;
11
12pub struct GuiContext {
13    pub coords_map_scaling: CoordsMappingScaling,
14    pub texture_filtering: GlowTextureFiltering,
15    pub interactions: GuiInteractionsEngine,
16    application: Application,
17    text_renderer: TextRenderer<Color>,
18    immediate: ImmediateContext,
19    timer: Instant,
20    glyphs_texture: Option<Texture>,
21}
22
23impl Default for GuiContext {
24    fn default() -> Self {
25        Self {
26            coords_map_scaling: Default::default(),
27            texture_filtering: Default::default(),
28            interactions: Default::default(),
29            application: Default::default(),
30            text_renderer: Default::default(),
31            immediate: Default::default(),
32            timer: Instant::now(),
33            glyphs_texture: None,
34        }
35    }
36}
37
38impl GuiContext {
39    pub fn mark_dirty(&mut self) {
40        self.application.mark_dirty();
41    }
42
43    pub fn begin_frame(&self) {
44        ImmediateContext::activate(&self.immediate);
45        begin();
46    }
47
48    pub fn end_frame(
49        &mut self,
50        draw: &mut DrawContext,
51        graphics: &mut Graphics<Vertex>,
52        colored_shader: &ShaderRef,
53        textured_shader: &ShaderRef,
54        text_shader: &ShaderRef,
55    ) {
56        let widgets = end();
57        ImmediateContext::deactivate();
58        self.application
59            .apply(make_widget!(content_box).key("root").listed_slots(widgets));
60        let elapsed = std::mem::replace(&mut self.timer, Instant::now())
61            .elapsed()
62            .as_secs_f32();
63        self.timer = Instant::now();
64        self.application.animations_delta_time = elapsed;
65        let coords_mapping = CoordsMapping::new_scaling(
66            Rect {
67                left: 0.0,
68                right: graphics.main_camera.screen_size.x,
69                top: 0.0,
70                bottom: graphics.main_camera.screen_size.y,
71            },
72            self.coords_map_scaling,
73        );
74        if self.application.process() {
75            let mut layout_engine = DefaultLayoutEngine::<()>::default();
76            let _ = self.application.layout(&coords_mapping, &mut layout_engine);
77        }
78        self.interactions.maintain(&coords_mapping);
79        let _ = self.application.interact(&mut self.interactions);
80        self.application.consume_signals();
81        let mut renderer = GuiRenderer {
82            texture_filtering: self.texture_filtering,
83            draw,
84            graphics,
85            colored_shader,
86            textured_shader,
87            text_shader,
88        };
89        let _ = self.application.render(&coords_mapping, &mut renderer);
90        let [w, h, d] = self.text_renderer.atlas_size();
91        if let Some(texture) = self.glyphs_texture.as_mut() {
92            texture.upload(
93                w as _,
94                h as _,
95                d as _,
96                GlowTextureFormat::Monochromatic,
97                Some(self.text_renderer.image()),
98            );
99        } else {
100            self.glyphs_texture = graphics
101                .texture(
102                    w as _,
103                    h as _,
104                    d as _,
105                    GlowTextureFormat::Monochromatic,
106                    Some(self.text_renderer.image()),
107                )
108                .ok();
109        }
110    }
111}