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