egui_sdl2/lib.rs
1//! # egui-sdl2
2//!
3//! Integration between [`egui`](https://github.com/emilk/egui) and
4//! [`sdl2`](https://github.com/Rust-SDL2/rust-sdl2).
5//!
6//! ## Features
7//! - Translate SDL2 events into [`egui`] events.
8//! - Handle [`egui::PlatformOutput`] (clipboard, cursor updates, links).
9//! - Render with OpenGL via [`glow`] (`glow-backend` feature).
10//! - Render with the SDL2 software renderer via [`sdl2::render::Canvas`] (`canvas-backend` feature).
11//!
12//! ## Usage
13//! ```no_run
14//! // Create SDL2 window:
15//! let sdl = sdl2::init().unwrap();
16//! let video = sdl.video().unwrap();
17//! let window = video.window("Egui SDL2 Canvas", 800, 600).build().unwrap();
18//! // Create egui renderer:
19//! let mut egui = egui_sdl2::EguiCanvas::new(window);
20//! let mut event_pump = sdl.event_pump().unwrap();
21//! loop {
22//! // Feed SDL2 events into egui:
23//! for event in event_pump.poll_iter() {
24//! egui.on_event(&event);
25//! }
26//! // Call `run` + `paint` each frame:
27//! egui.run(|ctx: &egui::Context| {});
28//! egui.paint();
29//! egui.present();
30//! std::thread::sleep(std::time::Duration::from_secs_f64(1.0 / 60.0));
31//!}
32//! ```
33
34pub use egui;
35#[cfg(feature = "glow-backend")]
36pub use egui_glow;
37pub use sdl2;
38
39#[cfg(feature = "canvas-backend")]
40pub mod canvas;
41#[cfg(feature = "glow-backend")]
42pub mod glow;
43pub mod state;
44#[cfg(feature = "wgpu-backend")]
45pub mod wgpu;
46
47#[cfg(feature = "canvas-backend")]
48pub use canvas::EguiCanvas;
49#[cfg(feature = "glow-backend")]
50pub use glow::*;
51pub use state::*;
52#[cfg(feature = "wgpu-backend")]
53pub use wgpu::EguiWgpu;
54
55/// The results of running one frame of `egui`.
56///
57/// `EguiRunOutput` collects the renderable shapes, texture updates, and scale
58/// factor from a single `egui` run. It also provides convenience methods for
59/// updating its contents from an `egui::Context` and for draining the data
60/// when it is time to render.
61///
62/// This is typically created once per backend instance and reused across frames.
63pub struct EguiRunOutput {
64 /// The clipped shapes that should be rendered for the current frame.
65 ///
66 /// This is produced by egui’s tessellation step and represents what should
67 /// be drawn to the screen.
68 pub shapes: Vec<egui::epaint::ClippedShape>,
69
70 /// The logical-to-physical pixel scaling factor used by egui in this frame.
71 ///
72 /// Backends should respect this when converting coordinates to pixels.
73 pub pixels_per_point: f32,
74
75 /// The delta of texture updates required for this frame.
76 ///
77 /// Includes new textures to upload and old textures to free.
78 pub textures_delta: egui::TexturesDelta,
79}
80
81impl Default for EguiRunOutput {
82 /// Creates an empty `EguiRunOutput` with no shapes, no texture updates,
83 /// and a scale factor of `1.0`.
84 fn default() -> Self {
85 Self {
86 shapes: Default::default(),
87 pixels_per_point: 1.0,
88 textures_delta: Default::default(),
89 }
90 }
91}
92
93impl EguiRunOutput {
94 /// Run `egui` for one frame and update this output with the results.
95 ///
96 /// # Parameters
97 /// - `ctx`: The [`egui::Context`] used to run the UI.
98 /// - `state`: A backend state that provides input for egui and
99 /// handles platform output (clipboard, cursor, etc.).
100 /// - `run_ui`: A closure that builds the UI using the given `egui::Context`.
101 ///
102 /// # Behavior
103 /// - Takes input events from `state`.
104 /// - Runs egui with the provided `run_ui` closure.
105 /// - Handles platform output via `state`.
106 /// - Stores the frame’s shapes, texture updates, and scale factor
107 /// in this `EguiRunOutput`.
108 #[inline]
109 pub fn update(
110 &mut self,
111 ctx: &egui::Context,
112 state: &mut State,
113 run_ui: impl FnMut(&egui::Context),
114 ) {
115 let raw_input = state.take_egui_input();
116 let egui::FullOutput {
117 platform_output,
118 viewport_output: _,
119 textures_delta,
120 shapes,
121 pixels_per_point,
122 } = ctx.run(raw_input, run_ui);
123 state.handle_platform_output(platform_output);
124
125 self.shapes = shapes;
126 self.textures_delta.append(textures_delta);
127 self.pixels_per_point = pixels_per_point;
128 }
129
130 /// Take ownership of the texture updates and shapes for the current frame.
131 ///
132 /// This clears both fields in the struct, leaving them empty for the next frame.
133 ///
134 /// # Returns
135 /// - `(textures_delta, shapes)` where:
136 /// - `textures_delta`: The [`egui::TexturesDelta`] with texture uploads/free requests.
137 /// - `shapes`: The tessellated shapes that should be rendered.
138 #[inline]
139 pub fn take(&mut self) -> (egui::TexturesDelta, Vec<egui::epaint::ClippedShape>) {
140 let textures_delta = std::mem::take(&mut self.textures_delta);
141 let shapes = std::mem::take(&mut self.shapes);
142
143 (textures_delta, shapes)
144 }
145}