From 7752a009fe111bb0ef2ee8f2fc3fceba605136dc Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 28 Jul 2026 20:41:48 +0300 Subject: [PATCH] Add window mode setting --- rust/src/game_settings.rs | 33 ++++++++++++++++-- rust/src/ui/settings.rs | 72 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/rust/src/game_settings.rs b/rust/src/game_settings.rs index 5e632a6..0595f03 100644 --- a/rust/src/game_settings.rs +++ b/rust/src/game_settings.rs @@ -5,8 +5,8 @@ use std::{ use godot::{ classes::{ - AudioServer, FileAccess, InputEvent, InputEventKey, InputEventMouseButton, InputMap, - file_access::ModeFlags, + AudioServer, DisplayServer, FileAccess, InputEvent, InputEventKey, InputEventMouseButton, + InputMap, display_server::WindowMode, file_access::ModeFlags, }, global::{Key, MouseButton}, prelude::*, @@ -26,6 +26,7 @@ pub struct GameSettings { pub fov: f64, pub default_name: String, pub replay_fps: u8, + pub window_mode: WindowModeSetting, pub recent_servers: Vec, pub volume: VolumeSettings, pub keybinds: KeybindSettings, @@ -53,6 +54,26 @@ pub struct KeybindSettings { pub telegrenade: Keybind, } +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, PartialOrd)] +pub enum WindowModeSetting { + Fullscreen = 0, + BorderlessFullscreen, + Windowed, +} + +impl TryFrom for WindowModeSetting { + type Error = (); + + fn try_from(value: usize) -> Result { + match value { + 0 => Ok(WindowModeSetting::Fullscreen), + 1 => Ok(WindowModeSetting::BorderlessFullscreen), + 2 => Ok(WindowModeSetting::Windowed), + _ => Err(()), + } + } +} + #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, PartialOrd)] pub enum Keybind { Key(i32), @@ -125,6 +146,7 @@ impl Default for GameSettings { fov: 90., default_name: "Default McGee".to_owned(), replay_fps: 60, + window_mode: WindowModeSetting::Windowed, recent_servers: Vec::new(), volume: VolumeSettings { master_volume: 100., @@ -194,6 +216,13 @@ impl GameSettingsManager { set_keybind("jump", settings.keybinds.jump); set_keybind("throw_telegrenade", settings.keybinds.telegrenade); + let window_mode = match settings.window_mode { + WindowModeSetting::Fullscreen => WindowMode::EXCLUSIVE_FULLSCREEN, + WindowModeSetting::BorderlessFullscreen => WindowMode::EXCLUSIVE_FULLSCREEN, + WindowModeSetting::Windowed => WindowMode::WINDOWED, + }; + DisplayServer::singleton().window_set_mode(window_mode); + self.settings = settings; if let Some(mut file) = FileAccess::open("user://config.toml", ModeFlags::WRITE) { if let Ok(serialized) = toml::to_string(&self.settings) { diff --git a/rust/src/ui/settings.rs b/rust/src/ui/settings.rs index b35c5bd..5d14dbb 100644 --- a/rust/src/ui/settings.rs +++ b/rust/src/ui/settings.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use godot::{ classes::{ - Button, Control, GridContainer, IPanelContainer, InputEvent, Label, LineEdit, + Button, Control, GridContainer, IPanelContainer, InputEvent, Label, LineEdit, OptionButton, PanelContainer, control::{FocusBehaviorRecursive, SizeFlags}, }, @@ -10,7 +10,7 @@ use godot::{ }; use crate::{ - game_settings::{GameSettings, GameSettingsManager, Keybind}, + game_settings::{GameSettings, GameSettingsManager, Keybind, WindowModeSetting}, ui::slider::SliderContainer, }; @@ -20,6 +20,7 @@ pub enum Setting { FoV, DefaultName, ReplayFPS, + WindowMode, // Volume settings MasterVolume, @@ -52,6 +53,7 @@ impl ToString for Setting { Setting::FoV => "Field of View", Setting::DefaultName => "Default Name", Setting::ReplayFPS => "Replay FPS", + Setting::WindowMode => "Window Mode", Setting::MasterVolume => "Master volume", Setting::SfxVolume => "Sfx Volume", @@ -79,6 +81,7 @@ impl Setting { Setting::FoV => SettingsTab::General, Setting::DefaultName => SettingsTab::General, Setting::ReplayFPS => SettingsTab::General, + Setting::WindowMode => SettingsTab::General, Setting::MasterVolume => SettingsTab::Volume, Setting::SfxVolume => SettingsTab::Volume, @@ -95,6 +98,13 @@ pub enum SettingValue { SliderNumber(SliderValue), String(String), Keybind(Keybind), + OptionSetting(usize, Vec), +} + +#[derive(Clone, Debug, PartialEq, PartialOrd)] +pub struct OptionSetting { + value: usize, + text: String, } #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] @@ -237,6 +247,30 @@ impl IPanelContainer for SettingsPanel { toggle_button.upcast() } + SettingValue::OptionSetting(value, items) => { + let mut option_button = OptionButton::new_alloc(); + for item in &items { + option_button.add_item(&item.text); + } + option_button.select(value as i32); + + let setting_clone = setting.clone(); + let items_clone = items.clone(); + option_button.signals().item_selected().connect_other( + self, + move |s, i| { + s.on_change( + setting_clone, + SettingValue::OptionSetting( + i as usize, + items_clone.clone(), + ), + ); + }, + ); + + option_button.upcast() + } }; self.values.insert(*setting, node.clone()); @@ -283,6 +317,11 @@ impl SettingsPanel { self.on_change(setting, new_value); } } + SettingValue::OptionSetting(selected, _) => { + if let Ok(mut button) = control.try_cast::() { + button.select(selected as i32); + } + } } } } @@ -308,6 +347,13 @@ impl SettingsPanel { (Setting::ReplayFPS, SettingValue::SliderNumber(value)) => { new_settings.replay_fps = value.value as u8; } + (Setting::WindowMode, SettingValue::OptionSetting(selected, items)) => { + if let Some(item) = items.get(*selected) { + if let Ok(setting) = WindowModeSetting::try_from(item.value) { + new_settings.window_mode = setting; + } + } + } (Setting::MasterVolume, SettingValue::SliderNumber(value)) => { new_settings.volume.master_volume = value.value; @@ -389,9 +435,29 @@ fn settings_from(map: &mut HashMap, settings: &GameSettin SettingValue::SliderNumber(SliderValue { min: 1., max: 240., - value: 60., + value: settings.replay_fps as f64, }), ); + map.insert( + Setting::WindowMode, + SettingValue::OptionSetting( + settings.window_mode as usize, + vec![ + OptionSetting { + value: WindowModeSetting::Fullscreen as usize, + text: "Fullscreen".to_string(), + }, + OptionSetting { + value: WindowModeSetting::BorderlessFullscreen as usize, + text: "Borderless Fullscreen".to_string(), + }, + OptionSetting { + value: WindowModeSetting::Windowed as usize, + text: "Windowed".to_string(), + }, + ], + ), + ); map.insert( Setting::MasterVolume, SettingValue::SliderNumber(SliderValue {