egui_sdl2/wgpu/
mod.rs

1//! Integration between [`egui`] and [`wgpu`](https://docs.rs/wgpu) API.
2//!
3//! This module provides [`EguiWgpu`], a convenience wrapper that bundles
4//! together:
5//! - [`egui::Context`] for running your UI
6//! - [`crate::State`] for event and input handling
7//! - [`Painter`] for rendering using [`wgpu`](https://docs.rs/wgpu)
8
9//! # Usage
10//! Typical usage is to:
11//! 1. Create an [`EguiWgpu`] for your SDL2 window
12//! 2. Pass SDL2 events to [`EguiWgpu::on_event`]
13//! 3. Call [`EguiWgpu::run`] providing our UI function
14//! 4. Paint egui output via [`EguiWgpu::paint`]
15//!
16
17use std::num::NonZeroU32;
18pub mod painter;
19pub use painter::*;
20
21/// Integration between [`egui`] and [`wgpu`](https://docs.rs/wgpu) for app based on [`sdl2`].
22pub struct EguiWgpu {
23    backend: crate::EguiBackend,
24    viewport_id: egui::ViewportId,
25    pub ctx: egui::Context,
26    pub state: crate::State,
27    pub painter: painter::Painter,
28    pub window: sdl2::video::Window,
29}
30
31impl EguiWgpu {
32    pub async fn new(window: sdl2::video::Window) -> Self {
33        let ctx = egui::Context::default();
34        let viewport_id = egui::ViewportId::ROOT;
35        let state = crate::State::new(&window, ctx.clone(), viewport_id);
36        let backend = crate::EguiBackend::new(ctx.clone());
37        let config = egui_wgpu::WgpuConfiguration::default();
38        let mut painter = painter::Painter::new(ctx.clone(), config, 1, None, true, false).await;
39        // SAFETY:
40        // Window lives as long as self
41        unsafe {
42            painter.set_window(viewport_id, &window).await.unwrap();
43        }
44
45        Self {
46            window,
47            ctx,
48            painter,
49            state,
50            backend,
51            viewport_id,
52        }
53    }
54
55    pub fn on_event(&mut self, event: &sdl2::event::Event) -> crate::EventResponse {
56        match event {
57            sdl2::event::Event::Window {
58                window_id,
59                win_event:
60                    sdl2::event::WindowEvent::Resized(w, h)
61                    | sdl2::event::WindowEvent::SizeChanged(w, h),
62                ..
63            } if *window_id == self.window.id() && *w > 0 && *h > 0 => {
64                let w = NonZeroU32::new(*w as u32).unwrap();
65                let h = NonZeroU32::new(*h as u32).unwrap();
66                self.painter.on_window_resized(self.viewport_id, w, h);
67            }
68            _ => {}
69        }
70
71        self.state.on_event(&self.window, event)
72    }
73
74    /// Call [`Self::paint`] later to paint.
75    pub fn run(&mut self, run_ui: impl FnMut(&egui::Context)) {
76        self.backend.run(&mut self.state, run_ui);
77    }
78
79    /// Paint the results of the last call to [`Self::run`].
80    pub fn paint(&mut self, clear_color: [f32; 4]) {
81        let textures_delta = std::mem::take(&mut self.backend.textures_delta);
82        let pixels_per_point = self.backend.pixels_per_point;
83        let shapes = std::mem::take(&mut self.backend.shapes);
84        let clipped_primitives = self.ctx.tessellate(shapes, pixels_per_point);
85        self.painter.paint_and_update_textures(
86            self.viewport_id,
87            pixels_per_point,
88            clear_color,
89            &clipped_primitives,
90            &textures_delta,
91            Vec::with_capacity(0),
92        );
93    }
94}