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}