diff options
| author | Micha White <botahamec@outlook.com> | 2022-09-18 13:49:35 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2022-09-18 13:49:35 -0400 |
| commit | b92e827eb623a8d93872c6f95aceeb882b867a29 (patch) | |
| tree | a6024b190ac142f2b10c96fd454fa475278e83ff /src/config.rs | |
| parent | 8f08ff0b62d82bc969aed135b37b864e6b51e0c8 (diff) | |
Reorganized the config
Diffstat (limited to 'src/config.rs')
| -rw-r--r-- | src/config.rs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..1e8c43e --- /dev/null +++ b/src/config.rs @@ -0,0 +1,166 @@ +use std::borrow::Cow; +use std::num::NonZeroU32; + +use winit::dpi::{LogicalPosition, LogicalSize}; +use winit::window::{Fullscreen, WindowBuilder}; + +/// Describes how a window may be resized +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Resizable { + /// The minimum width of the window, or None if unconstrained + pub min_width: Option<NonZeroU32>, + /// The minimum height of the window, or None if unconstrained + pub min_height: Option<NonZeroU32>, + /// The maximum width of the window, or None if unconstrained + pub max_width: Option<NonZeroU32>, + /// The maximum height of the window, or None if unconstrained + pub max_height: Option<NonZeroU32>, +} + +/// Information about a window, that is not fullscreened +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct WindowInfo { + pub default_x: i32, + pub default_y: i32, + pub resizable: Option<Resizable>, + pub default_maximized: bool, +} + +impl Default for WindowInfo { + fn default() -> Self { + Self { + default_x: 100, + default_y: 100, + resizable: Some(Resizable::default()), + default_maximized: false, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum WindowMode { + Windowed(WindowInfo), + // TODO support choosing a monitor + BorderlessFullscreen, // TODO exclusive fullscreen +} + +impl Default for WindowMode { + fn default() -> Self { + Self::Windowed(WindowInfo::default()) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +// TODO window icon +pub struct RenderWindowConfig<'a> { + /// The width of the window, once initialized + pub default_width: NonZeroU32, + /// The height of the window, once initialized + pub default_height: NonZeroU32, + /// The window may be fullscreen + pub mode: WindowMode, + /// The title for the window + pub title: Cow<'a, str>, + /// If true, a low-power device will be selected as the GPU, if possible + pub low_power: bool, + /// If true, Fifo mode is used to present frames. If false, then Mailbox or + /// Immediate will be used if available. Otherwise, Fifo will be used. + pub vsync: bool, +} + +impl<'a> Default for RenderWindowConfig<'a> { + fn default() -> Self { + Self { + default_width: NonZeroU32::new(640).unwrap(), + default_height: NonZeroU32::new(480).unwrap(), + mode: WindowMode::default(), + title: "Alligator Game".into(), + low_power: true, + vsync: true, + } + } +} + +impl<'a> RenderWindowConfig<'a> { + /// Create a `WindowBuilder` from the configuration given + pub(crate) fn to_window(&self) -> WindowBuilder { + // start building the window + let mut builder = WindowBuilder::new() + .with_title(self.title.as_ref()) + .with_inner_size(LogicalSize::new( + self.default_width.get(), + self.default_height.get(), + )); + + match self.mode { + WindowMode::Windowed(window_info) => { + builder = builder.with_maximized(window_info.default_maximized); + + if let Some(resizing_options) = window_info.resizable { + if resizing_options.max_height.is_some() || resizing_options.max_width.is_some() + { + builder = builder.with_max_inner_size(LogicalSize::new( + resizing_options.max_width.unwrap_or(NonZeroU32::MAX).get(), + resizing_options.max_height.unwrap_or(NonZeroU32::MAX).get(), + )); + } + + if resizing_options.min_height.is_some() || resizing_options.min_width.is_some() + { + builder = builder.with_min_inner_size(LogicalSize::new( + resizing_options.min_width.unwrap_or(NonZeroU32::MAX).get(), + resizing_options.min_height.unwrap_or(NonZeroU32::MAX).get(), + )); + } + } else { + builder = builder.with_resizable(false); + } + + // TODO clamp the position to the monitor's size + builder = builder.with_position(LogicalPosition::new( + window_info.default_x, + window_info.default_y, + )); + } + WindowMode::BorderlessFullscreen => { + builder = builder.with_fullscreen(Some(Fullscreen::Borderless(None))); + } + } + + builder + } + + /// Gets a surface configuration out of the config. + pub(crate) fn to_surface_configuration( + &self, + supported_modes: &[wgpu::PresentMode], + texture_format: wgpu::TextureFormat, + ) -> wgpu::SurfaceConfiguration { + let present_mode = if self.vsync { + wgpu::PresentMode::Fifo + } else if supported_modes.contains(&wgpu::PresentMode::Mailbox) { + wgpu::PresentMode::Mailbox + } else if supported_modes.contains(&wgpu::PresentMode::Immediate) { + wgpu::PresentMode::Immediate + } else { + wgpu::PresentMode::Fifo + }; + + // configuration for the surface + wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: texture_format, + width: self.default_width.get(), + height: self.default_height.get(), + present_mode, + } + } + + pub(crate) const fn power_preference(&self) -> wgpu::PowerPreference { + if self.low_power { + wgpu::PowerPreference::LowPower + } else { + wgpu::PowerPreference::HighPerformance + } + } +} |
