Merge branch 'master_InputGLSwitch' into 'master'

Draft: Added the ability to switch between local and global input in the user configuration

See merge request ryubing/ryujinx!8
This commit is contained in:
Goodfeat 2025-04-13 04:52:39 -05:00
commit 2b13ba4de6
14 changed files with 253 additions and 63 deletions

View file

@ -6522,6 +6522,31 @@
"zh_TW": "輸入" "zh_TW": "輸入"
} }
}, },
{
"ID": "SettingsTabInputUseGlobalInput",
"Translations": {
"ar_SA": "إدخال عالمي",
"de_DE": "Globale Eingabe",
"el_GR": "Παγκόσμια εισαγωγή",
"en_US": "Global Input",
"es_ES": "Entrada Global",
"fr_FR": "Saisie Globale",
"he_IL": "קלט גלובלי",
"it_IT": "Input Globale",
"ja_JP": "グローバル入力",
"ko_KR": "글로벌 입력",
"no_NO": "Global Inndata",
"pl_PL": "Globalny Wpis",
"pt_BR": "Entrada Global",
"ru_RU": "Глобальный Ввод",
"sv_SE": "Global Input",
"th_TH": "การป้อนข้อมูลแบบโกลบอล",
"tr_TR": "Küresel Girdi",
"uk_UA": "Глобальний Ввід",
"zh_CN": "全局输入",
"zh_TW": "全域輸入"
}
},
{ {
"ID": "SettingsTabInputEnableDockedMode", "ID": "SettingsTabInputEnableDockedMode",
"Translations": { "Translations": {
@ -16272,6 +16297,31 @@
"zh_TW": "瀏覽自訂 GUI 佈景主題" "zh_TW": "瀏覽自訂 GUI 佈景主題"
} }
}, },
{
"ID": "UseGlobalInputTooltip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "If this option is enabled in custom settings, the global input configuration will be used.\n\nIn the global settings: you can enable or disable it as needed; this setting will be inherited by any new custom configurations created.",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Если эта опция включена в пользовательских настройках, будет использована глобальная конфигурация ввода.\n\nВ глобальных настройках: переключите эту опцию по своему усмотрению, это будет унаследовано для вновь созданых пользовательских конфигураций",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{ {
"ID": "DockModeToggleTooltip", "ID": "DockModeToggleTooltip",
"Translations": { "Translations": {

View file

@ -25,6 +25,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Silk.NET.Vulkan;
namespace Ryujinx.Ava namespace Ryujinx.Ava
{ {
@ -35,6 +36,7 @@ namespace Ryujinx.Ava
public static string Version { get; private set; } public static string Version { get; private set; }
public static string ConfigurationPath { get; private set; } public static string ConfigurationPath { get; private set; }
public static string GlobalConfigurationPath { get; private set; } public static string GlobalConfigurationPath { get; private set; }
public static bool UseExtraConfig{ get; private set; }
public static bool PreviewerDetached { get; private set; } public static bool PreviewerDetached { get; private set; }
public static bool UseHardwareAcceleration { get; private set; } public static bool UseHardwareAcceleration { get; private set; }
public static string BackendThreadingArg { get; private set; } public static string BackendThreadingArg { get; private set; }
@ -160,6 +162,7 @@ namespace Ryujinx.Ava
} }
} }
public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false) public static string GetDirGameUserConfig(string gameId, bool rememberGlobalDir = false, bool changeFolderForGame = false)
{ {
if (string.IsNullOrEmpty(gameId)) if (string.IsNullOrEmpty(gameId))
@ -169,24 +172,22 @@ namespace Ryujinx.Ava
string gameDir = Path.Combine(AppDataManager.GamesDirPath, gameId, ReleaseInformation.ConfigName); 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) if (changeFolderForGame)
{ {
ConfigurationPath = gameDir; ConfigurationPath = gameDir;
UseExtraConfig = true;
} }
return gameDir; return gameDir;
} }
public static void ReloadConfig() public static void SetUseExtraConfig(bool value)
{
UseExtraConfig = value;
}
public static void ReloadConfig(bool rememberGlobalDir = false)
{ {
//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 localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName); string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
@ -227,6 +228,12 @@ namespace Ryujinx.Ava
} }
} }
// When you first load the program, copy to remember the path for the global configuration
if (GlobalConfigurationPath == null)
{
GlobalConfigurationPath = ConfigurationPath;
}
UseHardwareAcceleration = ConfigurationState.Instance.EnableHardwareAcceleration; UseHardwareAcceleration = ConfigurationState.Instance.EnableHardwareAcceleration;
// Check if graphics backend was overridden // Check if graphics backend was overridden

View file

@ -461,7 +461,15 @@ namespace Ryujinx.Ava.Systems
DisplaySleep.Prevent(); DisplaySleep.Prevent();
if (ConfigurationState.Instance.System.UseInputGlobalConfig.Value && Program.UseExtraConfig)
{
NpadManager.Initialize(Device, ConfigurationState.InstanceExtra.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
}
else
{
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse); NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
}
TouchScreenManager.Initialize(Device); TouchScreenManager.Initialize(Device);
_viewModel.IsGameRunning = true; _viewModel.IsGameRunning = true;

View file

@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Systems.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 69; public const int CurrentVersion = 70;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@ -152,6 +152,11 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary> /// </summary>
public bool MatchSystemTime { get; set; } public bool MatchSystemTime { get; set; }
/// <summary>
/// Enable or disable use global input config (Independent from controllers binding)
/// </summary>
public bool UseInputGlobalConfig { get; set; }
/// <summary> /// <summary>
/// Enables or disables Docked Mode /// Enables or disables Docked Mode
/// </summary> /// </summary>

View file

@ -90,6 +90,7 @@ namespace Ryujinx.Ava.Systems.Configuration
System.TimeZone.Value = cff.SystemTimeZone; System.TimeZone.Value = cff.SystemTimeZone;
System.SystemTimeOffset.Value = shouldLoadFromFile ? cff.SystemTimeOffset : System.SystemTimeOffset.Value; // Get from global config only System.SystemTimeOffset.Value = shouldLoadFromFile ? cff.SystemTimeOffset : System.SystemTimeOffset.Value; // Get from global config only
System.MatchSystemTime.Value = shouldLoadFromFile ? cff.MatchSystemTime : System.MatchSystemTime.Value; // Get from global config only System.MatchSystemTime.Value = shouldLoadFromFile ? cff.MatchSystemTime : System.MatchSystemTime.Value; // Get from global config only
System.UseInputGlobalConfig.Value = cff.UseInputGlobalConfig;
System.EnableDockedMode.Value = cff.DockedMode; System.EnableDockedMode.Value = cff.DockedMode;
System.EnablePtc.Value = cff.EnablePtc; System.EnablePtc.Value = cff.EnablePtc;
System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc; System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;

View file

@ -326,6 +326,12 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> MatchSystemTime { get; private set; } public ReactiveObject<bool> MatchSystemTime { get; private set; }
/// <summary>
/// Enable or disable use global input config (Independent from controllers binding)
/// </summary>
public ReactiveObject<bool> UseInputGlobalConfig { get; private set; }
/// <summary> /// <summary>
/// Enables or disables Docked Mode /// Enables or disables Docked Mode
/// </summary> /// </summary>
@ -417,6 +423,8 @@ namespace Ryujinx.Ava.Systems.Configuration
SystemTimeOffset.LogChangesToValue(nameof(SystemTimeOffset)); SystemTimeOffset.LogChangesToValue(nameof(SystemTimeOffset));
MatchSystemTime = new ReactiveObject<bool>(); MatchSystemTime = new ReactiveObject<bool>();
MatchSystemTime.LogChangesToValue(nameof(MatchSystemTime)); MatchSystemTime.LogChangesToValue(nameof(MatchSystemTime));
UseInputGlobalConfig = new ReactiveObject<bool>();
UseInputGlobalConfig.LogChangesToValue(nameof(UseInputGlobalConfig));
EnableDockedMode = new ReactiveObject<bool>(); EnableDockedMode = new ReactiveObject<bool>();
EnableDockedMode.LogChangesToValue(nameof(EnableDockedMode)); EnableDockedMode.LogChangesToValue(nameof(EnableDockedMode));
EnablePtc = new ReactiveObject<bool>(); EnablePtc = new ReactiveObject<bool>();
@ -490,6 +498,7 @@ namespace Ryujinx.Ava.Systems.Configuration
/// TODO: Implement a ReactiveList class. /// TODO: Implement a ReactiveList class.
/// </summary> /// </summary>
public ReactiveObject<List<InputConfig>> InputConfig { get; private set; } public ReactiveObject<List<InputConfig>> InputConfig { get; private set; }
public ReactiveObject<List<InputConfig>> UseInputGlobalConfig { get; private set; }
/// <summary> /// <summary>
/// The speed of spectrum cycling for the Rainbow LED feature. /// The speed of spectrum cycling for the Rainbow LED feature.
@ -503,6 +512,7 @@ namespace Ryujinx.Ava.Systems.Configuration
DisableInputWhenOutOfFocus = new ReactiveObject<bool>(); DisableInputWhenOutOfFocus = new ReactiveObject<bool>();
Hotkeys = new ReactiveObject<KeyboardHotkeys>(); Hotkeys = new ReactiveObject<KeyboardHotkeys>();
InputConfig = new ReactiveObject<List<InputConfig>>(); InputConfig = new ReactiveObject<List<InputConfig>>();
UseInputGlobalConfig = new ReactiveObject<List<InputConfig>>();
RainbowSpeed = new ReactiveObject<float>(); RainbowSpeed = new ReactiveObject<float>();
RainbowSpeed.Event += (_, args) => Rainbow.Speed = args.NewValue; RainbowSpeed.Event += (_, args) => Rainbow.Speed = args.NewValue;
} }
@ -761,6 +771,8 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary> /// </summary>
public static ConfigurationState Instance { get; private set; } public static ConfigurationState Instance { get; private set; }
public static ConfigurationState InstanceExtra{ get; private set; }
/// <summary> /// <summary>
/// The UI section /// The UI section
/// </summary> /// </summary>

View file

@ -15,12 +15,13 @@ namespace Ryujinx.Ava.Systems.Configuration
{ {
public static void Initialize() public static void Initialize()
{ {
if (Instance != null) if (Instance != null || InstanceExtra!= null)
{ {
throw new InvalidOperationException("Configuration is already initialized"); throw new InvalidOperationException("Configuration is already initialized");
} }
Instance = new ConfigurationState(); Instance = new ConfigurationState();
InstanceExtra= new ConfigurationState();
} }
public ConfigurationFileFormat ToFileFormat() public ConfigurationFileFormat ToFileFormat()
@ -54,6 +55,7 @@ namespace Ryujinx.Ava.Systems.Configuration
SystemTimeZone = System.TimeZone, SystemTimeZone = System.TimeZone,
SystemTimeOffset = System.SystemTimeOffset, SystemTimeOffset = System.SystemTimeOffset,
MatchSystemTime = System.MatchSystemTime, MatchSystemTime = System.MatchSystemTime,
UseInputGlobalConfig = System.UseInputGlobalConfig,
DockedMode = System.EnableDockedMode, DockedMode = System.EnableDockedMode,
EnableDiscordIntegration = EnableDiscordIntegration, EnableDiscordIntegration = EnableDiscordIntegration,
UpdateCheckerType = UpdateCheckerType, UpdateCheckerType = UpdateCheckerType,
@ -178,6 +180,7 @@ namespace Ryujinx.Ava.Systems.Configuration
System.Region.Value = Region.USA; System.Region.Value = Region.USA;
System.TimeZone.Value = "UTC"; System.TimeZone.Value = "UTC";
System.SystemTimeOffset.Value = 0; System.SystemTimeOffset.Value = 0;
System.UseInputGlobalConfig.Value = false;
System.EnableDockedMode.Value = true; System.EnableDockedMode.Value = true;
EnableDiscordIntegration.Value = true; EnableDiscordIntegration.Value = true;
UpdateCheckerType.Value = UpdaterType.PromptAtStartup; UpdateCheckerType.Value = UpdaterType.PromptAtStartup;

View file

@ -82,6 +82,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public AvaloniaList<string> ProfilesList { get; set; } public AvaloniaList<string> ProfilesList { get; set; }
public AvaloniaList<string> DeviceList { get; set; } public AvaloniaList<string> DeviceList { get; set; }
public bool _useExtraConfig;
public bool _useGlobalInput;
// XAML Flags // XAML Flags
public bool ShowSettings => _device > 0; public bool ShowSettings => _device > 0;
public bool IsController => _device > 1; public bool IsController => _device > 1;
@ -255,12 +259,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public InputConfig Config { get; set; } public InputConfig Config { get; set; }
public InputViewModel(UserControl owner) : this() public InputViewModel(UserControl owner, bool UseGlobalInput = false) : this()
{ {
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
{ {
_mainWindow = RyujinxApp.MainWindow; _mainWindow = RyujinxApp.MainWindow;
_useExtraConfig = Program.UseExtraConfig;
AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner); AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
@ -268,6 +274,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates(); _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
_useGlobalInput = UseGlobalInput;
_isLoaded = false; _isLoaded = false;
LoadDevices(); LoadDevices();
@ -298,9 +306,18 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
PlayerIndexes.Add(new(PlayerIndex.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsHandheld])); PlayerIndexes.Add(new(PlayerIndex.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsHandheld]));
} }
private void LoadConfiguration(InputConfig inputConfig = null) private void LoadConfiguration(InputConfig inputConfig = null)
{
if (_useGlobalInput && _useExtraConfig)
{
Config = inputConfig ?? ConfigurationState.InstanceExtra.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
}
else
{ {
Config = inputConfig ?? ConfigurationState.Instance.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId); Config = inputConfig ?? ConfigurationState.Instance.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
}
if (Config is StandardKeyboardInputConfig keyboardInputConfig) if (Config is StandardKeyboardInputConfig keyboardInputConfig)
{ {
@ -834,7 +851,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
List<InputConfig> newConfig = []; List<InputConfig> newConfig = [];
if (_useGlobalInput && _useExtraConfig)
{
newConfig.AddRange(ConfigurationState.InstanceExtra.Hid.InputConfig.Value);
}
else
{
newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value); newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
}
newConfig.Remove(newConfig.FirstOrDefault(x => x == null)); newConfig.Remove(newConfig.FirstOrDefault(x => x == null));
@ -874,15 +898,24 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
} }
} }
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
// Atomically replace and signal input change. // Atomically replace and signal input change.
// NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event. // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
ConfigurationState.Instance.Hid.InputConfig.Value = newConfig; _mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
if (_useGlobalInput && _useExtraConfig)
{
// In User Settings when "Use Global Input" is enabled, it saves global input to global setting
ConfigurationState.InstanceExtra.Hid.InputConfig.Value = newConfig;
ConfigurationState.InstanceExtra.ToFileFormat().SaveConfig(Program.GlobalConfigurationPath);
}
else
{
ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
} }
}
public void NotifyChange(string property) public void NotifyChange(string property)
{ {
OnPropertyChanged(property); OnPropertyChanged(property);

View file

@ -1565,6 +1565,13 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
// Loads the user configuration, having previously changed the global configuration to the user configuration // Loads the user configuration, having previously changed the global configuration to the user configuration
ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true, true), idGame); ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true, true), idGame);
if (ConfigurationFileFormat.TryLoad(Program.GlobalConfigurationPath, out ConfigurationFileFormat configurationFileFormatExtra))
{
//This is where the global configuration will be stored.
//This allows you to change the global configuration settings during the game (for example, the global input setting)
ConfigurationState.InstanceExtra.Load(configurationFileFormatExtra, Program.GlobalConfigurationPath);
}
} }
// Code where conditions will be executed after loading user configuration // Code where conditions will be executed after loading user configuration

View file

@ -53,6 +53,7 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] private bool _isVulkanAvailable = true; [ObservableProperty] private bool _isVulkanAvailable = true;
[ObservableProperty] private bool _gameListNeedsRefresh; [ObservableProperty] private bool _gameListNeedsRefresh;
private readonly List<string> _gpuIds = []; private readonly List<string> _gpuIds = [];
public bool _useInputGlobalConfig;
private int _graphicsBackendIndex; private int _graphicsBackendIndex;
private int _scalingFilter; private int _scalingFilter;
private int _scalingFilterLevel; private int _scalingFilterLevel;
@ -64,6 +65,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public event Action CloseWindow; public event Action CloseWindow;
public event Action SaveSettingsEvent; public event Action SaveSettingsEvent;
public event Action<bool> LocalGlobalInputSwitchEvent;
private int _networkInterfaceIndex; private int _networkInterfaceIndex;
private int _multiplayerModeIndex; private int _multiplayerModeIndex;
private string _ldnPassphrase; private string _ldnPassphrase;
@ -84,6 +86,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsGameTitleNotNull => !string.IsNullOrEmpty(GameTitle); public bool IsGameTitleNotNull => !string.IsNullOrEmpty(GameTitle);
public double PanelOpacity => IsGameTitleNotNull ? 0.5 : 1; public double PanelOpacity => IsGameTitleNotNull ? 0.5 : 1;
public int ResolutionScale public int ResolutionScale
{ {
get => _resolutionScale; get => _resolutionScale;
@ -142,9 +145,22 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableKeyboard { get; set; } public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; } public bool EnableMouse { get; set; }
public bool DisableInputWhenOutOfFocus { get; set; } public bool DisableInputWhenOutOfFocus { get; set; }
public int FocusLostActionType { get; set; } public int FocusLostActionType { get; set; }
public bool EnableConfigGlobal
{
get => _useInputGlobalConfig;
set
{
_useInputGlobalConfig = value;
LocalGlobalInputSwitchEvent?.Invoke(_useInputGlobalConfig);
OnPropertyChanged(nameof(PanelOpacityInput));
OnPropertyChanged();
}
}
public double PanelOpacityInput => EnableConfigGlobal ? 0.5 : 1;
public VSyncMode VSyncMode public VSyncMode VSyncMode
{ {
get => _vSyncMode; get => _vSyncMode;
@ -411,7 +427,16 @@ namespace Ryujinx.Ava.UI.ViewModels
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
{ {
string gameDir = Program.GetDirGameUserConfig(gameId, false, true); string gameDir = Program.GetDirGameUserConfig(gameId, true, true);
Program.SetUseExtraConfig(true);
if (ConfigurationFileFormat.TryLoad(Program.GlobalConfigurationPath, out ConfigurationFileFormat configurationFileFormatExtra))
{
// Extra load global configuration for input setting and save global input setting with other global config
ConfigurationState.InstanceExtra.Load(configurationFileFormatExtra, Program.GlobalConfigurationPath);
}
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat)) if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
{ {
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId); ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
@ -551,9 +576,9 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public void LoadCurrentConfiguration() public void LoadCurrentConfiguration(bool global = false)
{ {
ConfigurationState config = ConfigurationState.Instance; ConfigurationState config = global ? ConfigurationState.InstanceExtra: ConfigurationState.Instance;
// User Interface // User Interface
EnableDiscordIntegration = config.EnableDiscordIntegration; EnableDiscordIntegration = config.EnableDiscordIntegration;
@ -579,6 +604,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}; };
// Input // Input
EnableConfigGlobal = config.System.UseInputGlobalConfig;
EnableDockedMode = config.System.EnableDockedMode; EnableDockedMode = config.System.EnableDockedMode;
EnableKeyboard = config.Hid.EnableKeyboard; EnableKeyboard = config.Hid.EnableKeyboard;
EnableMouse = config.Hid.EnableMouse; EnableMouse = config.Hid.EnableMouse;
@ -661,9 +687,9 @@ namespace Ryujinx.Ava.UI.ViewModels
LdnServer = config.Multiplayer.LdnServer; LdnServer = config.Multiplayer.LdnServer;
} }
public void SaveSettings() public void SaveSettings(bool global = false)
{ {
ConfigurationState config = ConfigurationState.Instance; ConfigurationState config = global ? ConfigurationState.InstanceExtra: ConfigurationState.Instance;
// User Interface // User Interface
config.EnableDiscordIntegration.Value = EnableDiscordIntegration; config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
@ -685,6 +711,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}; };
// Input // Input
config.System.UseInputGlobalConfig.Value = EnableConfigGlobal;
config.System.EnableDockedMode.Value = EnableDockedMode; config.System.EnableDockedMode.Value = EnableDockedMode;
config.Hid.EnableKeyboard.Value = EnableKeyboard; config.Hid.EnableKeyboard.Value = EnableKeyboard;
config.Hid.EnableMouse.Value = EnableMouse; config.Hid.EnableMouse.Value = EnableMouse;
@ -797,11 +824,14 @@ namespace Ryujinx.Ava.UI.ViewModels
private static void RevertIfNotSaved() private static void RevertIfNotSaved()
{ {
// maybe this is an unnecessary check(all options need to be tested) /*
maybe this is an unnecessary check(all options need to be tested)
if (string.IsNullOrEmpty(Program.GlobalConfigurationPath)) if (string.IsNullOrEmpty(Program.GlobalConfigurationPath))
{ {
Program.ReloadConfig(); Program.ReloadConfig();
} }
*/
Program.ReloadConfig();
} }
public void ApplyButton() public void ApplyButton()

View file

@ -1,5 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
@ -13,7 +14,7 @@ namespace Ryujinx.Ava.UI.Views.Input
public InputView() public InputView()
{ {
ViewModel = new InputViewModel(this); ViewModel = new InputViewModel(this, ConfigurationState.Instance.System.UseInputGlobalConfig.Value);
InitializeComponent(); InitializeComponent();
} }
@ -23,6 +24,14 @@ namespace Ryujinx.Ava.UI.Views.Input
ViewModel.Save(); ViewModel.Save();
} }
public void ToggleLocalGlobalInput(bool enableConfigGlobal)
{
Dispose();
ViewModel = new InputViewModel(this, enableConfigGlobal); // Create new Input Page with other input configs
InitializeComponent();
}
private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
if (PlayerIndexBox != null) if (PlayerIndexBox != null)

View file

@ -1,4 +1,4 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsInputView" x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsInputView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -22,9 +22,16 @@
<Panel <Panel
Margin="10"> Margin="10">
<Grid RowDefinitions="Auto,*,Auto"> <Grid RowDefinitions="Auto,*,Auto">
<StackPanel>
<!--
Opacity="{Binding PanelOpacityInput}">
IsEnabled="{Binding !EnableConfigGlobal}">
-->
<views:InputView <views:InputView
Grid.Row="0" Grid.Row="0"
Name="InputView" /> Name="InputView" />
</StackPanel>
<StackPanel <StackPanel
Orientation="Vertical" Orientation="Vertical"
Grid.Row="2"> Grid.Row="2">
@ -34,6 +41,13 @@
<StackPanel <StackPanel
Orientation="Horizontal" Orientation="Horizontal"
Spacing="10"> Spacing="10">
<CheckBox
ToolTip.Tip="{ext:Locale UseGlobalInputTooltip}"
MinWidth="0"
IsChecked="{Binding EnableConfigGlobal}">
<TextBlock
Text="{ext:Locale SettingsTabInputUseGlobalInput}" />
</CheckBox>
<CheckBox <CheckBox
ToolTip.Tip="{ext:Locale DockModeToggleTooltip}" ToolTip.Tip="{ext:Locale DockModeToggleTooltip}"
MinWidth="0" MinWidth="0"

View file

@ -120,15 +120,24 @@
IconSource="Code" /> IconSource="Code" />
</ui:NavigationView.MenuItems> </ui:NavigationView.MenuItems>
</ui:NavigationView> </ui:NavigationView>
<Grid Grid.Row="3"
ColumnDefinitions="Auto,*,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal" Margin="10" Spacing="10">
<Button
IsVisible="{Binding !IsGameRunning}"
Content="{ext:Locale UserProfilesDelete}"
Command="{Binding DeleteConfigGame}"
Classes="red"/>
</StackPanel>
<ReversibleStackPanel <ReversibleStackPanel
Grid.Row="2" Grid.Column="2"
Margin="10" Margin="10"
Spacing="10" Spacing="10"
Orientation="Horizontal" Orientation="Horizontal"
HorizontalAlignment="Right" HorizontalAlignment="Right"
ReverseOrder="{x:Static helper:RunningPlatform.IsMacOS}"> ReverseOrder="{x:Static helper:RunningPlatform.IsMacOS}">
<Button <Button
Classes="accent"
Content="{ext:Locale SettingsButtonSave}" Content="{ext:Locale SettingsButtonSave}"
Command="{Binding SaveUserConfig}" /> Command="{Binding SaveUserConfig}" />
<Button <Button
@ -136,14 +145,9 @@
Content="{ext:Locale SettingsButtonClose}" Content="{ext:Locale SettingsButtonClose}"
Command="{Binding CancelButton}" /> Command="{Binding CancelButton}" />
<Button <Button
IsVisible="{Binding IsGameRunning}"
Content="{ext:Locale SettingsButtonApply}" Content="{ext:Locale SettingsButtonApply}"
Command="{Binding ApplyButton}" /> Command="{Binding ApplyButton}" />
<Button
IsVisible="{Binding !IsGameRunning}"
Content="{ext:Locale UserProfilesDelete}"
Command="{Binding DeleteConfigGame}"
Classes="red"/>
</ReversibleStackPanel> </ReversibleStackPanel>
</Grid> </Grid>
</Grid>
</window:StyleableAppWindow> </window:StyleableAppWindow>

View file

@ -29,6 +29,8 @@ namespace Ryujinx.Ava.UI.Windows
ViewModel.CloseWindow += Close; ViewModel.CloseWindow += Close;
ViewModel.SaveSettingsEvent += SaveSettings; ViewModel.SaveSettingsEvent += SaveSettings;
ViewModel.LocalGlobalInputSwitchEvent += ToggleLocalGlobalInput;
InitializeComponent(); InitializeComponent();
Load(); Load();
} }
@ -38,6 +40,10 @@ namespace Ryujinx.Ava.UI.Windows
InputPage.InputView?.SaveCurrentProfile(); InputPage.InputView?.SaveCurrentProfile();
} }
public void ToggleLocalGlobalInput(bool enableConfigGlobal)
{
InputPage.InputView?.ToggleLocalGlobalInput(enableConfigGlobal);
}
private void Load() private void Load()
{ {
@ -92,6 +98,7 @@ namespace Ryujinx.Ava.UI.Windows
protected override void OnClosing(WindowClosingEventArgs e) protected override void OnClosing(WindowClosingEventArgs e)
{ {
Program.SetUseExtraConfig(false);
InputPage.Dispose(); // You need to unload the gamepad settings, otherwise the controls will be blocked InputPage.Dispose(); // You need to unload the gamepad settings, otherwise the controls will be blocked
base.OnClosing(e); base.OnClosing(e);
} }