Added custom setting function for each game
This commit is contained in:
parent
131fe71205
commit
2640f083b6
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@ -10,9 +10,9 @@ env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.2"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "master"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Goodfeat"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx_alt"
|
||||
RELEASE: 1
|
||||
|
||||
jobs:
|
||||
|
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
{
|
||||
|
@ -582,6 +582,10 @@ namespace Ryujinx.Ava
|
||||
Rainbow.Disable();
|
||||
Rainbow.Reset();
|
||||
|
||||
//Reload settings when the game is turned off
|
||||
//(resets custom settings if there were any)
|
||||
Program.ReloadConfig();
|
||||
|
||||
_isStopped = true;
|
||||
Stop();
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
<Styles
|
||||
<Styles
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia">
|
||||
<Design.PreviewWith>
|
||||
<Border Height="2000"
|
||||
@ -30,7 +31,8 @@
|
||||
<Button
|
||||
Name="btnRem"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
Content="Add"
|
||||
Classes="red"/>
|
||||
<TextBox
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
@ -41,7 +43,12 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ui:NumberBox Value="1" />
|
||||
<MenuItem
|
||||
IconSource="Settings"
|
||||
Header="123 0000"
|
||||
ToolTip.Tip="What this"/>
|
||||
</StackPanel>
|
||||
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Style Selector="DropDownButton">
|
||||
@ -373,6 +380,16 @@
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource AppListHoverBackgroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="Button.red /template/ ContentPresenter">
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Background" Value="red"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
<Style Selector="Button.red:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Background" Value="{DynamicResource WarningBackgroundColor}" />
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
<Styles.Resources>
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush"
|
||||
Color="{DynamicResource SystemAccentColor}" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
@ -12,11 +12,13 @@
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||
<Color x:Key="Custom">#6483F5</Color>
|
||||
<Color x:Key="Warning">#800080</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||
@ -29,11 +31,13 @@
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||
<Color x:Key="Switch">#13c3a4</Color>
|
||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||
<Color x:Key="Custom">#6483F5</Color>
|
||||
<Color x:Key="Warning">#800080</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||
@ -46,11 +50,13 @@
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||
<Color x:Key="WarningBackgroundColor">#FF6347</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||
<Color x:Key="Custom">#6483F5</Color>
|
||||
<Color x:Key="Warning">#FFA500</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
@ -2747,6 +2747,31 @@
|
||||
"zh_TW": "在 macOS 的應用程式資料夾中建立捷徑,啟動選取的應用程式"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "EditGameConfigurationToolTip",
|
||||
"Translations": {
|
||||
"ar_SA": "ينشئ تكوينًا مستقلًا للعبة الحالية",
|
||||
"de_DE": "Erstellt eine unabhängige Konfiguration für das aktuelle Spiel",
|
||||
"el_GR": "Δημιουργεί μια ανεξάρτητη διαμόρφωση για το τρέχον παιχνίδι",
|
||||
"en_US": "Creates an independent configuration for the current game",
|
||||
"es_ES": "Crea una configuración independiente para el juego actual",
|
||||
"fr_FR": "Crée une configuration indépendante pour le jeu en cours",
|
||||
"he_IL": "יוצר תצורה עצמאית למשחק הנוכחי",
|
||||
"it_IT": "Crea una configurazione indipendente per il gioco attuale",
|
||||
"ja_JP": "現在のゲーム用の独立した設定を作成します",
|
||||
"ko_KR": "현재 게임에 대한 독립적인 설정을 생성합니다",
|
||||
"no_NO": "Oppretter en uavhengig konfigurasjon for det gjeldende spillet",
|
||||
"pl_PL": "Tworzy niezależną konfigurację dla bieżącej gry",
|
||||
"pt_BR": "Cria uma configuração independente para o jogo atual",
|
||||
"ru_RU": "Создает независимую конфигурацию для текущей игры",
|
||||
"sv_SE": "Skapar en oberoende konfiguration för det aktuella spelet",
|
||||
"th_TH": "สร้างการกำหนดค่าที่เป็นอิสระสำหรับเกมปัจจุบัน",
|
||||
"tr_TR": "Mevcut oyun için bağımsız bir yapılandırma oluşturur",
|
||||
"uk_UA": "Створює незалежну конфігурацію для поточної гри",
|
||||
"zh_CN": "为当前游戏创建独立的配置",
|
||||
"zh_TW": "為當前遊戲創建獨立的配置"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "GameListContextMenuShowCompatEntry",
|
||||
"Translations": {
|
||||
|
@ -23,6 +23,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace Ryujinx.Ava
|
||||
{
|
||||
@ -32,6 +33,7 @@ namespace Ryujinx.Ava
|
||||
public static double DesktopScaleFactor { get; set; } = 1.0;
|
||||
public static string Version { get; private set; }
|
||||
public static string ConfigurationPath { get; private set; }
|
||||
public static string GlobalConfigurationPath { get; private set; }
|
||||
public static bool PreviewerDetached { get; private set; }
|
||||
public static bool UseHardwareAcceleration { get; private set; }
|
||||
|
||||
@ -155,11 +157,42 @@ namespace Ryujinx.Ava
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReloadGameConfig(string gamedir)
|
||||
{
|
||||
if (File.Exists(gamedir))
|
||||
{
|
||||
ConfigurationPath = gamedir;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
|
||||
{
|
||||
string gameDir = Path.Combine(AppDataManager.GamesDirPath, gameId, ReleaseInformation.ConfigName);
|
||||
|
||||
// Should load with the game if there is a custom setting for the game
|
||||
if (rememberGlobalDir)
|
||||
{
|
||||
GlobalConfigurationPath = ConfigurationPath;
|
||||
}
|
||||
|
||||
if (changeFolderForGame)
|
||||
{
|
||||
ConfigurationPath = gameDir;
|
||||
}
|
||||
|
||||
return gameDir;
|
||||
}
|
||||
|
||||
public static void ReloadConfig()
|
||||
{
|
||||
//It is necessary that when a user setting appears, the global setting remains available
|
||||
GlobalConfigurationPath = null;
|
||||
|
||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||
|
||||
|
||||
// Now load the configuration as the other subsystems are now registered
|
||||
if (File.Exists(localConfigurationPath))
|
||||
{
|
||||
@ -232,8 +265,35 @@ namespace Ryujinx.Ava
|
||||
_ => ConfigurationState.Instance.HideCursor,
|
||||
};
|
||||
|
||||
// Check if memoryManagerMode was overridden.
|
||||
if (CommandLineState.OverrideMemoryManagerMode is not null)
|
||||
if (Enum.TryParse(CommandLineState.OverrideMemoryManagerMode, true, out MemoryManagerMode result))
|
||||
{
|
||||
ConfigurationState.Instance.System.MemoryManagerMode.Value = result;
|
||||
}
|
||||
|
||||
// Check if hardware-acceleration was overridden.
|
||||
// Check if PPTC was overridden.
|
||||
if (CommandLineState.OverridePPTC is not null)
|
||||
if (Enum.TryParse(CommandLineState.OverridePPTC, true, out bool result))
|
||||
{
|
||||
ConfigurationState.Instance.System.EnablePtc.Value = result;
|
||||
}
|
||||
|
||||
// Check if region was overridden.
|
||||
if (CommandLineState.OverrideSystemRegion is not null)
|
||||
if (Enum.TryParse(CommandLineState.OverrideSystemRegion, true, out Ryujinx.HLE.HOS.SystemState.RegionCode result))
|
||||
{
|
||||
ConfigurationState.Instance.System.Region.Value = (Utilities.Configuration.System.Region)result;
|
||||
}
|
||||
|
||||
//Check if language was overridden.
|
||||
if (CommandLineState.OverrideSystemLanguage is not null)
|
||||
if (Enum.TryParse(CommandLineState.OverrideSystemLanguage, true, out Ryujinx.HLE.HOS.SystemState.SystemLanguage result))
|
||||
{
|
||||
ConfigurationState.Instance.System.Language.Value = (Utilities.Configuration.System.Language)result;
|
||||
}
|
||||
|
||||
// Check if hardware-acceleration was overridden. MemoryManagerMode ( outdated! )
|
||||
if (CommandLineState.OverrideHardwareAcceleration != null)
|
||||
UseHardwareAcceleration = CommandLineState.OverrideHardwareAcceleration.Value;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
@ -172,5 +172,10 @@
|
||||
<ItemGroup>
|
||||
<Folder Include="Assets\Fonts\Mono\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="UI\Windows\UserConfigWindows.axaml.cs">
|
||||
<DependentUpon>UserConfigWindows.axaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -19,6 +19,11 @@
|
||||
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
||||
Icon="{ext:Icon fa-solid fa-bookmark}"
|
||||
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||
<MenuItem
|
||||
Click="EditGameConfiguration_Click"
|
||||
Header="Edit Game Configuration"
|
||||
Icon="{ext:Icon fa-solid fa-gear}"
|
||||
ToolTip.Tip="{ext:Locale EditGameConfigurationToolTip}" />
|
||||
<MenuItem
|
||||
IsVisible="{Binding HasCompatibilityEntry}"
|
||||
Click="OpenApplicationCompatibility_Click"
|
||||
|
@ -13,6 +13,7 @@ using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Compat;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.HLE.HOS;
|
||||
@ -36,6 +37,21 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public void ToggleUserControl_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
return;
|
||||
|
||||
viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite;
|
||||
|
||||
ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.IdString, appMetadata =>
|
||||
{
|
||||
appMetadata.Favorite = viewModel.SelectedApplication.Favorite;
|
||||
});
|
||||
|
||||
viewModel.RefreshView();
|
||||
}
|
||||
|
||||
public void ToggleFavorite_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
@ -387,6 +403,20 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
);
|
||||
}
|
||||
|
||||
public async void EditGameConfiguration_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
{
|
||||
await new UserConfigWindows(viewModel).ShowDialog((Window)viewModel.TopLevel);
|
||||
|
||||
//just checking for file presence
|
||||
viewModel.SelectedApplication.UserConfig = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false));
|
||||
|
||||
viewModel.RefreshView();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
|
@ -73,12 +73,18 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Name}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
IsVisible="{Binding UserConfig}"
|
||||
Text="User Config"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Warning}" />
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</Border>
|
||||
@ -86,10 +92,28 @@
|
||||
Margin="5,5,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="16"
|
||||
FontSize="18"
|
||||
Foreground="{DynamicResource FavoriteApplicationIconColor}"
|
||||
IsVisible="{Binding Favorite}"
|
||||
Symbol="StarFilled" />
|
||||
<Grid IsVisible="{Binding !$parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||
<Border
|
||||
Margin="15,35,5,15"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="90"
|
||||
Height="20"
|
||||
CornerRadius="4"
|
||||
IsVisible="{Binding UserConfig}"
|
||||
Background="{DynamicResource ThemeContentBackgroundColor}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="User Config"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
@ -145,6 +145,13 @@
|
||||
Text="{Binding Converter={x:Static helpers:MultiplayerInfoConverter.Instance}}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap"/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding UserConfig}"
|
||||
Text="User Config"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Warning}" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="4"
|
||||
|
@ -4,6 +4,7 @@ using Avalonia.Input.Platform;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Compat;
|
||||
using System;
|
||||
@ -42,6 +43,19 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
await CompatibilityList.Show((string)playabilityLabel.Tag);
|
||||
}
|
||||
|
||||
public async void EditGameConfiguration_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
{
|
||||
await new UserConfigWindows(viewModel).ShowDialog((Window)viewModel.TopLevel);
|
||||
|
||||
//viewModel.SelectedApplication.UserConfig = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString));
|
||||
|
||||
viewModel.RefreshView();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel mwvm)
|
||||
|
@ -1540,6 +1540,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
#if RELEASE
|
||||
await PerformanceCheck();
|
||||
#endif
|
||||
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
|
||||
string gameDir = Program.GetDirGameUserConfig(application.IdBaseString, true, true);
|
||||
|
||||
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
||||
{
|
||||
//Program.GetDirGameUserConfig(application.IdBaseString, false);
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, application.IdBaseString);
|
||||
}
|
||||
|
||||
Logger.RestartTime();
|
||||
|
||||
@ -1585,6 +1593,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
||||
gameThread.Start();
|
||||
|
||||
}
|
||||
|
||||
public void SwitchToRenderer(bool startFullscreen) =>
|
||||
|
@ -1,8 +1,10 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Humanizer;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.OpenAL;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
@ -26,6 +28,7 @@ using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading.Tasks;
|
||||
@ -67,6 +70,49 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private string _ldnServer;
|
||||
|
||||
public SettingsHacksViewModel DirtyHacks { get; }
|
||||
public string GamePath { get; }
|
||||
public string GameName { get; }
|
||||
|
||||
private Bitmap _gameIcon;
|
||||
|
||||
private string _gameTitle;
|
||||
private string _gameId;
|
||||
public Bitmap GameIcon
|
||||
{
|
||||
get => _gameIcon;
|
||||
set
|
||||
{
|
||||
if (_gameIcon != value)
|
||||
{
|
||||
_gameIcon = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GameTitle
|
||||
{
|
||||
get => _gameTitle;
|
||||
set
|
||||
{
|
||||
if (_gameTitle != value)
|
||||
{
|
||||
_gameTitle = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GameId
|
||||
{
|
||||
get => _gameId;
|
||||
set
|
||||
{
|
||||
if (_gameId != value)
|
||||
{
|
||||
_gameId = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int ResolutionScale
|
||||
{
|
||||
@ -342,6 +388,37 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager, string gamePath, string gameName, string gameId, byte[] gameIconData) : this()
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
|
||||
if (gameIconData != null && gameIconData.Length > 0)
|
||||
{
|
||||
using (var ms = new MemoryStream(gameIconData))
|
||||
{
|
||||
GameIcon = new Bitmap(ms);
|
||||
}
|
||||
}
|
||||
|
||||
GameTitle = gameName;
|
||||
GameId = gameId;
|
||||
|
||||
string gameDir = Program.GetDirGameUserConfig(gameId,false,true);
|
||||
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
||||
{
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||
LoadCurrentConfiguration(); // Needed to load custom configuration
|
||||
}
|
||||
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
Task.Run(LoadTimeZones);
|
||||
|
||||
DirtyHacks = new SettingsHacksViewModel(this);
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel()
|
||||
{
|
||||
GameDirectories = [];
|
||||
@ -468,6 +545,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
|
||||
if (string.IsNullOrEmpty(GameId))
|
||||
{
|
||||
// User Interface
|
||||
EnableDiscordIntegration = config.EnableDiscordIntegration;
|
||||
CheckUpdatesOnStart = config.CheckUpdatesOnStart;
|
||||
@ -489,6 +568,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
"Dark" => 2,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
// Input
|
||||
EnableDockedMode = config.System.EnableDockedMode;
|
||||
@ -569,7 +649,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
LdnServer = config.Multiplayer.LdnServer;
|
||||
}
|
||||
|
||||
public void SaveSettings()
|
||||
public void SaveSettings2()
|
||||
{
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
|
||||
@ -599,6 +679,50 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
_ => "Auto"
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(GameId))
|
||||
{
|
||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
ConfigurationState config = ConfigurationState.Instance;
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(GameId))
|
||||
{
|
||||
// User Interface
|
||||
config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
|
||||
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
|
||||
config.ShowConfirmExit.Value = ShowConfirmExit;
|
||||
config.RememberWindowState.Value = RememberWindowState;
|
||||
config.ShowTitleBar.Value = ShowTitleBar;
|
||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||
|
||||
if (GameDirectoryChanged)
|
||||
{
|
||||
config.UI.GameDirs.Value = [.. GameDirectories];
|
||||
}
|
||||
|
||||
if (AutoloadDirectoryChanged)
|
||||
{
|
||||
config.UI.AutoloadDirs.Value = [.. AutoloadDirectories];
|
||||
}
|
||||
|
||||
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
||||
{
|
||||
0 => "Auto",
|
||||
1 => "Light",
|
||||
2 => "Dark",
|
||||
_ => "Auto"
|
||||
};
|
||||
}
|
||||
|
||||
// Input
|
||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||
@ -693,8 +817,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled;
|
||||
config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay;
|
||||
|
||||
|
||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
|
||||
|
||||
MainWindow.UpdateGraphicsConfig();
|
||||
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
||||
|
||||
@ -705,15 +831,38 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
|
||||
private static void RevertIfNotSaved()
|
||||
{
|
||||
// maybe this is an unnecessary check(all options need to be tested)
|
||||
if (string.IsNullOrEmpty(Program.GlobalConfigurationPath))
|
||||
{
|
||||
Program.ReloadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyButton()
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
public void DeleteConfigGame()
|
||||
{
|
||||
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
|
||||
|
||||
if (File.Exists(gameDir))
|
||||
{
|
||||
File.Delete(gameDir);
|
||||
}
|
||||
RevertIfNotSaved();
|
||||
CloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
public void SaveUserConfig()
|
||||
{
|
||||
SaveSettings();
|
||||
RevertIfNotSaved();
|
||||
CloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
public void OkButton()
|
||||
{
|
||||
SaveSettings();
|
||||
|
139
src/Ryujinx/UI/Windows/UserConfigWindows.axaml
Normal file
139
src/Ryujinx/UI/Windows/UserConfigWindows.axaml
Normal file
@ -0,0 +1,139 @@
|
||||
<window:StyleableAppWindow
|
||||
x:Class="Ryujinx.Ava.UI.Windows.UserConfigWindows"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:settings="clr-namespace:Ryujinx.Ava.UI.Views.Settings"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||
Width="1100"
|
||||
Height="768"
|
||||
MinWidth="800"
|
||||
MinHeight="480"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
x:DataType="viewModels:SettingsViewModel"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Design.DataContext>
|
||||
<viewModels:SettingsViewModel />
|
||||
</Design.DataContext>
|
||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinWidth="600" RowDefinitions="Auto,*,Auto">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
Grid.Row="1"
|
||||
IsVisible="False"
|
||||
KeyboardNavigation.IsTabStop="False"/>
|
||||
<Grid Name="Pages" IsVisible="False" Grid.Row="2">
|
||||
<settings:SettingsSystemView Name="SystemPage" />
|
||||
<settings:SettingsCPUView Name="CpuPage" />
|
||||
<settings:SettingsGraphicsView Name="GraphicsPage" />
|
||||
<settings:SettingsAudioView Name="AudioPage" />
|
||||
<settings:SettingsNetworkView Name="NetworkPage" />
|
||||
<settings:SettingsLoggingView Name="LoggingPage" />
|
||||
<settings:SettingsHacksView Name="HacksPage" />
|
||||
</Grid>
|
||||
<ui:NavigationView
|
||||
Grid.Row="1"
|
||||
IsSettingsVisible="False"
|
||||
Name="NavPanel"
|
||||
IsBackEnabled="False"
|
||||
PaneDisplayMode="Left"
|
||||
Margin="2,10,10,0"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
OpenPaneLength="200"
|
||||
IsPaneToggleButtonVisible="False">
|
||||
|
||||
<!-- For image -->
|
||||
<ui:NavigationView.PaneHeader>
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="5"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{Binding GameId}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,10"
|
||||
TextAlignment="Center" Grid.Row="0" />
|
||||
<Image Source="{Binding GameIcon}"
|
||||
Width="160"
|
||||
Height="160"
|
||||
Grid.Row="1"
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center" />
|
||||
<TextBlock Text="{Binding GameTitle}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,10"
|
||||
TextAlignment="Center" Grid.Row="2" />
|
||||
<Separator Height="1" Grid.Row="3" Margin="0,0,0,10" HorizontalAlignment="Stretch"/>
|
||||
</Grid>
|
||||
</ui:NavigationView.PaneHeader>
|
||||
|
||||
<ui:NavigationView.MenuItems>
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabSystem}"
|
||||
Tag="SystemPage"
|
||||
IconSource="Settings" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabCpu}"
|
||||
Tag="CpuPage">
|
||||
<ui:NavigationViewItem.IconSource>
|
||||
<ui:FontIconSource
|
||||
FontFamily="avares://Ryujinx/Assets/Fonts#Segoe Fluent Icons"
|
||||
Glyph="{helpers:GlyphValueConverter Chip}" />
|
||||
</ui:NavigationViewItem.IconSource>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabGraphics}"
|
||||
Tag="GraphicsPage"
|
||||
IconSource="Image" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabAudio}"
|
||||
IconSource="Audio"
|
||||
Tag="AudioPage" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabNetwork}"
|
||||
Tag="NetworkPage"
|
||||
IconSource="Globe" />
|
||||
<ui:NavigationViewItem
|
||||
Content="{ext:Locale SettingsTabLogging}"
|
||||
Tag="LoggingPage"
|
||||
IconSource="Document" />
|
||||
<ui:NavigationViewItem
|
||||
IsVisible="{Binding ShowDirtyHacks}"
|
||||
Content="Dirty Hacks"
|
||||
Tag="HacksPage"
|
||||
IconSource="Code" />
|
||||
</ui:NavigationView.MenuItems>
|
||||
</ui:NavigationView>
|
||||
|
||||
<ReversibleStackPanel
|
||||
Grid.Row="2"
|
||||
Margin="10"
|
||||
Spacing="10"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
ReverseOrder="{x:Static helper:RunningPlatform.IsMacOS}">
|
||||
<Button
|
||||
Content="{ext:Locale SettingsButtonSave}"
|
||||
Command="{Binding SaveUserConfig}" />
|
||||
<Button
|
||||
HotKey="Escape"
|
||||
Content="{ext:Locale SettingsButtonClose}"
|
||||
Command="{Binding CancelButton}" />
|
||||
<Button
|
||||
Content="{ext:Locale UserProfilesDelete}"
|
||||
Command="{Binding DeleteConfigGame}"
|
||||
Classes="red"/>
|
||||
</ReversibleStackPanel>
|
||||
</Grid>
|
||||
</window:StyleableAppWindow>
|
108
src/Ryujinx/UI/Windows/UserConfigWindows.axaml.cs
Normal file
108
src/Ryujinx/UI/Windows/UserConfigWindows.axaml.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media.Imaging;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Projektanker.Icons.Avalonia;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Key = Avalonia.Input.Key;
|
||||
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
public partial class UserConfigWindows : StyleableAppWindow
|
||||
{
|
||||
internal readonly SettingsViewModel ViewModel;
|
||||
|
||||
public UserConfigWindows(MainWindowViewModel viewModel)
|
||||
{
|
||||
Title = RyujinxApp.FormatTitle(LocaleKeys.Settings);
|
||||
|
||||
DataContext = ViewModel = new SettingsViewModel(
|
||||
viewModel.VirtualFileSystem,
|
||||
viewModel.ContentManager,
|
||||
viewModel.SelectedApplication.Path,
|
||||
viewModel.SelectedApplication.Name,
|
||||
viewModel.SelectedApplication.IdString,
|
||||
viewModel.SelectedApplication.Icon);
|
||||
|
||||
ViewModel.CloseWindow += Close;
|
||||
|
||||
InitializeComponent();
|
||||
Load();
|
||||
|
||||
#if DEBUG
|
||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void Load()
|
||||
{
|
||||
Pages.Children.Clear();
|
||||
NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
|
||||
NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
|
||||
|
||||
}
|
||||
|
||||
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
|
||||
{
|
||||
|
||||
if (e.SelectedItem is NavigationViewItem navItem && navItem.Tag is not null)
|
||||
{
|
||||
switch (navItem.Tag.ToString())
|
||||
{
|
||||
//case nameof(InputPage):
|
||||
// NavPanel.Content = InputPage;
|
||||
// break;
|
||||
case nameof(SystemPage):
|
||||
SystemPage.ViewModel = ViewModel;
|
||||
NavPanel.Content = SystemPage;
|
||||
break;
|
||||
case nameof(CpuPage):
|
||||
NavPanel.Content = CpuPage;
|
||||
break;
|
||||
case nameof(GraphicsPage):
|
||||
NavPanel.Content = GraphicsPage;
|
||||
break;
|
||||
case nameof(AudioPage):
|
||||
NavPanel.Content = AudioPage;
|
||||
break;
|
||||
case nameof(NetworkPage):
|
||||
NetworkPage.ViewModel = ViewModel;
|
||||
NavPanel.Content = NetworkPage;
|
||||
break;
|
||||
case nameof(LoggingPage):
|
||||
NavPanel.Content = LoggingPage;
|
||||
break;
|
||||
case nameof(HacksPage):
|
||||
HacksPage.DataContext = ViewModel;
|
||||
NavPanel.Content = HacksPage;
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public class ApplicationData
|
||||
{
|
||||
public bool Favorite { get; set; }
|
||||
public bool UserConfig { get; set; }
|
||||
public byte[] Icon { get; set; }
|
||||
public string Name { get; set; } = "Unknown";
|
||||
|
||||
|
@ -533,6 +533,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
data.Favorite = appMetadata.Favorite;
|
||||
data.TimePlayed = appMetadata.TimePlayed;
|
||||
data.LastPlayed = appMetadata.LastPlayed;
|
||||
data.UserConfig = File.Exists(Program.GetDirGameUserConfig(data.IdBaseString, false, false)); // just check for file presence
|
||||
}
|
||||
|
||||
data.FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper();
|
||||
|
@ -6,11 +6,15 @@ namespace Ryujinx.Ava.Utilities
|
||||
public static class CommandLineState
|
||||
{
|
||||
public static string[] Arguments { get; private set; }
|
||||
|
||||
public static int CountArguments { get; private set; }
|
||||
public static bool? OverrideDockedMode { get; private set; }
|
||||
public static bool? OverrideHardwareAcceleration { get; private set; }
|
||||
public static string OverrideGraphicsBackend { get; private set; }
|
||||
public static string OverrideBackendThreading { get; private set; }
|
||||
public static string OverridePPTC { get; private set; }
|
||||
public static string OverrideMemoryManagerMode { get; private set; }
|
||||
public static string OverrideSystemRegion { get; private set; }
|
||||
public static string OverrideSystemLanguage { get; private set; }
|
||||
public static string OverrideHideCursor { get; private set; }
|
||||
public static string BaseDirPathArg { get; private set; }
|
||||
public static string Profile { get; private set; }
|
||||
@ -19,6 +23,11 @@ namespace Ryujinx.Ava.Utilities
|
||||
public static bool StartFullscreenArg { get; private set; }
|
||||
public static bool HideAvailableUpdates { get; private set; }
|
||||
|
||||
public static void ArgumentsClean()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void ParseArguments(string[] args)
|
||||
{
|
||||
List<string> arguments = [];
|
||||
@ -28,6 +37,11 @@ namespace Ryujinx.Ava.Utilities
|
||||
{
|
||||
string arg = args[i];
|
||||
|
||||
if (arg.Contains("-") || arg.Contains("--"))
|
||||
{
|
||||
CountArguments++;
|
||||
}
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case "-r":
|
||||
@ -85,6 +99,47 @@ namespace Ryujinx.Ava.Utilities
|
||||
|
||||
OverrideBackendThreading = args[++i];
|
||||
break;
|
||||
case "--pptc":
|
||||
if (i + 1 >= args.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
OverridePPTC = args[++i];
|
||||
break;
|
||||
case "-m":
|
||||
case "--memory-manager-mode":
|
||||
if (i + 1 >= args.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
OverrideMemoryManagerMode = args[++i];
|
||||
break;
|
||||
case "--system-region":
|
||||
if (i + 1 >= args.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
OverrideSystemRegion = args[++i];
|
||||
break;
|
||||
case "--system-language":
|
||||
if (i + 1 >= args.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
OverrideSystemLanguage = args[++i];
|
||||
break;
|
||||
case "-i":
|
||||
case "--application-id":
|
||||
LaunchApplicationId = args[++i];
|
||||
|
@ -18,9 +18,15 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
{
|
||||
public partial class ConfigurationState
|
||||
{
|
||||
public void Load(ConfigurationFileFormat cff, string configurationFilePath)
|
||||
public void Load(ConfigurationFileFormat cff, string configurationFilePath, string gameId="")
|
||||
{
|
||||
bool configurationFileUpdated = false;
|
||||
bool LoadSetting = true;
|
||||
|
||||
if (!string.IsNullOrEmpty(gameId))
|
||||
{
|
||||
LoadSetting = false;
|
||||
}
|
||||
|
||||
if (cff.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
|
||||
{
|
||||
@ -43,13 +49,13 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
||||
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
|
||||
ShowConfirmExit.Value = cff.ShowConfirmExit;
|
||||
RememberWindowState.Value = cff.RememberWindowState;
|
||||
ShowTitleBar.Value = cff.ShowTitleBar;
|
||||
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
|
||||
HideCursor.Value = cff.HideCursor;
|
||||
EnableDiscordIntegration.Value = LoadSetting ? cff.EnableDiscordIntegration : EnableDiscordIntegration.Value;
|
||||
CheckUpdatesOnStart.Value = LoadSetting ? cff.CheckUpdatesOnStart : CheckUpdatesOnStart.Value;
|
||||
ShowConfirmExit.Value = LoadSetting ? cff.ShowConfirmExit : ShowConfirmExit.Value;
|
||||
RememberWindowState.Value = LoadSetting ? cff.RememberWindowState : RememberWindowState.Value;
|
||||
ShowTitleBar.Value = LoadSetting ? cff.ShowTitleBar : ShowTitleBar.Value;
|
||||
EnableHardwareAcceleration.Value = LoadSetting ? cff.EnableHardwareAcceleration : EnableHardwareAcceleration.Value;
|
||||
HideCursor.Value = LoadSetting ? cff.HideCursor : HideCursor.Value;
|
||||
|
||||
Logger.EnableFileLog.Value = cff.EnableFileLog;
|
||||
Logger.EnableDebug.Value = cff.LoggingEnableDebug;
|
||||
@ -100,41 +106,42 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
System.IgnoreApplet.Value = cff.IgnoreApplet;
|
||||
System.UseHypervisor.Value = cff.UseHypervisor;
|
||||
|
||||
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
||||
UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
|
||||
UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
|
||||
UI.GuiColumns.DevColumn.Value = cff.GuiColumns.DevColumn;
|
||||
UI.GuiColumns.VersionColumn.Value = cff.GuiColumns.VersionColumn;
|
||||
UI.GuiColumns.TimePlayedColumn.Value = cff.GuiColumns.TimePlayedColumn;
|
||||
UI.GuiColumns.LastPlayedColumn.Value = cff.GuiColumns.LastPlayedColumn;
|
||||
UI.GuiColumns.FileExtColumn.Value = cff.GuiColumns.FileExtColumn;
|
||||
UI.GuiColumns.FileSizeColumn.Value = cff.GuiColumns.FileSizeColumn;
|
||||
UI.GuiColumns.PathColumn.Value = cff.GuiColumns.PathColumn;
|
||||
UI.ColumnSort.SortColumnId.Value = cff.ColumnSort.SortColumnId;
|
||||
UI.ColumnSort.SortAscending.Value = cff.ColumnSort.SortAscending;
|
||||
UI.GameDirs.Value = cff.GameDirs;
|
||||
UI.AutoloadDirs.Value = cff.AutoloadDirs ?? [];
|
||||
UI.ShownFileTypes.NSP.Value = cff.ShownFileTypes.NSP;
|
||||
UI.ShownFileTypes.PFS0.Value = cff.ShownFileTypes.PFS0;
|
||||
UI.ShownFileTypes.XCI.Value = cff.ShownFileTypes.XCI;
|
||||
UI.ShownFileTypes.NCA.Value = cff.ShownFileTypes.NCA;
|
||||
UI.ShownFileTypes.NRO.Value = cff.ShownFileTypes.NRO;
|
||||
UI.ShownFileTypes.NSO.Value = cff.ShownFileTypes.NSO;
|
||||
UI.LanguageCode.Value = cff.LanguageCode;
|
||||
UI.BaseStyle.Value = cff.BaseStyle;
|
||||
UI.GameListViewMode.Value = cff.GameListViewMode;
|
||||
UI.ShowNames.Value = cff.ShowNames;
|
||||
UI.IsAscendingOrder.Value = cff.IsAscendingOrder;
|
||||
UI.GridSize.Value = cff.GridSize;
|
||||
UI.ApplicationSort.Value = cff.ApplicationSort;
|
||||
UI.StartFullscreen.Value = cff.StartFullscreen;
|
||||
UI.StartNoUI.Value = cff.StartNoUI;
|
||||
UI.ShowConsole.Value = cff.ShowConsole;
|
||||
UI.WindowStartup.WindowSizeWidth.Value = cff.WindowStartup.WindowSizeWidth;
|
||||
UI.WindowStartup.WindowSizeHeight.Value = cff.WindowStartup.WindowSizeHeight;
|
||||
UI.WindowStartup.WindowPositionX.Value = cff.WindowStartup.WindowPositionX;
|
||||
UI.WindowStartup.WindowPositionY.Value = cff.WindowStartup.WindowPositionY;
|
||||
UI.WindowStartup.WindowMaximized.Value = cff.WindowStartup.WindowMaximized;
|
||||
UI.GuiColumns.FavColumn.Value = LoadSetting ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value;
|
||||
UI.GuiColumns.IconColumn.Value = LoadSetting ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value;
|
||||
UI.GuiColumns.AppColumn.Value = LoadSetting ? cff.GuiColumns.AppColumn : UI.GuiColumns.AppColumn.Value;
|
||||
UI.GuiColumns.DevColumn.Value = LoadSetting ? cff.GuiColumns.DevColumn : UI.GuiColumns.DevColumn.Value;
|
||||
UI.GuiColumns.VersionColumn.Value = LoadSetting ? cff.GuiColumns.VersionColumn : UI.GuiColumns.VersionColumn.Value;
|
||||
UI.GuiColumns.TimePlayedColumn.Value = LoadSetting ? cff.GuiColumns.TimePlayedColumn : UI.GuiColumns.TimePlayedColumn.Value;
|
||||
UI.GuiColumns.LastPlayedColumn.Value = LoadSetting ? cff.GuiColumns.LastPlayedColumn : UI.GuiColumns.LastPlayedColumn.Value;
|
||||
UI.GuiColumns.FileExtColumn.Value = LoadSetting ? cff.GuiColumns.FileExtColumn : UI.GuiColumns.FileExtColumn.Value;
|
||||
UI.GuiColumns.FileSizeColumn.Value = LoadSetting ? cff.GuiColumns.FileSizeColumn : UI.GuiColumns.FileSizeColumn.Value;
|
||||
UI.GuiColumns.PathColumn.Value = LoadSetting ? cff.GuiColumns.PathColumn : UI.GuiColumns.PathColumn.Value;
|
||||
UI.ColumnSort.SortColumnId.Value = LoadSetting ? cff.ColumnSort.SortColumnId : UI.ColumnSort.SortColumnId.Value;
|
||||
UI.ColumnSort.SortAscending.Value = LoadSetting ? cff.ColumnSort.SortAscending : UI.ColumnSort.SortAscending.Value;
|
||||
UI.GameDirs.Value = LoadSetting ? cff.GameDirs : UI.GameDirs.Value;
|
||||
UI.AutoloadDirs.Value = LoadSetting ? (cff.AutoloadDirs ?? []) : UI.AutoloadDirs.Value;
|
||||
UI.ShownFileTypes.NSP.Value = LoadSetting ? cff.ShownFileTypes.NSP : UI.ShownFileTypes.NSP.Value;
|
||||
UI.ShownFileTypes.PFS0.Value = LoadSetting ? cff.ShownFileTypes.PFS0 : UI.ShownFileTypes.PFS0.Value;
|
||||
UI.ShownFileTypes.XCI.Value = LoadSetting ? cff.ShownFileTypes.XCI : UI.ShownFileTypes.XCI.Value;
|
||||
UI.ShownFileTypes.NCA.Value = LoadSetting ? cff.ShownFileTypes.NCA : UI.ShownFileTypes.NCA.Value;
|
||||
UI.ShownFileTypes.NRO.Value = LoadSetting ? cff.ShownFileTypes.NRO : UI.ShownFileTypes.NRO.Value;
|
||||
UI.ShownFileTypes.NSO.Value = LoadSetting ? cff.ShownFileTypes.NSO : UI.ShownFileTypes.NSO.Value;
|
||||
UI.LanguageCode.Value = LoadSetting ? cff.LanguageCode : UI.LanguageCode.Value;
|
||||
UI.BaseStyle.Value = LoadSetting ? cff.BaseStyle : UI.BaseStyle.Value;
|
||||
UI.GameListViewMode.Value = LoadSetting ? cff.GameListViewMode : UI.GameListViewMode.Value;
|
||||
UI.ShowNames.Value = LoadSetting ? cff.ShowNames : UI.ShowNames.Value;
|
||||
UI.IsAscendingOrder.Value = LoadSetting ? cff.IsAscendingOrder : UI.IsAscendingOrder.Value;
|
||||
UI.GridSize.Value = LoadSetting ? cff.GridSize : UI.GridSize.Value;
|
||||
UI.ApplicationSort.Value = LoadSetting ? cff.ApplicationSort : UI.ApplicationSort.Value;
|
||||
UI.StartFullscreen.Value = LoadSetting ? cff.StartFullscreen : UI.StartFullscreen.Value;
|
||||
UI.StartNoUI.Value = LoadSetting ? cff.StartNoUI : UI.StartNoUI.Value;
|
||||
UI.ShowConsole.Value = LoadSetting ? cff.ShowConsole : UI.ShowConsole.Value;
|
||||
UI.WindowStartup.WindowSizeWidth.Value = LoadSetting ? cff.WindowStartup.WindowSizeWidth : UI.WindowStartup.WindowSizeWidth.Value;
|
||||
UI.WindowStartup.WindowSizeHeight.Value = LoadSetting ? cff.WindowStartup.WindowSizeHeight : UI.WindowStartup.WindowSizeHeight.Value;
|
||||
UI.WindowStartup.WindowPositionX.Value = LoadSetting ? cff.WindowStartup.WindowPositionX : UI.WindowStartup.WindowPositionX.Value;
|
||||
UI.WindowStartup.WindowPositionY.Value = LoadSetting ? cff.WindowStartup.WindowPositionY : UI.WindowStartup.WindowPositionY.Value;
|
||||
UI.WindowStartup.WindowMaximized.Value = LoadSetting ? cff.WindowStartup.WindowMaximized : UI.WindowStartup.WindowMaximized.Value;
|
||||
|
||||
|
||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
public static class ShortcutHelper
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void CreateShortcutWindows(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath)
|
||||
private static void CreateShortcutWindows(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath, string args = "")
|
||||
{
|
||||
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe");
|
||||
iconPath += ".ico";
|
||||
@ -22,13 +22,13 @@ namespace Ryujinx.Ava.Utilities
|
||||
image.Resize(new SKImageInfo(128, 128), SKFilterQuality.High);
|
||||
SaveBitmapAsIcon(image, iconPath);
|
||||
|
||||
Shortcut shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath, applicationId), iconPath, 0);
|
||||
Shortcut shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath, applicationId, args), iconPath, 0);
|
||||
shortcut.StringData.NameString = cleanedAppName;
|
||||
shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk"));
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
private static void CreateShortcutLinux(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
|
||||
private static void CreateShortcutLinux(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName, string args = "")
|
||||
{
|
||||
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
|
||||
string desktopFile = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-template.desktop");
|
||||
@ -40,11 +40,11 @@ namespace Ryujinx.Ava.Utilities
|
||||
data.SaveTo(file);
|
||||
|
||||
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
|
||||
outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath, applicationId)}");
|
||||
outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath, applicationId, args)}");
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static void CreateShortcutMacos(string appFilePath, string applicationId, byte[] iconData, string desktopPath, string cleanedAppName)
|
||||
private static void CreateShortcutMacos(string appFilePath, string applicationId, byte[] iconData, string desktopPath, string cleanedAppName, string args = "")
|
||||
{
|
||||
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
|
||||
string plistFile = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-template.plist");
|
||||
@ -63,7 +63,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
string scriptPath = Path.Combine(scriptFolderPath, ScriptName);
|
||||
using StreamWriter scriptFile = new(scriptPath);
|
||||
|
||||
scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath, applicationId));
|
||||
scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath, applicationId, args));
|
||||
|
||||
// Set execute permission
|
||||
FileInfo fileInfo = new(scriptPath);
|
||||
@ -87,7 +87,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName);
|
||||
}
|
||||
|
||||
public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData)
|
||||
public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData, string args = "")
|
||||
{
|
||||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
|
||||
string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars()));
|
||||
@ -96,7 +96,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
{
|
||||
string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app");
|
||||
|
||||
CreateShortcutWindows(applicationFilePath, applicationId, iconData, iconPath, cleanedAppName, desktopPath);
|
||||
CreateShortcutWindows(applicationFilePath, applicationId, iconData, iconPath, cleanedAppName, desktopPath, args);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -106,14 +106,14 @@ namespace Ryujinx.Ava.Utilities
|
||||
string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx");
|
||||
|
||||
Directory.CreateDirectory(iconPath);
|
||||
CreateShortcutLinux(applicationFilePath, applicationId, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName);
|
||||
CreateShortcutLinux(applicationFilePath, applicationId, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName, args);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
CreateShortcutMacos(applicationFilePath, applicationId, iconData, desktopPath, cleanedAppName);
|
||||
CreateShortcutMacos(applicationFilePath, applicationId, iconData, desktopPath, cleanedAppName, args);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -121,7 +121,7 @@ namespace Ryujinx.Ava.Utilities
|
||||
throw new NotImplementedException("Shortcut support has not been implemented yet for this OS.");
|
||||
}
|
||||
|
||||
private static string GetArgsString(string appFilePath, string applicationId)
|
||||
private static string GetArgsString(string appFilePath, string applicationId, string config = "")
|
||||
{
|
||||
// args are first defined as a list, for easier adjustments in the future
|
||||
List<string> argsList = [];
|
||||
@ -132,6 +132,11 @@ namespace Ryujinx.Ava.Utilities
|
||||
argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(config))
|
||||
{
|
||||
argsList.Add(config);
|
||||
}
|
||||
|
||||
if (appFilePath.ToLower().EndsWith(".xci"))
|
||||
{
|
||||
argsList.Add("--application-id");
|
||||
|
Loading…
x
Reference in New Issue
Block a user