From 84683ded869fdef4b5acf09ba89aa19a946a4427 Mon Sep 17 00:00:00 2001 From: Observer KRypt0n_ Date: Thu, 2 Mar 2023 15:31:21 +0200 Subject: [PATCH] feat(ui): added gamescope settings support Added gamescope settings support. As well made gamemode and gamescope switches non-sensitive if needed packages aren't installed --- Cargo.lock | 2 +- anime-launcher-sdk | 2 +- assets/locales/de/enhancements.ftl | 4 + assets/locales/de/gamescope.ftl | 6 + assets/locales/de/main.ftl | 3 + assets/locales/en/enhancements.ftl | 4 + assets/locales/en/gamescope.ftl | 6 + assets/locales/en/main.ftl | 3 + assets/locales/ru/enhancements.ftl | 4 + assets/locales/ru/gamescope.ftl | 6 + assets/locales/ru/main.ftl | 3 + src/ui/about.rs | 5 +- src/ui/preferences/enhancements.rs | 70 ++++++++- src/ui/preferences/gamescope.rs | 243 +++++++++++++++++++++++++++++ src/ui/preferences/main.rs | 2 + src/ui/preferences/mod.rs | 1 + 16 files changed, 357 insertions(+), 7 deletions(-) create mode 100644 assets/locales/de/gamescope.ftl create mode 100644 assets/locales/en/gamescope.ftl create mode 100644 assets/locales/ru/gamescope.ftl create mode 100644 src/ui/preferences/gamescope.rs diff --git a/Cargo.lock b/Cargo.lock index 75027f3..52a530d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "anime-launcher-sdk" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anime-game-core", "anyhow", diff --git a/anime-launcher-sdk b/anime-launcher-sdk index e662699..f1f8eb6 160000 --- a/anime-launcher-sdk +++ b/anime-launcher-sdk @@ -1 +1 @@ -Subproject commit e662699b992108c50602944647cded05df6beba9 +Subproject commit f1f8eb6a2cc2d61dc8a2fa02051bd5ab2c400338 diff --git a/assets/locales/de/enhancements.ftl b/assets/locales/de/enhancements.ftl index 7686cd7..3839fce 100644 --- a/assets/locales/de/enhancements.ftl +++ b/assets/locales/de/enhancements.ftl @@ -24,6 +24,9 @@ performance = Leistung gamemode = Gamemode gamemode-description = Dem Spiel den Vorrang vor den übrigen Prozessen geben +gamescope = Gamescope +gamescope-description = Gamescope is a tool from Valve that allows for games to run in an isolated Xwayland instance and supports AMD, Intel, and Nvidia GPUs + fps-unlocker = FPS Freischalter enabled = Aktiviert @@ -36,6 +39,7 @@ monitor = Monitor monitor-description = Nummer des Monitors, auf dem das Spiel laufen soll window-mode = Fenster Modus +borderless = Borderless popup = Popup fullscreen = Vollbild diff --git a/assets/locales/de/gamescope.ftl b/assets/locales/de/gamescope.ftl new file mode 100644 index 0000000..c5d96fe --- /dev/null +++ b/assets/locales/de/gamescope.ftl @@ -0,0 +1,6 @@ +game-resolution = Game resolution +gamescope-resolution = Gamescope resolution +other-settings = Other settings +framerate-limit = Framerate limit +unfocused-framerate-limit = Unfocused framerate limit +integer-scaling = Integer scaling diff --git a/assets/locales/de/main.ftl b/assets/locales/de/main.ftl index dfde5a0..9046d54 100644 --- a/assets/locales/de/main.ftl +++ b/assets/locales/de/main.ftl @@ -3,6 +3,9 @@ none = Kein default = Standard details = Einzelheiten +width = Width +height = Height + # Menu items launcher-folder = Launcher-Ordner diff --git a/assets/locales/en/enhancements.ftl b/assets/locales/en/enhancements.ftl index 6fa4476..dbf44fc 100644 --- a/assets/locales/en/enhancements.ftl +++ b/assets/locales/en/enhancements.ftl @@ -24,6 +24,9 @@ performance = Performance gamemode = Gamemode gamemode-description = Prioritize the game over the rest of the processes +gamescope = Gamescope +gamescope-description = Gamescope is a tool from Valve that allows for games to run in an isolated Xwayland instance and supports AMD, Intel, and Nvidia GPUs + fps-unlocker = FPS Unlocker enabled = Enabled @@ -36,6 +39,7 @@ monitor = Monitor monitor-description = Number of monitor you want to run the game on window-mode = Window Mode +borderless = Borderless popup = Popup fullscreen = Fullscreen diff --git a/assets/locales/en/gamescope.ftl b/assets/locales/en/gamescope.ftl new file mode 100644 index 0000000..c5d96fe --- /dev/null +++ b/assets/locales/en/gamescope.ftl @@ -0,0 +1,6 @@ +game-resolution = Game resolution +gamescope-resolution = Gamescope resolution +other-settings = Other settings +framerate-limit = Framerate limit +unfocused-framerate-limit = Unfocused framerate limit +integer-scaling = Integer scaling diff --git a/assets/locales/en/main.ftl b/assets/locales/en/main.ftl index 15e0137..ba6342e 100644 --- a/assets/locales/en/main.ftl +++ b/assets/locales/en/main.ftl @@ -3,6 +3,9 @@ none = None default = Default details = Details +width = Width +height = Height + # Menu items launcher-folder = Launcher folder diff --git a/assets/locales/ru/enhancements.ftl b/assets/locales/ru/enhancements.ftl index fc85c04..96a34eb 100644 --- a/assets/locales/ru/enhancements.ftl +++ b/assets/locales/ru/enhancements.ftl @@ -24,6 +24,9 @@ performance = Скорость gamemode = Gamemode gamemode-description = Выделять игре приоритет перед остальными процессами +gamescope = Gamescope +gamescope-description = Программа от Valve, позволяющая запускать игры в изолированном окружении Xwayland и поддерживает видеокарты от AMD, Intel, и Nvidia + fps-unlocker = FPS Unlocker enabled = Включен @@ -36,6 +39,7 @@ monitor = Монитор monitor-description = Номер монитора, на котором стоит запустить игру window-mode = Режим окна +borderless = Безрамочный popup = Всплывающий fullscreen = Полноэкранный diff --git a/assets/locales/ru/gamescope.ftl b/assets/locales/ru/gamescope.ftl new file mode 100644 index 0000000..95d6ee3 --- /dev/null +++ b/assets/locales/ru/gamescope.ftl @@ -0,0 +1,6 @@ +game-resolution = Разрешение игры +gamescope-resolution = Разрешение Gamescope +other-settings = Другие настройки +framerate-limit = Лимит числа кадров +unfocused-framerate-limit = Лимит числа кадров вне фокуса +integer-scaling = Целочисленное масштабирование diff --git a/assets/locales/ru/main.ftl b/assets/locales/ru/main.ftl index 0992c80..696a3de 100644 --- a/assets/locales/ru/main.ftl +++ b/assets/locales/ru/main.ftl @@ -3,6 +3,9 @@ none = Нет default = По умолчанию details = Подробнее +width = Ширина +height = Высота + # Menu items launcher-folder = Папка лаунчера diff --git a/src/ui/about.rs b/src/ui/about.rs index 66acfde..f5b116f 100644 --- a/src/ui/about.rs +++ b/src/ui/about.rs @@ -2,6 +2,7 @@ use relm4::prelude::*; use gtk::prelude::*; +use anime_launcher_sdk::VERSION as SDK_VERSION; use anime_launcher_sdk::anime_game_core::{VERSION as CORE_VERSION, curl_sys}; lazy_static::lazy_static! { @@ -65,7 +66,9 @@ impl SimpleComponent for AboutDialog { ].join("\n"), set_debug_info: &[ - format!("Anime Game core: {CORE_VERSION}"), + format!("Anime Launcher SDK: {SDK_VERSION}"), + format!("Anime Game Core: {CORE_VERSION}"), + String::new(), format!("curl: {}", CURL_INFO.version()), format!("SSL: {}", CURL_INFO.ssl_version().unwrap_or("?")), String::new(), diff --git a/src/ui/preferences/enhancements.rs b/src/ui/preferences/enhancements.rs index 1e7cbd6..5be9291 100644 --- a/src/ui/preferences/enhancements.rs +++ b/src/ui/preferences/enhancements.rs @@ -5,16 +5,27 @@ use adw::prelude::*; use anime_launcher_sdk::config; use anime_launcher_sdk::config::prelude::*; +use anime_launcher_sdk::is_available; use crate::i18n::tr; use crate::*; -pub struct EnhancementsApp; +use super::gamescope::*; + +pub struct EnhancementsApp { + gamescope: AsyncController +} + +#[derive(Debug)] +pub enum EnhancementsAppMsg { + SetGamescopeParent(adw::PreferencesWindow), + OpenGamescope +} #[relm4::component(async, pub)] impl SimpleAsyncComponent for EnhancementsApp { type Init = (); - type Input = (); + type Input = EnhancementsAppMsg; type Output = (); view! { @@ -227,6 +238,8 @@ impl SimpleAsyncComponent for EnhancementsApp { set_title: &tr("gamemode"), set_subtitle: &tr("gamemode-description"), + set_sensitive: is_available("gamemoderun"), + add_suffix = >k::Switch { set_valign: gtk::Align::Center, @@ -237,6 +250,38 @@ impl SimpleAsyncComponent for EnhancementsApp { if let Ok(mut config) = config::get() { config.game.enhancements.gamemode = switch.state(); + config::update(config); + } + } + } + } + }, + + adw::ActionRow { + set_title: &tr("gamescope"), + set_subtitle: &tr("gamescope-description"), + + set_sensitive: is_available("gamescope"), + + add_suffix = >k::Button { + set_icon_name: "emblem-system-symbolic", + add_css_class: "flat", + + set_valign: gtk::Align::Center, + + connect_clicked => EnhancementsAppMsg::OpenGamescope + }, + + add_suffix = >k::Switch { + set_valign: gtk::Align::Center, + + set_state: CONFIG.game.enhancements.gamescope.enabled, + + connect_state_notify => move |switch| { + if is_ready() { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.enabled = switch.state(); + config::update(config); } } @@ -402,13 +447,30 @@ impl SimpleAsyncComponent for EnhancementsApp { async fn init( _init: Self::Init, root: Self::Root, - _sender: AsyncComponentSender, + sender: AsyncComponentSender, ) -> AsyncComponentParts { tracing::info!("Initializing enhancements settings"); - let model = Self; + let model = Self { + gamescope: GamescopeApp::builder() + .launch(()) + .detach() + }; + let widgets = view_output!(); AsyncComponentParts { model, widgets } } + + async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender) { + match msg { + EnhancementsAppMsg::SetGamescopeParent(parent) => { + self.gamescope.widget().set_transient_for(Some(&parent)); + } + + EnhancementsAppMsg::OpenGamescope => { + self.gamescope.widget().show(); + } + } + } } diff --git a/src/ui/preferences/gamescope.rs b/src/ui/preferences/gamescope.rs new file mode 100644 index 0000000..bd66cc5 --- /dev/null +++ b/src/ui/preferences/gamescope.rs @@ -0,0 +1,243 @@ +use relm4::prelude::*; +use relm4::component::*; + +use adw::prelude::*; + +use anime_launcher_sdk::config; +use anime_launcher_sdk::config::prelude::*; + +use crate::i18n::tr; +use crate::*; + +pub struct GamescopeApp; + +#[relm4::component(async, pub)] +impl SimpleAsyncComponent for GamescopeApp { + type Init = (); + type Input = (); + type Output = (); + + view! { + adw::PreferencesWindow { + set_title: Some(&tr("gamescope")), + + set_modal: true, + set_hide_on_close: true, + set_search_enabled: false, + + add = &adw::PreferencesPage { + add = &adw::PreferencesGroup { + set_title: &tr("game-resolution"), + + adw::EntryRow { + set_title: &tr("width"), + set_input_purpose: gtk::InputPurpose::Digits, + + set_text: &if CONFIG.game.enhancements.gamescope.game.width > 0 { + CONFIG.game.enhancements.gamescope.game.width.to_string() + } else { + String::new() + }, + + connect_changed => |row| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.game.width = row.text().parse().unwrap_or_default(); + + config::update(config); + } + } + }, + + adw::EntryRow { + set_title: &tr("height"), + set_input_purpose: gtk::InputPurpose::Digits, + + set_text: &if CONFIG.game.enhancements.gamescope.game.height > 0 { + CONFIG.game.enhancements.gamescope.game.height.to_string() + } else { + String::new() + }, + + connect_changed => |row| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.game.height = row.text().parse().unwrap_or_default(); + + config::update(config); + } + } + } + }, + + add = &adw::PreferencesGroup { + set_title: &tr("gamescope-resolution"), + + adw::EntryRow { + set_title: &tr("width"), + set_input_purpose: gtk::InputPurpose::Digits, + + set_text: &if CONFIG.game.enhancements.gamescope.gamescope.width > 0 { + CONFIG.game.enhancements.gamescope.gamescope.width.to_string() + } else { + String::new() + }, + + connect_changed => |row| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.gamescope.width = row.text().parse().unwrap_or_default(); + + config::update(config); + } + } + }, + + adw::EntryRow { + set_title: &tr("height"), + set_input_purpose: gtk::InputPurpose::Digits, + + set_text: &if CONFIG.game.enhancements.gamescope.gamescope.height > 0 { + CONFIG.game.enhancements.gamescope.gamescope.height.to_string() + } else { + String::new() + }, + + connect_changed => |row| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.gamescope.height = row.text().parse().unwrap_or_default(); + + config::update(config); + } + } + } + }, + + add = &adw::PreferencesGroup { + set_title: &tr("other-settings"), + + // TODO: maybe use Fps enum like in fps unlocker settings + + adw::EntryRow { + set_title: &tr("framerate-limit"), + set_input_purpose: gtk::InputPurpose::Digits, + + set_text: &if CONFIG.game.enhancements.gamescope.framerate.focused > 0 { + CONFIG.game.enhancements.gamescope.framerate.focused.to_string() + } else { + String::new() + }, + + connect_changed => |row| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.framerate.focused = row.text().parse().unwrap_or_default(); + + config::update(config); + } + } + }, + + adw::EntryRow { + set_title: &tr("unfocused-framerate-limit"), + set_input_purpose: gtk::InputPurpose::Digits, + + set_text: &if CONFIG.game.enhancements.gamescope.framerate.unfocused > 0 { + CONFIG.game.enhancements.gamescope.framerate.unfocused.to_string() + } else { + String::new() + }, + + connect_changed => |row| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.framerate.unfocused = row.text().parse().unwrap_or_default(); + + config::update(config); + } + } + }, + + adw::ActionRow { + set_title: &tr("integer-scaling"), + + add_suffix = >k::Switch { + set_valign: gtk::Align::Center, + set_state: CONFIG.game.enhancements.gamescope.integer_scaling, + + connect_state_notify => |switch| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.integer_scaling = switch.state(); + + config::update(config); + } + } + } + }, + + adw::ActionRow { + set_title: "FSR", + + add_suffix = >k::Switch { + set_valign: gtk::Align::Center, + set_state: CONFIG.game.enhancements.gamescope.fsr, + + connect_state_notify => |switch| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.fsr = switch.state(); + + config::update(config); + } + } + } + }, + + adw::ActionRow { + set_title: "Nvidia Image Scaling", + + add_suffix = >k::Switch { + set_valign: gtk::Align::Center, + set_state: CONFIG.game.enhancements.gamescope.nis, + + connect_state_notify => |switch| { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.nis = switch.state(); + + config::update(config); + } + } + } + }, + + adw::ComboRow { + set_title: &tr("window-mode"), + + #[wrap(Some)] + set_model = >k::StringList::new(&[ + &tr("borderless"), + &tr("fullscreen") + ]), + + set_selected: CONFIG.game.enhancements.gamescope.window_type.ordinal() as u32, + + connect_selected_notify => |row| unsafe { + if let Ok(mut config) = config::get() { + config.game.enhancements.gamescope.window_type = WindowType::from_ordinal_unsafe(row.selected() as i8); + + config::update(config); + } + } + } + } + } + } + } + + async fn init( + _init: Self::Init, + root: Self::Root, + _sender: AsyncComponentSender, + ) -> AsyncComponentParts { + tracing::info!("Initializing gamescope settings"); + + let model = Self; + let widgets = view_output!(); + + AsyncComponentParts { model, widgets } + } +} diff --git a/src/ui/preferences/main.rs b/src/ui/preferences/main.rs index 39a3d28..298eba1 100644 --- a/src/ui/preferences/main.rs +++ b/src/ui/preferences/main.rs @@ -105,6 +105,8 @@ impl SimpleAsyncComponent for PreferencesApp { } #[allow(unused_must_use)] { + model.enhancements.sender().send(EnhancementsAppMsg::SetGamescopeParent(widgets.preferences_window.clone())); + model.general.sender().send(GeneralAppMsg::UpdateDownloadedWine); model.general.sender().send(GeneralAppMsg::UpdateDownloadedDxvk); } diff --git a/src/ui/preferences/mod.rs b/src/ui/preferences/mod.rs index 4bc8d46..292d031 100644 --- a/src/ui/preferences/mod.rs +++ b/src/ui/preferences/mod.rs @@ -2,3 +2,4 @@ pub mod main; pub mod general; pub mod enhancements; pub mod environment; +pub mod gamescope;