shura/graphics/gui/
gui.rs1use std::ops::{Deref, DerefMut};
2
3use crate::{gui::GuiContext, Gpu, GpuDefaults, RenderEncoder, Vector};
4use egui_wgpu::renderer::{Renderer, ScreenDescriptor};
5use egui_winit::State;
6use instant::Duration;
7use winit::window::Window;
8
9pub struct Gui {
10 state: State,
11 context: GuiContext,
12 renderer: Renderer,
13 screen_descriptor: ScreenDescriptor,
14}
15
16impl Gui {
17 pub(crate) fn new(
18 event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
19 gpu: &Gpu,
20 ) -> Self {
21 let config = &gpu.config;
22 let device = &gpu.device;
23 let renderer = Renderer::new(
24 device,
25 wgpu::TextureFormat::Rgba8UnormSrgb,
26 None,
27 gpu.base.sample_count,
28 );
29 let state = State::new(event_loop);
30 let context = GuiContext::default();
31
32 let screen_descriptor = ScreenDescriptor {
33 size_in_pixels: [config.width, config.height],
34 pixels_per_point: 1.0,
35 };
36 Self {
37 renderer,
38 state,
39 context,
40 screen_descriptor,
41 }
42 }
43
44 pub(crate) fn resize(&mut self, size: &Vector<u32>) {
45 self.screen_descriptor = ScreenDescriptor {
46 size_in_pixels: [size.x, size.y],
47 pixels_per_point: 1.0,
48 };
49 }
50
51 pub(crate) fn handle_event(&mut self, event: &winit::event::WindowEvent) {
52 self.state.on_event(&self.context, event).consumed;
53 }
54
55 pub(crate) fn begin(&mut self, total_time: &Duration, window: &Window) {
56 let mut egui_input = self.state.take_egui_input(window);
57 egui_input.time = Some(total_time.as_secs_f64());
58 self.context.begin_frame(egui_input);
59 }
60
61 pub(crate) fn render(
62 &mut self,
63 gpu: &Gpu,
64 defaults: &GpuDefaults,
65 encoder: &mut RenderEncoder,
66 ) {
67 let output = self.context.end_frame();
68 let paint_jobs = self.context.tessellate(output.shapes);
69
70 for add in &output.textures_delta.set {
71 self.renderer
72 .update_texture(&gpu.device, &gpu.queue, add.0, &add.1);
73 }
74
75 self.renderer.update_buffers(
76 &gpu.device,
77 &gpu.queue,
78 &mut encoder.inner,
79 &paint_jobs,
80 &self.screen_descriptor,
81 );
82
83 {
84 let mut rpass = encoder
85 .inner
86 .begin_render_pass(&wgpu::RenderPassDescriptor {
87 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
88 view: defaults.world_target.msaa(),
89 resolve_target: Some(defaults.world_target.view()),
90 ops: wgpu::Operations {
91 load: wgpu::LoadOp::Load,
92 store: true,
93 },
94 })],
95 depth_stencil_attachment: None,
96 label: Some("egui main render pass"),
97 });
98
99 self.renderer
100 .render(&mut rpass, &paint_jobs, &self.screen_descriptor);
101 }
102
103 for free in &output.textures_delta.free {
104 self.renderer.free_texture(free);
105 }
106 }
107}
108
109impl Deref for Gui {
110 type Target = GuiContext;
111
112 fn deref(&self) -> &Self::Target {
113 &self.context
114 }
115}
116
117impl DerefMut for Gui {
118 fn deref_mut(&mut self) -> &mut Self::Target {
119 &mut self.context
120 }
121}