1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 21:30:03 -04:00

Refactor integrations (#871)

* Unify code in egui_glium and egui_glow into egui_winit::EpiIntegration
* Simplify `EguiGlium` interface
* Simplify `EguiGlow` interface
* egui_web refactor: merge `WebBackend` into `AppRunner`
This commit is contained in:
Emil Ernerfeldt
2021-11-03 13:45:51 +01:00
committed by GitHub
parent b1716be745
commit 1dbe608e73
14 changed files with 381 additions and 479 deletions

View File

@@ -181,3 +181,157 @@ impl Persistence {
}
}
}
// ----------------------------------------------------------------------------
/// Everything needed to make a winit-based integration for [`epi`].
pub struct EpiIntegration {
integration_name: &'static str,
persistence: crate::epi::Persistence,
repaint_signal: std::sync::Arc<dyn epi::RepaintSignal>,
pub egui_ctx: egui::CtxRef,
egui_winit: crate::State,
pub app: Box<dyn epi::App>,
latest_frame_time: Option<f32>,
/// When set, it is time to quit
quit: bool,
}
impl EpiIntegration {
pub fn new(
integration_name: &'static str,
window: &winit::window::Window,
tex_allocator: &mut dyn epi::TextureAllocator,
repaint_signal: std::sync::Arc<dyn epi::RepaintSignal>,
persistence: crate::epi::Persistence,
app: Box<dyn epi::App>,
) -> Self {
let egui_ctx = egui::CtxRef::default();
*egui_ctx.memory() = persistence.load_memory().unwrap_or_default();
let mut slf = Self {
integration_name,
persistence,
repaint_signal,
egui_ctx,
egui_winit: crate::State::new(window),
app,
latest_frame_time: None,
quit: false,
};
slf.setup(window, tex_allocator);
if slf.app.warm_up_enabled() {
slf.warm_up(window, tex_allocator);
}
slf
}
fn setup(
&mut self,
window: &winit::window::Window,
tex_allocator: &mut dyn epi::TextureAllocator,
) {
let mut app_output = epi::backend::AppOutput::default();
let mut frame = epi::backend::FrameBuilder {
info: integration_info(self.integration_name, window, None),
tex_allocator,
output: &mut app_output,
repaint_signal: self.repaint_signal.clone(),
}
.build();
self.app
.setup(&self.egui_ctx, &mut frame, self.persistence.storage());
self.quit |= app_output.quit;
crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output);
}
fn warm_up(
&mut self,
window: &winit::window::Window,
tex_allocator: &mut dyn epi::TextureAllocator,
) {
let saved_memory = self.egui_ctx.memory().clone();
self.egui_ctx.memory().set_everything_is_visible(true);
self.update(window, tex_allocator);
*self.egui_ctx.memory() = saved_memory; // We don't want to remember that windows were huge.
self.egui_ctx.clear_animations();
}
/// If `true`, it is time to shut down.
pub fn should_quit(&self) -> bool {
self.quit
}
pub fn on_event(&mut self, event: &winit::event::WindowEvent<'_>) {
self.quit |= self.egui_winit.is_quit_event(event);
self.egui_winit.on_event(&self.egui_ctx, event);
}
/// Returns `needs_repaint` and shapes to paint.
pub fn update(
&mut self,
window: &winit::window::Window,
tex_allocator: &mut dyn epi::TextureAllocator,
) -> (bool, Vec<egui::epaint::ClippedShape>) {
let frame_start = std::time::Instant::now();
let raw_input = self.egui_winit.take_egui_input(window);
self.egui_ctx.begin_frame(raw_input);
let mut app_output = epi::backend::AppOutput::default();
let mut frame = epi::backend::FrameBuilder {
info: integration_info(self.integration_name, window, self.latest_frame_time),
tex_allocator,
output: &mut app_output,
repaint_signal: self.repaint_signal.clone(),
}
.build();
self.app.update(&self.egui_ctx, &mut frame);
let (egui_output, shapes) = self.egui_ctx.end_frame();
let needs_repaint = egui_output.needs_repaint;
self.egui_winit
.handle_output(window, &self.egui_ctx, egui_output);
self.quit |= app_output.quit;
crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output);
let frame_time = (std::time::Instant::now() - frame_start).as_secs_f64() as f32;
self.latest_frame_time = Some(frame_time);
(needs_repaint, shapes)
}
pub fn maybe_autosave(&mut self, window: &winit::window::Window) {
self.persistence
.maybe_autosave(&mut *self.app, &self.egui_ctx, window);
}
pub fn on_exit(&mut self, window: &winit::window::Window) {
self.app.on_exit();
self.persistence
.save(&mut *self.app, &self.egui_ctx, window);
}
}
fn integration_info(
integration_name: &'static str,
window: &winit::window::Window,
previous_frame_time: Option<f32>,
) -> epi::IntegrationInfo {
epi::IntegrationInfo {
name: integration_name,
web_info: None,
prefer_dark_mode: None, // TODO: figure out system default
cpu_usage: previous_frame_time,
native_pixels_per_point: Some(crate::native_pixels_per_point(window)),
}
}

View File

@@ -171,7 +171,7 @@ impl State {
/// Prepare for a new frame by extracting the accumulated input,
/// as well as setting [the time](egui::RawInput::time) and [screen rectangle](egui::RawInput::screen_rect).
pub fn take_egui_input(&mut self, display: &winit::window::Window) -> egui::RawInput {
pub fn take_egui_input(&mut self, window: &winit::window::Window) -> egui::RawInput {
let pixels_per_point = self.pixels_per_point();
self.egui_input.time = Some(self.start_time.elapsed().as_secs_f64());
@@ -179,7 +179,7 @@ impl State {
// On Windows, a minimized window will have 0 width and height.
// See: https://github.com/rust-windowing/winit/issues/208
// This solves an issue where egui window positions would be changed when minimizing on Windows.
let screen_size_in_pixels = screen_size_in_pixels(display);
let screen_size_in_pixels = screen_size_in_pixels(window);
let screen_size_in_points = screen_size_in_pixels / pixels_per_point;
self.egui_input.screen_rect =
if screen_size_in_points.x > 0.0 && screen_size_in_points.y > 0.0 {