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