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
This commit is contained in:
Observer KRypt0n_ 2023-03-02 15:31:21 +02:00
parent ec30411ef8
commit 84683ded86
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
16 changed files with 357 additions and 7 deletions

2
Cargo.lock generated
View file

@ -74,7 +74,7 @@ dependencies = [
[[package]]
name = "anime-launcher-sdk"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"anime-game-core",
"anyhow",

@ -1 +1 @@
Subproject commit e662699b992108c50602944647cded05df6beba9
Subproject commit f1f8eb6a2cc2d61dc8a2fa02051bd5ab2c400338

View file

@ -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

View file

@ -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

View file

@ -3,6 +3,9 @@ none = Kein
default = Standard
details = Einzelheiten
width = Width
height = Height
# Menu items
launcher-folder = Launcher-Ordner

View file

@ -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

View file

@ -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

View file

@ -3,6 +3,9 @@ none = None
default = Default
details = Details
width = Width
height = Height
# Menu items
launcher-folder = Launcher folder

View file

@ -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 = Полноэкранный

View file

@ -0,0 +1,6 @@
game-resolution = Разрешение игры
gamescope-resolution = Разрешение Gamescope
other-settings = Другие настройки
framerate-limit = Лимит числа кадров
unfocused-framerate-limit = Лимит числа кадров вне фокуса
integer-scaling = Целочисленное масштабирование

View file

@ -3,6 +3,9 @@ none = Нет
default = По умолчанию
details = Подробнее
width = Ширина
height = Высота
# Menu items
launcher-folder = Папка лаунчера

View file

@ -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(),

View file

@ -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<GamescopeApp>
}
#[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 = &gtk::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 = &gtk::Button {
set_icon_name: "emblem-system-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
connect_clicked => EnhancementsAppMsg::OpenGamescope
},
add_suffix = &gtk::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<Self>,
sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
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<Self>) {
match msg {
EnhancementsAppMsg::SetGamescopeParent(parent) => {
self.gamescope.widget().set_transient_for(Some(&parent));
}
EnhancementsAppMsg::OpenGamescope => {
self.gamescope.widget().show();
}
}
}
}

View file

@ -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 = &gtk::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 = &gtk::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 = &gtk::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 = &gtk::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<Self>,
) -> AsyncComponentParts<Self> {
tracing::info!("Initializing gamescope settings");
let model = Self;
let widgets = view_output!();
AsyncComponentParts { model, widgets }
}
}

View file

@ -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);
}

View file

@ -2,3 +2,4 @@ pub mod main;
pub mod general;
pub mod enhancements;
pub mod environment;
pub mod gamescope;