summaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
authorMicha White <botahamec@outlook.com>2022-09-18 13:49:35 -0400
committerMicha White <botahamec@outlook.com>2022-09-18 13:49:35 -0400
commitb92e827eb623a8d93872c6f95aceeb882b867a29 (patch)
treea6024b190ac142f2b10c96fd454fa475278e83ff /src/config.rs
parent8f08ff0b62d82bc969aed135b37b864e6b51e0c8 (diff)
Reorganized the config
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs166
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
+ }
+ }
+}