spitfire_gui/
context.rs

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