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