diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index 2da1be3..08b9397 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -8,6 +8,13 @@ use winit::{ }; use crate::settings::{GameSettings, FullscreenMode}; +const fn get_vsync_mode(vsync: bool) -> wgpu::PresentMode { + match vsync { + true => wgpu::PresentMode::AutoVsync, + false => wgpu::PresentMode::AutoNoVsync, + } +} + #[derive(Unique)] pub struct Renderer { window: Arc, @@ -116,12 +123,26 @@ impl Renderer { None, ).block_on().unwrap(); - let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); + let mut surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); + surface_config.present_mode = get_vsync_mode(settings.vsync); surface.configure(&device, &surface_config); Self { window, instance, surface, device, queue, surface_config, size } } + pub fn reload_settings(&mut self, settings: &GameSettings) { + // TODO update fullscreen mode + + let mut should_reconfigure = false; + + should_reconfigure |= get_vsync_mode(settings.vsync) != self.surface_config.present_mode; + self.surface_config.present_mode = get_vsync_mode(settings.vsync); + + if should_reconfigure { + self.reconfigure(); + } + } + pub fn resize(&mut self, size: PhysicalSize) { if size.width == 0 || size.height == 0 { log::warn!("Ignoring resize event with zero width or height"); @@ -135,7 +156,7 @@ impl Renderer { self.size = size; self.surface_config.width = size.width; self.surface_config.height = size.height; - self.surface.configure(&self.device, &self.surface_config); + self.reconfigure(); } pub fn reconfigure(&self) { diff --git a/kubi/src/settings.rs b/kubi/src/settings.rs index 9a83be3..9b98fcd 100644 --- a/kubi/src/settings.rs +++ b/kubi/src/settings.rs @@ -11,7 +11,7 @@ pub struct FullscreenSettings { #[derive(Unique)] pub struct GameSettings { - // pub vsync: bool, + pub vsync: bool, pub fullscreen: Option, // pub msaa: Option, // pub max_anisotropy: Option, @@ -24,7 +24,7 @@ pub struct GameSettings { impl Default for GameSettings { fn default() -> Self { Self { - // vsync: false, + vsync: true, fullscreen: None, // msaa: Some(4), // max_anisotropy: Some(16), diff --git a/kubi/src/ui/settings_ui.rs b/kubi/src/ui/settings_ui.rs index 6211c6d..f25b517 100644 --- a/kubi/src/ui/settings_ui.rs +++ b/kubi/src/ui/settings_ui.rs @@ -1,24 +1,74 @@ use hui::{ - element::{br::Break, container::Container, slider::Slider, text::Text, UiElementExt}, + element::{br::Break, container::Container, slider::Slider, text::Text, ElementList, UiElementExt}, layout::{Alignment, Direction}, signal::Signal, - rect_frame, size, + rect_frame, + size, }; use shipyard::{NonSendSync, UniqueView, UniqueViewMut}; use winit::keyboard::KeyCode; -use crate::{hui_integration::UiState, input::RawKbmInputState, rendering::Renderer, settings::GameSettings}; +use crate::{ + hui_integration::UiState, + input::RawKbmInputState, + rendering::Renderer, + settings::GameSettings +}; #[derive(Signal)] enum SettingsSignal { SetRenderDistance(u8), SetEnableDynamicCrosshair(bool), + SetEnableVsync(bool), SetEnableDebugChunkBorder(bool), SetMouseSensitivity(f32), } +// hUI doesn't have a checkbox element yet +// so we'll have to use sliders for now +fn checkbox( + ui: &mut ElementList, + text: &'static str, + value: bool, + signal: impl Fn(bool) -> SettingsSignal + 'static, +) { + const WIDTH: f32 = 50.; + const HEIGHT: f32 = WIDTH / 2.; + const TRACK_HEIGHT_RATIO: f32 = 0.75; + + Container::default() + .with_direction(Direction::Horizontal) + .with_align(Alignment::Center) + .with_gap(5.) + .with_children(|ui| { + Text::new(text) + .add_child(ui); + Slider::new(value as u32 as f32) + .with_size(size!(WIDTH, HEIGHT)) + .with_track_height(TRACK_HEIGHT_RATIO) + .with_track(rect_frame! { + color: (0.5, 0.5, 0.5), + corner_radius: TRACK_HEIGHT_RATIO * HEIGHT * 0.5, + }) + .with_track_active(rect_frame! { + color: (0., 0., 0.75), + corner_radius: TRACK_HEIGHT_RATIO * HEIGHT * 0.5, + }) + .with_handle_size((25., 1.)) + .with_handle(rect_frame! { + color: (0., 0., 1.), + corner_radius: HEIGHT * 0.5, + }) + .on_change(move |f| signal(f >= 0.5)) + .add_child(ui); + Text::new(if value { "On" } else { "Off" }) + .add_child(ui); + }) + .add_child(ui); +} + pub fn render_settings_ui( mut ui: NonSendSync>, - ren: UniqueView, + mut ren: UniqueViewMut, mut settings: UniqueViewMut, kbd: UniqueView, ) { @@ -64,28 +114,28 @@ pub fn render_settings_ui( .add_child(ui); Break.add_child(ui); - Text::new("Dynamic Crosshair") - .add_child(ui); - Slider::new(settings.dynamic_crosshair as u32 as f32) - .with_size(size!(50, auto)) - .with_track_height(1.) - .with_handle_size((25., 1.)) - .on_change(|f| SettingsSignal::SetEnableDynamicCrosshair(f >= 0.5)) - .add_child(ui); - Text::new(if settings.dynamic_crosshair { "On" } else { "Off" }) - .add_child(ui); + checkbox( + ui, + "Vsync", + settings.vsync, + SettingsSignal::SetEnableVsync + ); Break.add_child(ui); - Text::new("Enable debug chunk border") - .add_child(ui); - Slider::new(settings.debug_draw_current_chunk_border as u32 as f32) - .with_size(size!(50, (Slider::DEFAULT_HEIGHT))) - .with_track_height(1.) - .with_handle_size((25., 1.)) - .on_change(|f| SettingsSignal::SetEnableDebugChunkBorder(f >= 0.5)) - .add_child(ui); - Text::new(if settings.debug_draw_current_chunk_border { "On" } else { "Off" }) - .add_child(ui); + checkbox( + ui, + "Dynamic Crosshair", + settings.dynamic_crosshair, + SettingsSignal::SetEnableDynamicCrosshair + ); + Break.add_child(ui); + + checkbox( + ui, + "Debug Chunk Border", + settings.debug_draw_current_chunk_border, + SettingsSignal::SetEnableDebugChunkBorder + ); Break.add_child(ui); Text::new("Mouse Sensitivity") @@ -104,6 +154,10 @@ pub fn render_settings_ui( ui.hui.process_signals(|signal: SettingsSignal| match signal { SettingsSignal::SetRenderDistance(value) => settings.render_distance = value, SettingsSignal::SetEnableDynamicCrosshair(value) => settings.dynamic_crosshair = value, + SettingsSignal::SetEnableVsync(value) => { + settings.vsync = value; + ren.reload_settings(&settings); + }, SettingsSignal::SetEnableDebugChunkBorder(value) => settings.debug_draw_current_chunk_border = value && cfg!(not(target_os = "android")), SettingsSignal::SetMouseSensitivity(value) => settings.mouse_sensitivity = value, });