spitfire_gui/
context.rs

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::{interactions::GuiInteractionsEngine, prelude::GuiRenderer};
#[cfg(target_arch = "wasm32")]
use instant::Instant;
use raui_core::prelude::*;
use raui_immediate::*;
use spitfire_draw::prelude::*;
use spitfire_fontdue::*;
use spitfire_glow::prelude::*;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;

pub struct GuiContext {
    pub coords_map_scaling: CoordsMappingScaling,
    pub texture_filtering: GlowTextureFiltering,
    pub interactions: GuiInteractionsEngine,
    application: Application,
    text_renderer: TextRenderer<Color>,
    immediate: ImmediateContext,
    timer: Instant,
    glyphs_texture: Option<Texture>,
}

impl Default for GuiContext {
    fn default() -> Self {
        Self {
            coords_map_scaling: Default::default(),
            texture_filtering: Default::default(),
            interactions: Default::default(),
            application: Default::default(),
            text_renderer: Default::default(),
            immediate: Default::default(),
            timer: Instant::now(),
            glyphs_texture: None,
        }
    }
}

impl GuiContext {
    pub fn mark_dirty(&mut self) {
        self.application.mark_dirty();
    }

    pub fn begin_frame(&self) {
        ImmediateContext::activate(&self.immediate);
        begin();
    }

    pub fn end_frame(
        &mut self,
        draw: &mut DrawContext,
        graphics: &mut Graphics<Vertex>,
        colored_shader: &ShaderRef,
        textured_shader: &ShaderRef,
        text_shader: &ShaderRef,
    ) {
        let widgets = end();
        ImmediateContext::deactivate();
        self.application
            .apply(make_widget!(content_box).key("root").listed_slots(widgets));
        let elapsed = std::mem::replace(&mut self.timer, Instant::now())
            .elapsed()
            .as_secs_f32();
        self.timer = Instant::now();
        self.application.animations_delta_time = elapsed;
        let coords_mapping = CoordsMapping::new_scaling(
            Rect {
                left: 0.0,
                right: graphics.main_camera.screen_size.x,
                top: 0.0,
                bottom: graphics.main_camera.screen_size.y,
            },
            self.coords_map_scaling,
        );
        if self.application.process() {
            let _ = self
                .application
                .layout(&coords_mapping, &mut DefaultLayoutEngine);
        }
        self.interactions.maintain(&coords_mapping);
        let _ = self.application.interact(&mut self.interactions);
        self.application.consume_signals();
        let mut renderer = GuiRenderer {
            texture_filtering: self.texture_filtering,
            draw,
            graphics,
            colored_shader,
            textured_shader,
            text_shader,
        };
        let _ = self.application.render(&coords_mapping, &mut renderer);
        let [w, h, d] = self.text_renderer.atlas_size();
        if let Some(texture) = self.glyphs_texture.as_mut() {
            texture.upload(
                w as _,
                h as _,
                d as _,
                GlowTextureFormat::Monochromatic,
                Some(self.text_renderer.image()),
            );
        } else {
            self.glyphs_texture = graphics
                .texture(
                    w as _,
                    h as _,
                    d as _,
                    GlowTextureFormat::Monochromatic,
                    Some(self.text_renderer.image()),
                )
                .ok();
        }
    }
}