
* egui-winit: don't assume window available at init On Android in particular we can only initialize render state once we have a native window, after a 'Resumed' lifecycle event. It's still practical to be able to initialize an egui_winit::State early on so this adds setters for the max_texture_side and pixels_per_point that can be called once we have a valid Window and have initialized a graphics context. On Wayland, where we need to access the Display for clipboard handling we now get the Display from the event loop instead of a window. * egui-wgpu: lazily initialize render + surface state Enable the renderer and surface state initialization to be deferred until we know that any winit window we created has a valid native window and enable the surface state to be updated in case the native window changes. In particular these changes help with running on Android where winit windows will only have a valid native window associated with them between Resumed and Paused lifecycle events, and so surface creation (and render state initialization) needs to wait until the first Resumed event, and the surface needs to be dropped/recreated based on Paused/Resumed events.
120 lines
4 KiB
Rust
120 lines
4 KiB
Rust
//! Example how to use pure `egui_glow`.
|
|
|
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
|
#![allow(unsafe_code)]
|
|
|
|
fn main() {
|
|
let mut clear_color = [0.1, 0.1, 0.1];
|
|
|
|
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
|
let (gl_window, gl) = create_display(&event_loop);
|
|
let gl = std::sync::Arc::new(gl);
|
|
|
|
let mut egui_glow = egui_glow::EguiGlow::new(&event_loop, gl.clone());
|
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
let mut redraw = || {
|
|
let mut quit = false;
|
|
|
|
let needs_repaint = egui_glow.run(gl_window.window(), |egui_ctx| {
|
|
egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| {
|
|
ui.heading("Hello World!");
|
|
if ui.button("Quit").clicked() {
|
|
quit = true;
|
|
}
|
|
ui.color_edit_button_rgb(&mut clear_color);
|
|
});
|
|
});
|
|
|
|
*control_flow = if quit {
|
|
glutin::event_loop::ControlFlow::Exit
|
|
} else if needs_repaint {
|
|
gl_window.window().request_redraw();
|
|
glutin::event_loop::ControlFlow::Poll
|
|
} else {
|
|
glutin::event_loop::ControlFlow::Wait
|
|
};
|
|
|
|
{
|
|
unsafe {
|
|
use glow::HasContext as _;
|
|
gl.clear_color(clear_color[0], clear_color[1], clear_color[2], 1.0);
|
|
gl.clear(glow::COLOR_BUFFER_BIT);
|
|
}
|
|
|
|
// draw things behind egui here
|
|
|
|
egui_glow.paint(gl_window.window());
|
|
|
|
// draw things on top of egui here
|
|
|
|
gl_window.swap_buffers().unwrap();
|
|
}
|
|
};
|
|
|
|
match event {
|
|
// Platform-dependent event handlers to workaround a winit bug
|
|
// See: https://github.com/rust-windowing/winit/issues/987
|
|
// See: https://github.com/rust-windowing/winit/issues/1619
|
|
glutin::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(),
|
|
glutin::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(),
|
|
|
|
glutin::event::Event::WindowEvent { event, .. } => {
|
|
use glutin::event::WindowEvent;
|
|
if matches!(event, WindowEvent::CloseRequested | WindowEvent::Destroyed) {
|
|
*control_flow = glutin::event_loop::ControlFlow::Exit;
|
|
}
|
|
|
|
if let glutin::event::WindowEvent::Resized(physical_size) = &event {
|
|
gl_window.resize(*physical_size);
|
|
} else if let glutin::event::WindowEvent::ScaleFactorChanged {
|
|
new_inner_size,
|
|
..
|
|
} = &event
|
|
{
|
|
gl_window.resize(**new_inner_size);
|
|
}
|
|
|
|
egui_glow.on_event(&event);
|
|
|
|
gl_window.window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead
|
|
}
|
|
glutin::event::Event::LoopDestroyed => {
|
|
egui_glow.destroy();
|
|
}
|
|
|
|
_ => (),
|
|
}
|
|
});
|
|
}
|
|
|
|
fn create_display(
|
|
event_loop: &glutin::event_loop::EventLoop<()>,
|
|
) -> (
|
|
glutin::WindowedContext<glutin::PossiblyCurrent>,
|
|
glow::Context,
|
|
) {
|
|
let window_builder = glutin::window::WindowBuilder::new()
|
|
.with_resizable(true)
|
|
.with_inner_size(glutin::dpi::LogicalSize {
|
|
width: 800.0,
|
|
height: 600.0,
|
|
})
|
|
.with_title("egui_glow example");
|
|
|
|
let gl_window = unsafe {
|
|
glutin::ContextBuilder::new()
|
|
.with_depth_buffer(0)
|
|
.with_srgb(true)
|
|
.with_stencil_buffer(0)
|
|
.with_vsync(true)
|
|
.build_windowed(window_builder, event_loop)
|
|
.unwrap()
|
|
.make_current()
|
|
.unwrap()
|
|
};
|
|
|
|
let gl = unsafe { glow::Context::from_loader_function(|s| gl_window.get_proc_address(s)) };
|
|
|
|
(gl_window, gl)
|
|
}
|