polyscope_ui/
integration.rs1use egui::Context;
4use egui_wgpu::Renderer as EguiRenderer;
5use egui_wgpu::ScreenDescriptor;
6use egui_winit::State as EguiWinitState;
7use winit::event::WindowEvent;
8use winit::window::Window;
9
10pub struct EguiIntegration {
12 pub context: Context,
13 pub state: EguiWinitState,
14 pub renderer: EguiRenderer,
15 last_raw_input: egui::RawInput,
17}
18
19impl EguiIntegration {
20 #[must_use]
22 pub fn new(device: &wgpu::Device, output_format: wgpu::TextureFormat, window: &Window) -> Self {
23 let context = Context::default();
24
25 context.set_visuals(egui::Visuals::dark());
27
28 let viewport_id = context.viewport_id();
29 let state = EguiWinitState::new(context.clone(), viewport_id, window, None, None, None);
30
31 let renderer =
32 EguiRenderer::new(device, output_format, egui_wgpu::RendererOptions::default());
33
34 Self {
35 context,
36 state,
37 renderer,
38 last_raw_input: egui::RawInput::default(),
39 }
40 }
41
42 pub fn handle_event(&mut self, window: &Window, event: &WindowEvent) -> bool {
45 let response = self.state.on_window_event(window, event);
46 response.consumed
47 }
48
49 pub fn begin_frame(&mut self, window: &Window) {
51 let raw_input = self.state.take_egui_input(window);
52 self.last_raw_input = raw_input.clone();
53 self.context.begin_pass(raw_input);
54 }
55
56 pub fn begin_rerun_pass(&mut self) {
64 self.context.begin_pass(self.last_raw_input.take());
65 }
66
67 pub fn end_pass(&mut self) -> egui::FullOutput {
72 self.context.end_pass()
73 }
74
75 pub fn handle_platform_output(&mut self, window: &Window, output: &egui::PlatformOutput) {
77 self.state.handle_platform_output(window, output.clone());
78 }
79
80 pub fn end_frame(&mut self, window: &Window) -> egui::FullOutput {
82 let output = self.end_pass();
83 self.handle_platform_output(window, &output.platform_output);
84 output
85 }
86
87 pub fn render(
89 &mut self,
90 device: &wgpu::Device,
91 queue: &wgpu::Queue,
92 encoder: &mut wgpu::CommandEncoder,
93 view: &wgpu::TextureView,
94 screen_descriptor: &ScreenDescriptor,
95 output: egui::FullOutput,
96 ) {
97 let paint_jobs = self
98 .context
99 .tessellate(output.shapes, output.pixels_per_point);
100
101 for (id, image_delta) in &output.textures_delta.set {
102 self.renderer
103 .update_texture(device, queue, *id, image_delta);
104 }
105
106 self.renderer
107 .update_buffers(device, queue, encoder, &paint_jobs, screen_descriptor);
108
109 {
110 let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
111 label: Some("egui render pass"),
112 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
113 view,
114 resolve_target: None,
115 ops: wgpu::Operations {
116 load: wgpu::LoadOp::Load, store: wgpu::StoreOp::Store,
118 },
119 depth_slice: None,
120 })],
121 depth_stencil_attachment: None,
122 ..Default::default()
123 });
124
125 let mut render_pass = render_pass.forget_lifetime();
127
128 self.renderer
129 .render(&mut render_pass, &paint_jobs, screen_descriptor);
130 }
131
132 for id in &output.textures_delta.free {
133 self.renderer.free_texture(id);
134 }
135 }
136}