1use std::path::PathBuf;
2
3use dear_imgui_rs::{ConfigFlags, DockNodeFlags, WindowFlags};
4
5#[derive(Clone, Copy, Debug, Default)]
7pub struct AddOnsConfig {
8 pub with_implot: bool,
9 pub with_imnodes: bool,
10 pub with_implot3d: bool,
11}
12
13impl AddOnsConfig {
14 #[must_use]
16 pub const fn auto() -> Self {
17 Self {
18 with_implot: cfg!(feature = "implot"),
19 with_imnodes: cfg!(feature = "imnodes"),
20 with_implot3d: cfg!(feature = "implot3d"),
21 }
22 }
23}
24
25pub struct AppConfig {
27 pub window_title: String,
28 pub window_size: (f64, f64),
29 pub present_mode: wgpu::PresentMode,
30 pub clear_color: [f32; 4],
31 pub wgpu: WgpuConfig,
32 pub docking: DockingConfig,
33 pub addons: AddOnsConfig,
34 pub ini_filename: Option<PathBuf>,
35 pub restore_previous_geometry: bool,
36 pub redraw: RedrawMode,
37 pub io_config_flags: Option<ConfigFlags>,
38 pub theme: Option<Theme>,
39}
40
41impl Default for AppConfig {
42 fn default() -> Self {
43 Self {
44 window_title: format!("Dear ImGui App - {}", env!("CARGO_PKG_VERSION")),
45 window_size: (1280.0, 720.0),
46 present_mode: wgpu::PresentMode::Fifo,
47 clear_color: [0.1, 0.2, 0.3, 1.0],
48 wgpu: WgpuConfig::default(),
49 docking: DockingConfig::default(),
50 addons: AddOnsConfig::default(),
51 ini_filename: None,
52 restore_previous_geometry: true,
53 redraw: RedrawMode::Poll,
54 io_config_flags: None,
55 theme: None,
56 }
57 }
58}
59
60pub struct WgpuConfig {
62 pub backends: wgpu::Backends,
63 pub power_preference: wgpu::PowerPreference,
64 pub force_fallback_adapter: bool,
65 pub device_label: Option<String>,
66 pub required_features: wgpu::Features,
67 pub required_limits: wgpu::Limits,
68 pub memory_hints: wgpu::MemoryHints,
69}
70
71impl Default for WgpuConfig {
72 fn default() -> Self {
73 Self {
74 backends: wgpu::Backends::PRIMARY,
75 power_preference: wgpu::PowerPreference::HighPerformance,
76 force_fallback_adapter: false,
77 device_label: None,
78 required_features: wgpu::Features::empty(),
79 required_limits: wgpu::Limits::default(),
80 memory_hints: wgpu::MemoryHints::default(),
81 }
82 }
83}
84
85#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
87pub enum WgpuPreset {
88 #[default]
89 Default,
90 HighPerformance,
91 LowPower,
92 Balanced,
93 DownlevelCompatible,
94 SoftwareFallback,
95}
96
97impl WgpuConfig {
98 #[must_use]
99 pub fn from_preset(preset: WgpuPreset) -> Self {
100 match preset {
101 WgpuPreset::Default => Self::default(),
102 WgpuPreset::HighPerformance => Self {
103 power_preference: wgpu::PowerPreference::HighPerformance,
104 memory_hints: wgpu::MemoryHints::Performance,
105 ..Self::default()
106 },
107 WgpuPreset::LowPower => Self {
108 power_preference: wgpu::PowerPreference::LowPower,
109 memory_hints: wgpu::MemoryHints::MemoryUsage,
110 ..Self::default()
111 },
112 WgpuPreset::Balanced => Self {
113 power_preference: wgpu::PowerPreference::None,
114 ..Self::default()
115 },
116 WgpuPreset::DownlevelCompatible => Self {
117 power_preference: wgpu::PowerPreference::None,
118 required_limits: wgpu::Limits::downlevel_defaults(),
119 ..Self::default()
120 },
121 WgpuPreset::SoftwareFallback => Self {
122 power_preference: wgpu::PowerPreference::None,
123 force_fallback_adapter: true,
124 required_limits: wgpu::Limits::downlevel_defaults(),
125 ..Self::default()
126 },
127 }
128 }
129}
130
131#[derive(Default)]
136pub enum DockingConfig {
137 #[default]
139 Disabled,
140 ApplicationManaged { dockspace_flags: DockNodeFlags },
142 FullViewport {
144 dockspace_flags: DockNodeFlags,
145 host_window_flags: WindowFlags,
146 host_window_name: String,
147 },
148}
149
150impl DockingConfig {
151 #[must_use]
153 pub fn application_managed() -> Self {
154 Self::ApplicationManaged {
155 dockspace_flags: DockNodeFlags::PASSTHRU_CENTRAL_NODE,
156 }
157 }
158
159 #[must_use]
161 pub fn full_viewport() -> Self {
162 Self::FullViewport {
163 dockspace_flags: DockNodeFlags::PASSTHRU_CENTRAL_NODE,
164 host_window_flags: WindowFlags::NO_TITLE_BAR
165 | WindowFlags::NO_RESIZE
166 | WindowFlags::NO_MOVE
167 | WindowFlags::NO_COLLAPSE
168 | WindowFlags::NO_BRING_TO_FRONT_ON_FOCUS
169 | WindowFlags::NO_NAV_FOCUS,
170 host_window_name: "DockSpaceHost".to_owned(),
171 }
172 }
173
174 #[must_use]
175 pub const fn is_enabled(&self) -> bool {
176 !matches!(self, Self::Disabled)
177 }
178
179 pub(crate) fn dockspace_flags(&self) -> DockNodeFlags {
180 match self {
181 Self::Disabled => DockNodeFlags::empty(),
182 Self::ApplicationManaged { dockspace_flags }
183 | Self::FullViewport {
184 dockspace_flags, ..
185 } => DockNodeFlags::from_bits_retain(dockspace_flags.bits()),
186 }
187 }
188
189 pub(crate) fn full_viewport_host(&self) -> Option<(&str, WindowFlags)> {
190 match self {
191 Self::FullViewport {
192 host_window_flags,
193 host_window_name,
194 ..
195 } => Some((
196 host_window_name,
197 WindowFlags::from_bits_retain(host_window_flags.bits()),
198 )),
199 Self::Disabled | Self::ApplicationManaged { .. } => None,
200 }
201 }
202}
203
204#[derive(Clone, Copy, Debug)]
205pub enum RedrawMode {
206 Poll,
207 Wait,
208 WaitUntil { fps: f32 },
209}
210
211#[derive(Clone, Copy, Debug)]
212pub enum Theme {
213 Dark,
214 Light,
215 Classic,
216}
217
218#[cfg(test)]
219mod tests {
220 use super::{AppConfig, DockingConfig};
221
222 #[test]
223 fn default_app_does_not_enable_docking() {
224 assert!(!AppConfig::default().docking.is_enabled());
225 }
226
227 #[test]
228 fn docking_modes_assign_dockspace_ownership_explicitly() {
229 let application_managed = DockingConfig::application_managed();
230 let full_viewport = DockingConfig::full_viewport();
231
232 assert!(application_managed.is_enabled());
233 assert!(application_managed.full_viewport_host().is_none());
234 assert!(full_viewport.is_enabled());
235 assert!(full_viewport.full_viewport_host().is_some());
236 }
237}