imgui_sdl3/
lib.rs

1//! # Getting started
2//!
3//! ```rust,no_run
4//! use imgui_sdl3::ImGuiSdl3;
5//! use sdl3::{event::Event, gpu::*, pixels::Color};
6//!
7//! fn main() -> Result<(), Box<dyn std::error::Error>> {
8//!     // initialize SDL and its video subsystem
9//!     let mut sdl = sdl3::init().unwrap();
10//!     let video_subsystem = sdl.video().unwrap();
11//!
12//!     // create a new window
13//!     let window = video_subsystem
14//!         .window("Hello imgui-rs!", 1280, 720)
15//!         .position_centered()
16//!         .resizable()
17//!         .build()
18//!         .unwrap();
19//!
20//!     let device = Device::new(ShaderFormat::SPIRV, true)
21//!         .unwrap()
22//!         .with_window(&window)
23//!         .unwrap();
24//!
25//!     // create platform and renderer
26//!     let mut imgui = ImGuiSdl3::new(&device, &window, |ctx| {
27//!         // disable creation of files on disc
28//!         ctx.set_ini_filename(None);
29//!         ctx.set_log_filename(None);
30//!
31//!         // setup platform and renderer, and fonts to imgui
32//!         ctx.fonts()
33//!             .add_font(&[imgui::FontSource::DefaultFontData { config: None }]);
34//!     });
35//!
36//!     // start main loop
37//!     let mut event_pump = sdl.event_pump().unwrap();
38//!
39//!     'main: loop {
40//!         for event in event_pump.poll_iter() {
41//!             // pass all events to imgui platform
42//!             imgui.handle_event(&event);
43//!
44//!             if let Event::Quit { .. } = event {
45//!                 break 'main;
46//!             }
47//!         }
48//!
49//!         let mut command_buffer = device.acquire_command_buffer()?;
50//!
51//!         if let Ok(swapchain) = command_buffer.wait_and_acquire_swapchain_texture(&window) {
52//!             let color_targets = [ColorTargetInfo::default()
53//!                 .with_texture(&swapchain)
54//!                 .with_load_op(LoadOp::CLEAR)
55//!                 .with_store_op(StoreOp::STORE)
56//!                 .with_clear_color(Color::RGB(128, 128, 128))];
57//!
58//!             imgui.render(
59//!                 &mut sdl,
60//!                 &device,
61//!                 &window,
62//!                 &event_pump,
63//!                 &mut command_buffer,
64//!                 &color_targets,
65//!                 |ui| {
66//!                     // create imgui UI here
67//!                     ui.show_demo_window(&mut true);
68//!                 },
69//!             );
70//!
71//!             command_buffer.submit()?;
72//!         } else {
73//!             println!("Swapchain unavailable, cancel work");
74//!             command_buffer.cancel();
75//!         }
76//!     }
77//!
78//!     Ok(())
79//! }
80//! ```
81//!
82//! # Feature Flags
83//!
84//! | Name                | Description                          |
85//! |---------------------|--------------------------------------|
86//! | `imoguizmo`         | Add an interactive orientation gizmo |
87
88#![crate_name = "imgui_sdl3"]
89#![crate_type = "lib"]
90
91#[cfg(feature = "imoguizmo")]
92pub mod imoguizmo;
93pub mod platform;
94pub mod renderer;
95pub mod utils;
96use platform::Platform;
97use renderer::Renderer;
98use sdl3::gpu::*;
99
100/// Main integration point for using Dear ImGui with SDL3 + GPU rendering
101pub struct ImGuiSdl3 {
102    imgui_context: imgui::Context, // Dear ImGui context (state, configuration, fonts, etc.)
103    platform: Platform,            // Handles SDL3 platform event integration
104    renderer: Renderer,            // Handles GPU rendering of ImGui draw data
105}
106
107impl ImGuiSdl3 {
108    /// Create a new ImGuiSdl3 instance
109    ///
110    /// - `device`: GPU device handle from SDL3
111    /// - `window`: SDL3 window reference
112    /// - `ctx_configure`: Closure to configure the ImGui context (fonts, styles, etc.)
113    pub fn new<T>(device: &sdl3::gpu::Device, window: &sdl3::video::Window, ctx_configure: T) -> Self
114    where
115        T: Fn(&mut imgui::Context), // Allows custom configuration of the ImGui context
116    {
117        // Create a fresh Dear ImGui context
118        let mut imgui_context = imgui::Context::create();
119
120        // Apply user-provided configuration to the context
121        ctx_configure(&mut imgui_context);
122
123        // Set up SDL3 platform integration (input handling, DPI scaling, etc.)
124        let platform = Platform::new(&mut imgui_context);
125
126        // Set up the GPU renderer for drawing ImGui's UI
127        let renderer = Renderer::new(device, window, &mut imgui_context).unwrap();
128
129        Self {
130            imgui_context,
131            platform,
132            renderer,
133        }
134    }
135
136    /// Pass SDL3 events to ImGui so it can handle inputs (mouse, keyboard, etc.)
137    pub fn handle_event(&mut self, event: &sdl3::event::Event) {
138        self.platform.handle_event(&mut self.imgui_context, event);
139    }
140
141    /// Render an ImGui frame
142    ///
143    /// - `sdl_context`: SDL3 main context
144    /// - `device`: GPU device handle
145    /// - `window`: SDL3 window reference
146    /// - `event_pump`: SDL3 event pump for polling events
147    /// - `command_buffer`: GPU command buffer for recording draw commands
148    /// - `color_targets`: Color target attachments for rendering
149    /// - `draw_callback`: Closure to build the UI each frame
150    #[allow(clippy::too_many_arguments)]
151    pub fn render<T>(
152        &mut self,
153        sdl_context: &mut sdl3::Sdl,
154        device: &sdl3::gpu::Device,
155        window: &sdl3::video::Window,
156        event_pump: &sdl3::EventPump,
157        command_buffer: &mut CommandBuffer,
158        color_targets: &[ColorTargetInfo],
159        mut draw_callback: T,
160    ) where
161        T: FnMut(&mut imgui::Ui), // Function that takes a mutable reference to the UI builder
162    {
163        // Prepare ImGui for a new frame (update input state, time step, etc.)
164        self.platform
165            .prepare_frame(sdl_context, &mut self.imgui_context, window, event_pump);
166
167        // Start a new ImGui frame and get the UI object
168        let ui = self.imgui_context.new_frame();
169
170        // Call the user-provided draw function to build the UI
171        draw_callback(ui);
172
173        // Render the ImGui draw data to the GPU
174        self.renderer
175            .render(device, command_buffer, color_targets, &mut self.imgui_context)
176            .unwrap();
177    }
178}