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#![crate_name = "imgui_sdl3"]
83#![crate_type = "lib"]
84
85pub mod platform;
86pub mod renderer;
87pub mod utils;
88use platform::Platform;
89use renderer::Renderer;
90use sdl3::gpu::*;
91
92/// Main integration point for using Dear ImGui with SDL3 + GPU rendering
93pub struct ImGuiSdl3 {
94 imgui_context: imgui::Context, // Dear ImGui context (state, configuration, fonts, etc.)
95 platform: Platform, // Handles SDL3 platform event integration
96 renderer: Renderer, // Handles GPU rendering of ImGui draw data
97}
98
99impl ImGuiSdl3 {
100 /// Create a new ImGuiSdl3 instance
101 ///
102 /// - `device`: GPU device handle from SDL3
103 /// - `window`: SDL3 window reference
104 /// - `ctx_configure`: Closure to configure the ImGui context (fonts, styles, etc.)
105 pub fn new<T>(device: &sdl3::gpu::Device, window: &sdl3::video::Window, ctx_configure: T) -> Self
106 where
107 T: Fn(&mut imgui::Context), // Allows custom configuration of the ImGui context
108 {
109 // Create a fresh Dear ImGui context
110 let mut imgui_context = imgui::Context::create();
111
112 // Apply user-provided configuration to the context
113 ctx_configure(&mut imgui_context);
114
115 // Set up SDL3 platform integration (input handling, DPI scaling, etc.)
116 let platform = Platform::new(&mut imgui_context);
117
118 // Set up the GPU renderer for drawing ImGui's UI
119 let renderer = Renderer::new(device, window, &mut imgui_context).unwrap();
120
121 Self {
122 imgui_context,
123 platform,
124 renderer,
125 }
126 }
127
128 /// Pass SDL3 events to ImGui so it can handle inputs (mouse, keyboard, etc.)
129 pub fn handle_event(&mut self, event: &sdl3::event::Event) {
130 self.platform.handle_event(&mut self.imgui_context, event);
131 }
132
133 /// Render an ImGui frame
134 ///
135 /// - `sdl_context`: SDL3 main context
136 /// - `device`: GPU device handle
137 /// - `window`: SDL3 window reference
138 /// - `event_pump`: SDL3 event pump for polling events
139 /// - `command_buffer`: GPU command buffer for recording draw commands
140 /// - `color_targets`: Color target attachments for rendering
141 /// - `draw_callback`: Closure to build the UI each frame
142 #[allow(clippy::too_many_arguments)]
143 pub fn render<T>(
144 &mut self,
145 sdl_context: &mut sdl3::Sdl,
146 device: &sdl3::gpu::Device,
147 window: &sdl3::video::Window,
148 event_pump: &sdl3::EventPump,
149 command_buffer: &mut CommandBuffer,
150 color_targets: &[ColorTargetInfo],
151 mut draw_callback: T,
152 ) where
153 T: FnMut(&mut imgui::Ui), // Function that takes a mutable reference to the UI builder
154 {
155 // Prepare ImGui for a new frame (update input state, time step, etc.)
156 self.platform
157 .prepare_frame(sdl_context, &mut self.imgui_context, window, event_pump);
158
159 // Start a new ImGui frame and get the UI object
160 let ui = self.imgui_context.new_frame();
161
162 // Call the user-provided draw function to build the UI
163 draw_callback(ui);
164
165 // Render the ImGui draw data to the GPU
166 self.renderer
167 .render(device, command_buffer, color_targets, &mut self.imgui_context)
168 .unwrap();
169 }
170}