servoshell/desktop/
egui_glue.rs1use egui::{ViewportId, ViewportOutput};
37use egui_glow::ShaderVersion;
38pub use egui_winit;
39pub use egui_winit::EventResponse;
40use egui_winit::winit;
41use winit::event_loop::ActiveEventLoop;
42use winit::window::Theme;
43
44use super::events_loop::EventLoopProxy;
45use super::headed_window::Window;
46use super::window_trait::WindowPortsMethods;
47
48pub struct EguiGlow {
50 pub egui_ctx: egui::Context,
51 pub egui_winit: egui_winit::State,
52 pub painter: egui_glow::Painter,
53
54 shapes: Vec<egui::epaint::ClippedShape>,
55 textures_delta: egui::TexturesDelta,
56}
57
58impl EguiGlow {
59 pub fn new(
61 window: &Window,
62 event_loop: &ActiveEventLoop,
63 event_loop_proxy: EventLoopProxy,
64 gl: std::sync::Arc<glow::Context>,
65 shader_version: Option<ShaderVersion>,
66 ) -> Self {
67 let painter = egui_glow::Painter::new(gl, "", shader_version, false)
68 .map_err(|err| {
69 log::error!("error occurred in initializing painter:\n{err}");
70 })
71 .unwrap();
72
73 let theme = event_loop.system_theme().unwrap_or(Theme::Light);
74 let egui_ctx = egui::Context::default();
75 let mut egui_winit = egui_winit::State::new(
76 egui_ctx.clone(),
77 ViewportId::ROOT,
78 event_loop,
79 None,
80 Some(theme),
81 None,
82 );
83 let window = window.winit_window().unwrap();
84 egui_winit.init_accesskit(event_loop, window, event_loop_proxy);
85 window.set_visible(true);
86 Self {
87 egui_winit,
88 egui_ctx,
89 painter,
90 shapes: Default::default(),
91 textures_delta: Default::default(),
92 }
93 }
94
95 pub fn on_window_event(
96 &mut self,
97 window: &winit::window::Window,
98 event: &winit::event::WindowEvent,
99 ) -> EventResponse {
100 self.egui_winit.on_window_event(window, event)
101 }
102
103 pub fn run(
107 &mut self,
108 window: &winit::window::Window,
109 run_ui: impl FnMut(&egui::Context),
110 ) -> std::time::Duration {
111 let raw_input = self.egui_winit.take_egui_input(window);
112 let egui::FullOutput {
113 platform_output,
114 viewport_output,
115 textures_delta,
116 shapes,
117 pixels_per_point: _pixels_per_point,
118 } = self.egui_ctx.run(raw_input, run_ui);
119
120 self.egui_winit
121 .handle_platform_output(window, platform_output);
122
123 self.shapes = shapes;
124 self.textures_delta.append(textures_delta);
125 match viewport_output.get(&ViewportId::ROOT) {
126 Some(&ViewportOutput { repaint_delay, .. }) => repaint_delay,
127 None => std::time::Duration::ZERO,
128 }
129 }
130
131 pub fn paint(&mut self, window: &winit::window::Window) {
133 let shapes = &self.shapes;
135 let mut textures_delta = std::mem::take(&mut self.textures_delta);
136
137 for (id, image_delta) in textures_delta.set {
138 self.painter.set_texture(id, &image_delta);
139 }
140
141 let pixels_per_point = self.egui_ctx.pixels_per_point();
142 let clipped_primitives = self.egui_ctx.tessellate(shapes.clone(), pixels_per_point);
144 let dimensions: [u32; 2] = window.inner_size().into();
145 self.painter
146 .paint_primitives(dimensions, pixels_per_point, &clipped_primitives);
147
148 for id in textures_delta.free.drain(..) {
149 self.painter.free_texture(id);
150 }
151 }
152
153 pub fn destroy(&mut self) {
155 self.painter.destroy();
156 }
157}