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 _ = self
76                .application
77                .layout(&coords_mapping, &mut DefaultLayoutEngine);
78        }
79        self.interactions.maintain(&coords_mapping);
80        let _ = self.application.interact(&mut self.interactions);
81        self.application.consume_signals();
82        let mut renderer = GuiRenderer {
83            texture_filtering: self.texture_filtering,
84            draw,
85            graphics,
86            colored_shader,
87            textured_shader,
88            text_shader,
89        };
90        let _ = self.application.render(&coords_mapping, &mut renderer);
91        let [w, h, d] = self.text_renderer.atlas_size();
92        if let Some(texture) = self.glyphs_texture.as_mut() {
93            texture.upload(
94                w as _,
95                h as _,
96                d as _,
97                GlowTextureFormat::Monochromatic,
98                Some(self.text_renderer.image()),
99            );
100        } else {
101            self.glyphs_texture = graphics
102                .texture(
103                    w as _,
104                    h as _,
105                    d as _,
106                    GlowTextureFormat::Monochromatic,
107                    Some(self.text_renderer.image()),
108                )
109                .ok();
110        }
111    }
112}