mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-25 23:37:11 +02:00
parent
417df486b1
commit
361d0c5632
622 changed files with 3080 additions and 2652 deletions
|
@ -13,10 +13,10 @@ using LibHac.Tools.Fs;
|
|||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
|
@ -292,7 +292,7 @@ namespace Ryujinx.Ava.Common
|
|||
};
|
||||
extractorThread.Start();
|
||||
}
|
||||
|
||||
|
||||
public static void ExtractAoc(string destination, string updateFilePath, string updateName)
|
||||
{
|
||||
CancellationTokenSource cancellationToken = new();
|
||||
|
@ -416,12 +416,12 @@ namespace Ryujinx.Ava.Common
|
|||
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
|
||||
});
|
||||
|
||||
if (!result.HasValue) return;
|
||||
|
||||
if (!result.HasValue)
|
||||
return;
|
||||
|
||||
ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName);
|
||||
}
|
||||
|
||||
|
||||
public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0)
|
||||
{
|
||||
Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
|
||||
|
@ -429,7 +429,8 @@ namespace Ryujinx.Ava.Common
|
|||
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
|
||||
});
|
||||
|
||||
if (!result.HasValue) return;
|
||||
if (!result.HasValue)
|
||||
return;
|
||||
|
||||
ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using Gommon;
|
||||
using Ryujinx.Ava.Systems;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
|
@ -49,7 +49,7 @@ namespace Ryujinx.Ava.Common.Locale
|
|||
{
|
||||
string localeLanguageCode = !string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value) ?
|
||||
ConfigurationState.Instance.UI.LanguageCode.Value : CultureInfo.CurrentCulture.Name.Replace('-', '_');
|
||||
|
||||
|
||||
LoadLanguage(localeLanguageCode);
|
||||
|
||||
// Save whatever we ended up with.
|
||||
|
@ -64,8 +64,8 @@ namespace Ryujinx.Ava.Common.Locale
|
|||
public static string GetUnformatted(LocaleKeys key) => Instance.Get(key);
|
||||
|
||||
public string Get(LocaleKeys key) =>
|
||||
_localeStrings.TryGetValue(key, out string value)
|
||||
? value
|
||||
_localeStrings.TryGetValue(key, out string value)
|
||||
? value
|
||||
: key.ToString();
|
||||
|
||||
public string this[LocaleKeys key]
|
||||
|
@ -89,7 +89,7 @@ namespace Ryujinx.Ava.Common.Locale
|
|||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
return key.ToString(); // If the locale text doesn't exist return the key.
|
||||
}
|
||||
set
|
||||
|
@ -116,7 +116,7 @@ namespace Ryujinx.Ava.Common.Locale
|
|||
|
||||
OnPropertyChanged("Translation");
|
||||
}
|
||||
|
||||
|
||||
public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values)
|
||||
{
|
||||
SetDynamicValues(key, values);
|
||||
|
@ -162,8 +162,8 @@ namespace Ryujinx.Ava.Common.Locale
|
|||
if (locale.Translations.Count < _localeData.Value.Languages.Count)
|
||||
{
|
||||
throw new Exception($"Locale key {{{locale.ID}}} is missing languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (locale.Translations.Count > _localeData.Value.Languages.Count)
|
||||
{
|
||||
throw new Exception($"Locale key {{{locale.ID}}} has too many languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
|
||||
|
@ -175,7 +175,7 @@ namespace Ryujinx.Ava.Common.Locale
|
|||
string str = locale.Translations.TryGetValue(languageCode, out string val) && !string.IsNullOrEmpty(val)
|
||||
? val
|
||||
: locale.Translations[DefaultLanguageCode];
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
throw new Exception($"Locale key '{locale.ID}' has no valid translations for desired language {languageCode}! {DefaultLanguageCode} is an empty string or null");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia.Data.Core;
|
||||
using Avalonia.Data.Core;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
|
||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.Ava.Common.Markup
|
|||
Setter as Action<object, object?>,
|
||||
typeof(T));
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
=> new CompiledBindingExtension(
|
||||
new CompiledBindingPathBuilder()
|
||||
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
|
||||
|
|
|
@ -9,32 +9,32 @@ namespace Ryujinx.Ava.Common.Markup
|
|||
public override string Name => "Icon";
|
||||
protected override Icon Value => new() { Value = iconString };
|
||||
}
|
||||
|
||||
|
||||
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon>
|
||||
{
|
||||
public override string Name => "SIcon";
|
||||
protected override Icon Value => new() { Value = iconString, Animation = IconAnimation.Spin };
|
||||
}
|
||||
|
||||
|
||||
internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string>
|
||||
{
|
||||
public override string Name => "Translation";
|
||||
protected override string Value => LocaleManager.Instance[key];
|
||||
|
||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||
=> bindingExtension.Source = LocaleManager.Instance;
|
||||
}
|
||||
|
||||
|
||||
internal class WindowTitleExtension(LocaleKeys key, bool includeVersion) : BasicMarkupExtension<string>
|
||||
{
|
||||
public WindowTitleExtension(LocaleKeys key) : this(key, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override string Name => "WindowTitleTranslation";
|
||||
protected override string Value => RyujinxApp.FormatTitle(key, includeVersion);
|
||||
|
||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||
=> bindingExtension.Source = LocaleManager.Instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.Ava.Common.Models.Github
|
|||
public class GithubReleasesJsonResponse
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
public string TagName { get; set; }
|
||||
public List<GithubReleaseAssetJsonResponse> Assets { get; set; }
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace Ryujinx.Ava.Common.Models
|
|||
{
|
||||
get
|
||||
{
|
||||
return ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Undetermined &&
|
||||
ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Successful;
|
||||
return ProcessingOutcome is not XCIFileTrimmer.OperationOutcome.Undetermined and
|
||||
not XCIFileTrimmer.OperationOutcome.Successful;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,10 +43,10 @@ namespace Ryujinx.Ava.Common.Models
|
|||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
|
||||
return this.Path == obj.Path;
|
||||
}
|
||||
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Path.GetHashCode();
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ryujinx.Ava.Common
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
||||
{
|
||||
private readonly XciTrimmerViewModel _viewModel;
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Ryujinx.Headless
|
|||
// Logging system information.
|
||||
Program.PrintSystemInfo();
|
||||
}
|
||||
|
||||
|
||||
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||
{
|
||||
if (inputId == null)
|
||||
|
@ -280,7 +280,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
||||
{
|
||||
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
||||
|
@ -295,7 +295,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
foreach (DeviceInfo device in devices)
|
||||
{
|
||||
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
||||
if (device.Vendor.Equals(preferredGpuVendor, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
preferredGpuId = device.Id;
|
||||
break;
|
||||
|
@ -312,7 +312,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
return new OpenGLRenderer();
|
||||
}
|
||||
|
||||
|
||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options) =>
|
||||
new(
|
||||
new HleConfiguration(
|
||||
|
|
|
@ -86,23 +86,23 @@ namespace Ryujinx.Headless
|
|||
.WithNotParsed(errors =>
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
||||
|
||||
|
||||
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static void ReloadConfig(string customConfigPath = null)
|
||||
{
|
||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||
|
||||
string configurationPath = null;
|
||||
|
||||
|
||||
// Now load the configuration as the other subsystems are now registered
|
||||
if (customConfigPath != null && File.Exists(customConfigPath))
|
||||
{
|
||||
configurationPath = customConfigPath;
|
||||
}
|
||||
}
|
||||
else if (File.Exists(localConfigurationPath))
|
||||
{
|
||||
configurationPath = localConfigurationPath;
|
||||
|
@ -150,10 +150,10 @@ namespace Ryujinx.Headless
|
|||
}
|
||||
|
||||
AppDataManager.Initialize(option.BaseDataDir);
|
||||
|
||||
|
||||
if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out UserProfile profile))
|
||||
option.UserProfile = profile.Name;
|
||||
|
||||
|
||||
// Check if keys exists.
|
||||
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||
{
|
||||
|
@ -162,12 +162,12 @@ namespace Ryujinx.Headless
|
|||
Logger.Error?.Print(LogClass.Application, "Keys not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ReloadConfig();
|
||||
|
||||
if (!option.DisableMainInputConfig)
|
||||
option.InheritMainConfigInput(originalArgs, ConfigurationState.Instance);
|
||||
|
||||
|
||||
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
||||
_libHacHorizonManager = new LibHacHorizonManager();
|
||||
|
||||
|
@ -228,9 +228,9 @@ namespace Ryujinx.Headless
|
|||
_inputConfiguration ??= [];
|
||||
_enableKeyboard = option.EnableKeyboard;
|
||||
_enableMouse = option.EnableMouse;
|
||||
|
||||
|
||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
||||
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
|
||||
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
|
||||
|
@ -238,7 +238,7 @@ namespace Ryujinx.Headless
|
|||
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
|
||||
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
|
||||
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
|
||||
|
||||
|
||||
if (_inputConfiguration.Count == 0)
|
||||
{
|
||||
return;
|
||||
|
@ -286,7 +286,7 @@ namespace Ryujinx.Headless
|
|||
GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
|
||||
|
||||
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
||||
|
||||
|
||||
if (_inputConfiguration.OfType<StandardControllerInputConfig>()
|
||||
.Any(ic => ic?.Led?.UseRainbow ?? false))
|
||||
Rainbow.Enable();
|
||||
|
@ -306,10 +306,11 @@ namespace Ryujinx.Headless
|
|||
try
|
||||
{
|
||||
_inputManager.Dispose();
|
||||
} catch {}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return;
|
||||
|
||||
|
||||
void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||
{
|
||||
if (index == PlayerIndex.Handheld && _inputConfiguration.Count > 0)
|
||||
|
@ -317,7 +318,7 @@ namespace Ryujinx.Headless
|
|||
Logger.Info?.Print(LogClass.Configuration, "Skipping handheld configuration as there are already other players configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
InputConfig inputConfig = option.InheritedInputConfigs[index] ?? HandlePlayerConfiguration(inputProfileName, inputId, index);
|
||||
|
||||
if (inputConfig != null)
|
||||
|
@ -454,6 +455,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case ".nca":
|
||||
Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
|
||||
|
@ -464,6 +466,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case ".nsp":
|
||||
case ".pfs0":
|
||||
|
@ -475,6 +478,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
|
||||
|
@ -495,6 +499,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
if (NeedsOverride(nameof(EnableKeyboard)))
|
||||
EnableKeyboard = configurationState.Hid.EnableKeyboard;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(EnableMouse)))
|
||||
EnableMouse = configurationState.Hid.EnableMouse;
|
||||
|
||||
|
@ -39,40 +39,40 @@ namespace Ryujinx.Headless
|
|||
|
||||
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
||||
DisableFsIntegrityChecks = !configurationState.System.EnableFsIntegrityChecks;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
||||
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(VSyncMode)))
|
||||
VSyncMode = configurationState.Graphics.VSyncMode;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(CustomVSyncInterval)))
|
||||
CustomVSyncInterval = configurationState.Graphics.CustomVSyncInterval;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(DisableShaderCache)))
|
||||
DisableShaderCache = !configurationState.Graphics.EnableShaderCache;
|
||||
|
||||
if (NeedsOverride(nameof(EnableTextureRecompression)))
|
||||
EnableTextureRecompression = configurationState.Graphics.EnableTextureRecompression;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(DisableDockedMode)))
|
||||
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
||||
|
||||
if (NeedsOverride(nameof(SystemLanguage)))
|
||||
SystemLanguage = configurationState.System.Language.Value.ToHLE();
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(SystemRegion)))
|
||||
SystemRegion = configurationState.System.Region.Value.ToHLE();
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(SystemTimeZone)))
|
||||
SystemTimeZone = configurationState.System.TimeZone;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(SystemTimeOffset)))
|
||||
SystemTimeOffset = configurationState.System.SystemTimeOffset;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(MemoryManagerMode)))
|
||||
MemoryManagerMode = configurationState.System.MemoryManagerMode;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(AudioVolume)))
|
||||
AudioVolume = configurationState.System.AudioVolume;
|
||||
|
||||
|
@ -81,28 +81,28 @@ namespace Ryujinx.Headless
|
|||
|
||||
if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
|
||||
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(DisableFileLog)))
|
||||
DisableFileLog = !configurationState.Logger.EnableFileLog;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingEnableDebug)))
|
||||
LoggingEnableDebug = configurationState.Logger.EnableDebug;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableStub)))
|
||||
LoggingDisableStub = !configurationState.Logger.EnableStub;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableInfo)))
|
||||
LoggingDisableInfo = !configurationState.Logger.EnableInfo;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableWarning)))
|
||||
LoggingDisableWarning = !configurationState.Logger.EnableWarn;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableError)))
|
||||
LoggingDisableError = !configurationState.Logger.EnableError;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingEnableTrace)))
|
||||
LoggingEnableTrace = configurationState.Logger.EnableTrace;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableGuest)))
|
||||
LoggingDisableGuest = !configurationState.Logger.EnableGuest;
|
||||
|
||||
|
@ -114,40 +114,40 @@ namespace Ryujinx.Headless
|
|||
|
||||
if (NeedsOverride(nameof(ResScale)))
|
||||
ResScale = configurationState.Graphics.ResScale;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(MaxAnisotropy)))
|
||||
MaxAnisotropy = configurationState.Graphics.MaxAnisotropy;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(AspectRatio)))
|
||||
AspectRatio = configurationState.Graphics.AspectRatio;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(BackendThreading)))
|
||||
BackendThreading = configurationState.Graphics.BackendThreading;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(DisableMacroHLE)))
|
||||
DisableMacroHLE = !configurationState.Graphics.EnableMacroHLE;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(GraphicsShadersDumpPath)))
|
||||
GraphicsShadersDumpPath = configurationState.Graphics.ShadersDumpPath;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(GraphicsBackend)))
|
||||
GraphicsBackend = configurationState.Graphics.GraphicsBackend;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(AntiAliasing)))
|
||||
AntiAliasing = configurationState.Graphics.AntiAliasing;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(ScalingFilter)))
|
||||
ScalingFilter = configurationState.Graphics.ScalingFilter;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(ScalingFilterLevel)))
|
||||
ScalingFilterLevel = configurationState.Graphics.ScalingFilterLevel;
|
||||
|
||||
if (NeedsOverride(nameof(DramSize)))
|
||||
DramSize = configurationState.System.DramSize;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(IgnoreMissingServices)))
|
||||
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||
IgnoreControllerApplet = configurationState.System.IgnoreControllerApplet;
|
||||
|
||||
|
@ -155,7 +155,7 @@ namespace Ryujinx.Headless
|
|||
SkipUserProfilesManager = configurationState.System.SkipUserProfilesManager;
|
||||
|
||||
return;
|
||||
|
||||
|
||||
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||
}
|
||||
|
||||
|
@ -182,18 +182,18 @@ namespace Ryujinx.Headless
|
|||
}
|
||||
|
||||
return;
|
||||
|
||||
|
||||
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||
}
|
||||
|
||||
private static string OptionName(string propertyName) =>
|
||||
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;
|
||||
|
||||
|
||||
// General
|
||||
|
||||
|
||||
[Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")]
|
||||
public bool InheritConfig { get; set; }
|
||||
|
||||
|
||||
[Option("disable-main-input-config", Required = false, Default = false, HelpText = "Do not use the input-related settings from what was configured via the UI.")]
|
||||
public bool DisableMainInputConfig { get; set; }
|
||||
|
||||
|
@ -416,7 +416,7 @@ namespace Ryujinx.Headless
|
|||
|
||||
[Option("ignore-missing-services", Required = false, Default = false, HelpText = "Enable ignoring missing services.")]
|
||||
public bool IgnoreMissingServices { get; set; }
|
||||
|
||||
|
||||
[Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")]
|
||||
public bool IgnoreControllerApplet { get; set; }
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace Ryujinx.Headless
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private SDL2OpenGLContext _openGLContext;
|
||||
|
||||
public OpenGLWindow(
|
||||
|
|
|
@ -226,6 +226,7 @@ namespace Ryujinx.Headless
|
|||
Renderer?.Window.SetSize(Width, Height);
|
||||
MouseDriver.SetClientSize(Width, Height);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE:
|
||||
|
@ -488,8 +489,9 @@ namespace Ryujinx.Headless
|
|||
|
||||
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
||||
{
|
||||
if (_ignoreControllerApplet) return false;
|
||||
|
||||
if (_ignoreControllerApplet)
|
||||
return false;
|
||||
|
||||
string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
|
||||
|
||||
string message = $"Application requests {playerCount} {"player".ToQuantity(args.PlayerCountMin + args.PlayerCountMax, ShowQuantityAs.None)} with:\n\n"
|
||||
|
@ -558,7 +560,7 @@ namespace Ryujinx.Headless
|
|||
SDL2Driver.Instance.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public UserProfile ShowPlayerSelectDialog()
|
||||
{
|
||||
return AccountSaveDataManager.GetLastUsedUser();
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace Ryujinx.Ava.Input
|
|||
|
||||
internal bool IsPressed(Key key)
|
||||
{
|
||||
if (key == Key.Unbound || key == Key.Unknown)
|
||||
if (key is Key.Unbound or Key.Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ using Projektanker.Icons.Avalonia;
|
|||
using Projektanker.Icons.Avalonia.FontAwesome;
|
||||
using Projektanker.Icons.Avalonia.MaterialDesign;
|
||||
using Ryujinx.Ava.Systems;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.Systems.Configuration.System;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.Systems.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities.SystemInfo;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
|
@ -47,7 +47,7 @@ namespace Ryujinx.Ava
|
|||
public static int Main(string[] args)
|
||||
{
|
||||
Version = ReleaseInformation.Version;
|
||||
|
||||
|
||||
if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041))
|
||||
{
|
||||
_ = MessageBoxA(nint.Zero, "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", $"Ryujinx {Version}", MbIconwarning);
|
||||
|
@ -55,7 +55,7 @@ namespace Ryujinx.Ava
|
|||
}
|
||||
|
||||
PreviewerDetached = true;
|
||||
|
||||
|
||||
if (args.Length > 0 && args[0] is "--no-gui" or "nogui")
|
||||
{
|
||||
HeadlessRyujinx.Entrypoint(args[1..]);
|
||||
|
@ -63,7 +63,7 @@ namespace Ryujinx.Ava
|
|||
}
|
||||
|
||||
Initialize(args);
|
||||
|
||||
|
||||
LoggerAdapter.Register();
|
||||
|
||||
IconProvider.Current
|
||||
|
@ -115,11 +115,10 @@ namespace Ryujinx.Ava
|
|||
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
||||
=> ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
|
||||
TaskScheduler.UnobservedTaskException += (sender, e)
|
||||
=> ProcessUnhandledException(sender, e.Exception, false);
|
||||
=> ProcessUnhandledException(sender, e.Exception, false);
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
|
||||
|
||||
|
||||
|
||||
// Setup base data directory.
|
||||
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
|
||||
|
||||
|
@ -191,7 +190,6 @@ namespace Ryujinx.Ava
|
|||
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))
|
||||
{
|
||||
|
@ -257,7 +255,6 @@ namespace Ryujinx.Ava
|
|||
if (CommandLineState.OverrideDockedMode.HasValue)
|
||||
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
||||
|
||||
|
||||
// Check if HideCursor was overridden.
|
||||
if (CommandLineState.OverrideHideCursor is not null)
|
||||
ConfigurationState.Instance.HideCursor.Value = CommandLineState.OverrideHideCursor.ToLower() switch
|
||||
|
@ -307,13 +304,11 @@ namespace Ryujinx.Ava
|
|||
Logger.Notice.Print(LogClass.Application, $".NET Runtime: {RuntimeInformation.FrameworkDescription}");
|
||||
SystemInfo.Gather().Print();
|
||||
|
||||
Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {
|
||||
Logger.GetEnabledLevels()
|
||||
Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {Logger.GetEnabledLevels()
|
||||
.FormatCollection(
|
||||
x => x.ToString(),
|
||||
separator: ", ",
|
||||
emptyCollectionFallback: "<None>")
|
||||
}");
|
||||
x => x.ToString(),
|
||||
separator: ", ",
|
||||
emptyCollectionFallback: "<None>")}");
|
||||
|
||||
Logger.Notice.Print(LogClass.Application,
|
||||
AppDataManager.Mode == AppDataManager.LaunchMode.Custom
|
||||
|
@ -345,8 +340,8 @@ namespace Ryujinx.Ava
|
|||
else
|
||||
log.PrintMsg(LogClass.Application, message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (isTerminating)
|
||||
Exit();
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@ using Ryujinx.Audio.Integration;
|
|||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Renderer;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
|
@ -307,7 +307,7 @@ namespace Ryujinx.Ava.Systems
|
|||
Device.VSyncMode = e.NewValue;
|
||||
Device.UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
|
||||
_renderer.Window?.ChangeVSyncMode(e.NewValue);
|
||||
|
||||
_viewModel.UpdateVSyncIntervalPicker();
|
||||
|
@ -319,7 +319,7 @@ namespace Ryujinx.Ava.Systems
|
|||
bool customVSyncIntervalEnabled = ConfigurationState.Instance.Graphics.EnableCustomVSyncInterval.Value;
|
||||
|
||||
UpdateVSyncMode(this, new ReactiveEventArgs<VSyncMode>(
|
||||
oldVSyncMode,
|
||||
oldVSyncMode,
|
||||
oldVSyncMode.Next(customVSyncIntervalEnabled))
|
||||
);
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ namespace Ryujinx.Ava.Systems
|
|||
_renderingThread.Start();
|
||||
|
||||
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
||||
|
||||
|
||||
Rainbow.Enable();
|
||||
|
||||
MainLoop();
|
||||
|
@ -575,7 +575,7 @@ namespace Ryujinx.Ava.Systems
|
|||
}
|
||||
|
||||
DiscordIntegrationModule.GuestAppStartedAt = null;
|
||||
|
||||
|
||||
Rainbow.Disable();
|
||||
Rainbow.Reset();
|
||||
|
||||
|
@ -610,7 +610,6 @@ namespace Ryujinx.Ava.Systems
|
|||
if (Device.Processes != null)
|
||||
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
|
||||
|
||||
|
||||
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
|
||||
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
|
||||
ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState;
|
||||
|
@ -667,7 +666,7 @@ namespace Ryujinx.Ava.Systems
|
|||
public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||
{
|
||||
DiscordIntegrationModule.GuestAppStartedAt = Timestamps.Now;
|
||||
|
||||
|
||||
InitEmulatedSwitch();
|
||||
MainWindow.UpdateGraphicsConfig();
|
||||
|
||||
|
@ -751,7 +750,7 @@ namespace Ryujinx.Ava.Systems
|
|||
{
|
||||
romFsFiles = Directory.GetFiles(ApplicationPath, "*.romfs");
|
||||
}
|
||||
|
||||
|
||||
Logger.Notice.Print(LogClass.Application, $"Loading unpacked content archive from '{ApplicationPath}'.");
|
||||
|
||||
if (romFsFiles.Length > 0)
|
||||
|
@ -780,7 +779,7 @@ namespace Ryujinx.Ava.Systems
|
|||
else if (File.Exists(ApplicationPath))
|
||||
{
|
||||
Logger.Notice.Print(LogClass.Application, $"Loading content archive from '{ApplicationPath}'.");
|
||||
|
||||
|
||||
switch (Path.GetExtension(ApplicationPath).ToLowerInvariant())
|
||||
{
|
||||
case ".xci":
|
||||
|
@ -857,7 +856,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
|
||||
appMetadata => appMetadata.UpdatePreGame()
|
||||
);
|
||||
|
@ -1077,7 +1076,7 @@ namespace Ryujinx.Ava.Systems
|
|||
});
|
||||
|
||||
(RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
|
||||
|
||||
|
||||
// Reload settings when the game is turned off
|
||||
// (resets custom settings if there were any)
|
||||
Program.ReloadConfig();
|
||||
|
@ -1160,7 +1159,7 @@ namespace Ryujinx.Ava.Systems
|
|||
{
|
||||
if (_displayCount is 0 && _renderer.ProgramCount is 0)
|
||||
return;
|
||||
|
||||
|
||||
// If there is a mismatch between total program compile and previous count
|
||||
// this means new shaders have been compiled and should be displayed.
|
||||
if (_renderer.ProgramCount != _previousCount)
|
||||
|
@ -1233,7 +1232,7 @@ namespace Ryujinx.Ava.Systems
|
|||
{
|
||||
Device.ToggleTurbo();
|
||||
}
|
||||
|
||||
|
||||
switch (currentHotkeyState)
|
||||
{
|
||||
case KeyboardHotkeyState.ToggleVSyncMode:
|
||||
|
@ -1250,6 +1249,7 @@ namespace Ryujinx.Ava.Systems
|
|||
{
|
||||
Device.ToggleTurbo();
|
||||
}
|
||||
|
||||
break;
|
||||
case KeyboardHotkeyState.Screenshot:
|
||||
ScreenshotRequested = true;
|
||||
|
@ -1266,6 +1266,7 @@ namespace Ryujinx.Ava.Systems
|
|||
{
|
||||
Pause();
|
||||
}
|
||||
|
||||
break;
|
||||
case KeyboardHotkeyState.ToggleMute:
|
||||
if (Device.IsAudioMuted())
|
||||
|
|
|
@ -9,8 +9,8 @@ using LibHac.Tools.Fs;
|
|||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.PlayReport;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
||||
|
@ -37,13 +37,13 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
_id = value;
|
||||
|
||||
Compatibility = CompatibilityDatabase.Find(value);
|
||||
RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec)
|
||||
? gameSpec
|
||||
RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec)
|
||||
? gameSpec
|
||||
: default(Optional<GameSpec>);
|
||||
}
|
||||
}
|
||||
public Optional<GameSpec> RichPresenceSpec { get; set; }
|
||||
|
||||
|
||||
public string Developer { get; set; } = "Unknown";
|
||||
public string Version { get; set; } = "0";
|
||||
public int PlayerCount { get; set; }
|
||||
|
@ -53,7 +53,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
|
||||
public bool HasRichPresenceAsset => DiscordIntegrationModule.HasAssetImage(IdString);
|
||||
public bool HasDynamicRichPresenceSupport => RichPresenceSpec.HasValue;
|
||||
|
||||
|
||||
public TimeSpan TimePlayed { get; set; }
|
||||
public DateTime? LastPlayed { get; set; }
|
||||
public string FileExtension { get; set; }
|
||||
|
@ -70,22 +70,22 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n");
|
||||
|
||||
public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
|
||||
|
||||
|
||||
public Optional<CompatibilityEntry> Compatibility { get; private set; }
|
||||
|
||||
|
||||
public bool HasPlayabilityInfo => Compatibility.HasValue;
|
||||
|
||||
public string LocalizedStatus => Compatibility.Convert(x => x.LocalizedStatus);
|
||||
|
||||
public bool HasCompatibilityLabels => !FormattedCompatibilityLabels.Equals(string.Empty);
|
||||
|
||||
|
||||
public string FormattedCompatibilityLabels
|
||||
=> Compatibility.Convert(x => x.FormattedIssueLabels).OrElse(string.Empty);
|
||||
|
||||
|
||||
public LocaleKeys? PlayabilityStatus => Compatibility.Convert(x => x.Status).OrElse(null);
|
||||
|
||||
public string LocalizedStatusTooltip =>
|
||||
Compatibility.Convert(x =>
|
||||
Compatibility.Convert(x =>
|
||||
#pragma warning disable CS8509 // It is exhaustive for all possible values this can contain.
|
||||
LocaleManager.Instance[x.Status switch
|
||||
#pragma warning restore CS8509
|
||||
|
@ -97,7 +97,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip,
|
||||
}]
|
||||
).OrElse(string.Empty);
|
||||
|
||||
|
||||
|
||||
[JsonIgnore] public string IdString => Id.ToString("x16");
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
Logger.Error?.Print(LogClass.Application, $"File \"{titleFilePath}\" does not exist.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
Nca mainNca = null;
|
||||
|
|
|
@ -12,9 +12,9 @@ using LibHac.Tools.Fs;
|
|||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.Systems.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
|
@ -151,7 +151,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
|
||||
if (!DownloadableContents.Keys.FindFirst(x => x.TitleId == id).TryGet(out DownloadableContentModel dlcData))
|
||||
return id.ToString("X16");
|
||||
|
||||
|
||||
string name = Path.GetFileNameWithoutExtension(dlcData.FileName)!;
|
||||
int idx = name.IndexOf('[');
|
||||
if (idx != -1)
|
||||
|
@ -167,28 +167,28 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
|
||||
return appData.HasValue;
|
||||
}
|
||||
|
||||
|
||||
public bool FindUpdate(ulong id, out TitleUpdateModel foundData)
|
||||
{
|
||||
Gommon.Optional<TitleUpdateModel> appData =
|
||||
Gommon.Optional<TitleUpdateModel> appData =
|
||||
TitleUpdates.Keys.FindFirst(x => x.TitleId == id);
|
||||
foundData = appData.HasValue ? appData.Value : null;
|
||||
|
||||
return appData.HasValue;
|
||||
}
|
||||
|
||||
|
||||
public TitleUpdateModel[] FindUpdatesFor(ulong id)
|
||||
=> TitleUpdates.Keys.Where(x => x.TitleIdBase == (id & ~0x1FFFUL)).ToArray();
|
||||
|
||||
|
||||
public (TitleUpdateModel TitleUpdate, bool IsSelected)[] FindUpdateConfigurationFor(ulong id)
|
||||
=> TitleUpdates.Items.Where(x => x.TitleUpdate.TitleIdBase == (id & ~0x1FFFUL)).ToArray();
|
||||
|
||||
|
||||
public DownloadableContentModel[] FindDlcsFor(ulong id)
|
||||
=> DownloadableContents.Keys.Where(x => x.TitleIdBase == (id & ~0x1FFFUL)).ToArray();
|
||||
|
||||
|
||||
public (DownloadableContentModel Dlc, bool IsEnabled)[] FindDlcConfigurationFor(ulong id)
|
||||
=> DownloadableContents.Items.Where(x => x.Dlc.TitleIdBase == (id & ~0x1FFFUL)).ToArray();
|
||||
|
||||
|
||||
public bool HasDlcs(ulong id)
|
||||
=> DownloadableContents.Keys.Any(x => x.TitleIdBase == (id & ~0x1FFFUL));
|
||||
|
||||
|
@ -260,8 +260,8 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
}
|
||||
}
|
||||
|
||||
return isExeFs
|
||||
? GetApplicationFromExeFs(pfs, filePath)
|
||||
return isExeFs
|
||||
? GetApplicationFromExeFs(pfs, filePath)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
@ -529,7 +529,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
if (data.Id != 0)
|
||||
{
|
||||
ApplicationMetadata appMetadata = LoadAndSaveMetaData(data.IdString, appMetadata =>
|
||||
{
|
||||
{
|
||||
appMetadata.Title = data.Name;
|
||||
|
||||
// Only do the migration if time_played has a value and timespan_played hasn't been updated yet.
|
||||
|
@ -550,10 +550,9 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
// Migration successful: deleting last_played from the metadata file.
|
||||
appMetadata.LastPlayedOld = default;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
data.Favorite = appMetadata.Favorite;
|
||||
data.TimePlayed = appMetadata.TimePlayed;
|
||||
data.LastPlayed = appMetadata.LastPlayed;
|
||||
|
@ -788,7 +787,6 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Loops through applications list, creating a struct and then firing an event containing the struct for each application
|
||||
foreach (string applicationPath in applicationPaths)
|
||||
{
|
||||
|
@ -848,9 +846,9 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
public Task RefreshTotalTimePlayedAsync()
|
||||
{
|
||||
TotalTimePlayed = Gommon.Optional<TimeSpan>.None;
|
||||
|
||||
|
||||
TimeSpan temporary = TimeSpan.Zero;
|
||||
|
||||
|
||||
foreach (var installedApplication in Applications.Items)
|
||||
{
|
||||
temporary += LoadAndSaveMetaData(installedApplication.IdString).TimePlayed;
|
||||
|
@ -872,7 +870,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
{
|
||||
ldnWebHost = SharedConstants.DefaultLanPlayWebHost;
|
||||
}
|
||||
|
||||
|
||||
using HttpClient httpClient = new();
|
||||
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
|
||||
LdnGameData[] ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData).ToArray();
|
||||
|
@ -884,7 +882,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LdnGameDataReceived?.Invoke(LdnGameDataReceivedEventArgs.Empty);
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1146,8 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
|
||||
private bool AddAndAutoSelectUpdate(TitleUpdateModel update)
|
||||
{
|
||||
if (update == null) return false;
|
||||
if (update == null)
|
||||
return false;
|
||||
|
||||
DynamicData.Kernel.Optional<(TitleUpdateModel TitleUpdate, bool IsSelected)> currentlySelected = TitleUpdates.Items.FirstOrOptional(it =>
|
||||
it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected);
|
||||
|
@ -1157,7 +1156,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
currentlySelected.Value.TitleUpdate.Version < update.Version;
|
||||
|
||||
_titleUpdates.AddOrUpdate((update, shouldSelect));
|
||||
|
||||
|
||||
if (currentlySelected.HasValue && shouldSelect)
|
||||
{
|
||||
_titleUpdates.AddOrUpdate((currentlySelected.Value.TitleUpdate, false));
|
||||
|
@ -1557,7 +1556,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
if (!savedUpdateLookup.Contains(update))
|
||||
{
|
||||
bool shouldSelect = false;
|
||||
if (!selectedUpdate.HasValue || selectedUpdate.Value.Item1.Version < update.Version)
|
||||
if (!selectedUpdate.HasValue || selectedUpdate.Value.Update.Version < update.Version)
|
||||
{
|
||||
shouldSelect = true;
|
||||
if (selectedUpdate.HasValue)
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
public class Array
|
||||
{
|
||||
private readonly LdnGameData[] _ldnDatas;
|
||||
|
||||
|
||||
internal Array(IEnumerable<LdnGameData> receivedData)
|
||||
{
|
||||
_ldnDatas = receivedData.ToArray();
|
||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
|
||||
public static class LdnGameDataHelper
|
||||
{
|
||||
public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp)
|
||||
public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp)
|
||||
=> LdnGameData.GetArrayForApp(unfilteredDatas, ref acp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
public class LdnGameDataReceivedEventArgs : EventArgs
|
||||
{
|
||||
public static new readonly LdnGameDataReceivedEventArgs Empty = new(null);
|
||||
|
||||
|
||||
public LdnGameDataReceivedEventArgs(LdnGameData[] ldnData)
|
||||
{
|
||||
LdnData = ldnData ?? [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public LdnGameData[] LdnData { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using Humanizer;
|
||||
using nietras.SeparatedValues;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
|
@ -28,26 +28,26 @@ namespace Ryujinx.Ava.Systems
|
|||
.Enumerate(row => new CompatibilityEntry(ref columnIndices, row))
|
||||
.OrderBy(it => it.GameName)
|
||||
.ToArray();
|
||||
|
||||
|
||||
Logger.Debug?.Print(LogClass.UI, "Compatibility CSV loaded.", "LoadCompatibility");
|
||||
}
|
||||
|
||||
private static CompatibilityEntry[] _entries;
|
||||
|
||||
public static CompatibilityEntry[] Entries
|
||||
|
||||
public static CompatibilityEntry[] Entries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_entries == null)
|
||||
Load();
|
||||
|
||||
|
||||
return _entries;
|
||||
}
|
||||
}
|
||||
|
||||
public static CompatibilityEntry Find(string titleId)
|
||||
=> Entries.FirstOrDefault(x => x.TitleId.HasValue && x.TitleId.Value.EqualsIgnoreCase(titleId));
|
||||
|
||||
|
||||
public static CompatibilityEntry Find(ulong titleId)
|
||||
=> Find(titleId.ToString("X16"));
|
||||
}
|
||||
|
@ -57,10 +57,10 @@ namespace Ryujinx.Ava.Systems
|
|||
public CompatibilityEntry(ref ColumnIndices indices, SepReader.Row row)
|
||||
{
|
||||
string titleIdRow = ColStr(row[indices.TitleId]);
|
||||
TitleId = !string.IsNullOrEmpty(titleIdRow)
|
||||
? titleIdRow
|
||||
TitleId = !string.IsNullOrEmpty(titleIdRow)
|
||||
? titleIdRow
|
||||
: default(Optional<string>);
|
||||
|
||||
|
||||
GameName = ColStr(row[indices.GameName]);
|
||||
|
||||
Labels = ColStr(row[indices.Labels]).Split(';');
|
||||
|
@ -78,10 +78,10 @@ namespace Ryujinx.Ava.Systems
|
|||
LastUpdated = dt;
|
||||
|
||||
return;
|
||||
|
||||
string ColStr(SepReader.Col col) => col.ToString().Trim('"');
|
||||
|
||||
static string ColStr(SepReader.Col col) => col.ToString().Trim('"');
|
||||
}
|
||||
|
||||
|
||||
public string GameName { get; }
|
||||
public Optional<string> TitleId { get; }
|
||||
public string[] Labels { get; }
|
||||
|
@ -97,12 +97,12 @@ namespace Ryujinx.Ava.Systems
|
|||
LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip,
|
||||
_ => null
|
||||
};
|
||||
|
||||
|
||||
public DateTime LastUpdated { get; }
|
||||
|
||||
public string LocalizedLastUpdated =>
|
||||
LocaleManager.FormatDynamicValue(LocaleKeys.CompatibilityListLastUpdated, LastUpdated.Humanize());
|
||||
|
||||
|
||||
public string LocalizedStatus => LocaleManager.Instance[Status!.Value];
|
||||
public string LocalizedStatusDescription => LocaleManager.Instance[StatusDescription!.Value];
|
||||
public string FormattedTitleId => TitleId
|
||||
|
@ -117,9 +117,7 @@ namespace Ryujinx.Ava.Systems
|
|||
new StringBuilder("CompatibilityEntry: {")
|
||||
.Append($"{nameof(GameName)}=\"{GameName}\", ")
|
||||
.Append($"{nameof(TitleId)}={TitleId}, ")
|
||||
.Append($"{nameof(Labels)}={
|
||||
Labels.FormatCollection(it => $"\"{it}\"", separator: ", ", prefix: "[", suffix: "]")
|
||||
}, ")
|
||||
.Append($"{nameof(Labels)}={Labels.FormatCollection(it => $"\"{it}\"", separator: ", ", prefix: "[", suffix: "]")}, ")
|
||||
.Append($"{nameof(Status)}=\"{Status}\", ")
|
||||
.Append($"{nameof(LastUpdated)}=\"{LastUpdated}\"")
|
||||
.Append('}')
|
||||
|
@ -169,7 +167,7 @@ namespace Ryujinx.Ava.Systems
|
|||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public struct ColumnIndices(Func<ReadOnlySpan<char>, int> getIndex)
|
||||
{
|
||||
private const string TitleIdCol = "\"title_id\"";
|
||||
|
@ -177,7 +175,7 @@ namespace Ryujinx.Ava.Systems
|
|||
private const string LabelsCol = "\"labels\"";
|
||||
private const string StatusCol = "\"status\"";
|
||||
private const string LastUpdatedCol = "\"last_updated\"";
|
||||
|
||||
|
||||
public readonly int TitleId = getIndex(TitleIdCol);
|
||||
public readonly int GameName = getIndex(GameNameCol);
|
||||
public readonly int Labels = getIndex(LabelsCol);
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enables printing FS access log messages
|
||||
/// </summary>
|
||||
public bool LoggingEnableFsAccessLog { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enables log messages from Avalonia
|
||||
/// </summary>
|
||||
|
@ -146,7 +146,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Change System Time Offset in seconds
|
||||
/// </summary>
|
||||
public long SystemTimeOffset { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Instead of setting the time via configuration, use the values provided by the system.
|
||||
/// </summary>
|
||||
|
@ -166,12 +166,12 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// DEPRECATED: Checks for updates when Ryujinx starts when enabled
|
||||
/// </summary>
|
||||
public bool CheckUpdatesOnStart { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||
/// </summary>
|
||||
public UpdaterType UpdateCheckerType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How the emulator should behave when you click off/on the window.
|
||||
/// </summary>
|
||||
|
@ -263,7 +263,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enables or disables low-power profiled translation cache persistency loading
|
||||
/// </summary>
|
||||
public bool EnableLowPowerPtc { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clock tick scalar, in percent points (100 = 1.0).
|
||||
/// </summary>
|
||||
|
@ -398,7 +398,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enable or disable mouse support (Independent from controllers binding)
|
||||
/// </summary>
|
||||
public bool EnableMouse { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||
/// </summary>
|
||||
|
@ -413,7 +413,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Input configurations
|
||||
/// </summary>
|
||||
public List<InputConfig> InputConfig { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The speed of spectrum cycling for the Rainbow LED feature.
|
||||
/// </summary>
|
||||
|
@ -458,17 +458,17 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Uses Hypervisor over JIT if available
|
||||
/// </summary>
|
||||
public bool UseHypervisor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Show toggles for dirty hacks in the UI.
|
||||
/// </summary>
|
||||
public bool ShowDirtyHacks { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The packed values of the enabled dirty hacks.
|
||||
/// </summary>
|
||||
public ulong[] DirtyHacks { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Loads a configuration file from disk
|
||||
/// </summary>
|
||||
|
|
|
@ -33,18 +33,18 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
foreach ((int newVersion, Action<ConfigurationFileFormat> migratorFunction)
|
||||
in _migrations.OrderBy(x => x.Key))
|
||||
{
|
||||
if (cff.Version >= newVersion)
|
||||
if (cff.Version >= newVersion)
|
||||
continue;
|
||||
|
||||
RyuLogger.Warning?.Print(LogClass.Application,
|
||||
RyuLogger.Warning?.Print(LogClass.Application,
|
||||
$"Outdated configuration version {cff.Version}, migrating to version {newVersion}.");
|
||||
|
||||
|
||||
migratorFunction(cff);
|
||||
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
|
||||
UpdateCheckerType.Value = shouldLoadFromFile ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only
|
||||
FocusLostActionType.Value = cff.FocusLostActionType;
|
||||
|
@ -53,7 +53,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
ShowOldUI.Value = shouldLoadFromFile ? cff.ShowTitleBar : ShowOldUI.Value; // Get from global config only
|
||||
EnableHardwareAcceleration.Value = shouldLoadFromFile ? cff.EnableHardwareAcceleration : EnableHardwareAcceleration.Value; // Get from global config only
|
||||
HideCursor.Value = cff.HideCursor;
|
||||
|
||||
|
||||
Logger.EnableFileLog.Value = cff.EnableFileLog;
|
||||
Logger.EnableDebug.Value = cff.LoggingEnableDebug;
|
||||
Logger.EnableStub.Value = cff.LoggingEnableStub;
|
||||
|
@ -65,7 +65,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
Logger.EnableFsAccessLog.Value = cff.LoggingEnableFsAccessLog;
|
||||
Logger.FilteredClasses.Value = cff.LoggingFilteredClasses;
|
||||
Logger.GraphicsDebugLevel.Value = cff.LoggingGraphicsDebugLevel;
|
||||
|
||||
|
||||
Graphics.ResScale.Value = cff.ResScale;
|
||||
Graphics.ResScaleCustom.Value = cff.ResScaleCustom;
|
||||
Graphics.MaxAnisotropy.Value = cff.MaxAnisotropy;
|
||||
|
@ -84,7 +84,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
Graphics.EnableTextureRecompression.Value = cff.EnableTextureRecompression;
|
||||
Graphics.EnableMacroHLE.Value = cff.EnableMacroHLE;
|
||||
Graphics.EnableColorSpacePassthrough.Value = cff.EnableColorSpacePassthrough;
|
||||
|
||||
|
||||
System.Language.Value = cff.SystemLanguage;
|
||||
System.Region.Value = cff.SystemRegion;
|
||||
System.TimeZone.Value = cff.SystemTimeZone;
|
||||
|
@ -142,10 +142,9 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
UI.WindowStartup.WindowPositionY.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionY : UI.WindowStartup.WindowPositionY.Value;
|
||||
UI.WindowStartup.WindowMaximized.Value = shouldLoadFromFile ? cff.WindowStartup.WindowMaximized : UI.WindowStartup.WindowMaximized.Value;
|
||||
|
||||
|
||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
||||
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus : Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
||||
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||
Hid.RainbowSpeed.Value = cff.RainbowSpeed;
|
||||
|
@ -155,14 +154,14 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
Multiplayer.DisableP2p.Value = cff.MultiplayerDisableP2p;
|
||||
Multiplayer.LdnPassphrase.Value = cff.MultiplayerLdnPassphrase;
|
||||
Multiplayer.LdnServer.Value = cff.LdnServer;
|
||||
|
||||
{
|
||||
Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks: Hacks.ShowDirtyHacks.Value; // Get from global config only
|
||||
|
||||
DirtyHacks hacks = new (cff.DirtyHacks ?? []);
|
||||
{
|
||||
Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks : Hacks.ShowDirtyHacks.Value; // Get from global config only
|
||||
|
||||
DirtyHacks hacks = new(cff.DirtyHacks ?? []);
|
||||
|
||||
Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (configurationFileUpdated)
|
||||
|
@ -172,7 +171,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
RyuLogger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static readonly Dictionary<int, Action<ConfigurationFileFormat>> _migrations =
|
||||
Collections.NewDictionary<int, Action<ConfigurationFileFormat>>(
|
||||
(2, static cff => cff.SystemRegion = Region.USA),
|
||||
|
@ -184,13 +183,15 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
{
|
||||
cff.ColumnSort = new ColumnSort { SortColumnId = 0, SortAscending = false };
|
||||
cff.Hotkeys = new KeyboardHotkeys { ToggleVSyncMode = Key.F1 };
|
||||
}),
|
||||
}
|
||||
),
|
||||
(10, static cff => cff.AudioBackend = AudioBackend.OpenAl),
|
||||
(11, static cff =>
|
||||
{
|
||||
cff.ResScale = 1;
|
||||
cff.ResScaleCustom = 1.0f;
|
||||
}),
|
||||
}
|
||||
),
|
||||
(12, static cff => cff.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None),
|
||||
// 13 -> LDN1
|
||||
(14, static cff => cff.CheckUpdatesOnStart = true),
|
||||
|
@ -205,7 +206,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
|
||||
cff.MultiplayerMode = MultiplayerMode.Disabled;
|
||||
cff.MultiplayerLanInterfaceId = "0";
|
||||
}),
|
||||
}
|
||||
),
|
||||
(22, static cff => cff.HideCursor = HideCursorMode.Never),
|
||||
(24, static cff =>
|
||||
{
|
||||
|
@ -260,14 +262,17 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
},
|
||||
}
|
||||
];
|
||||
}),
|
||||
}
|
||||
),
|
||||
(26, static cff => cff.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe),
|
||||
(27, static cff => cff.EnableMouse = false),
|
||||
(29,
|
||||
static cff =>
|
||||
cff.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVSyncMode = Key.F1, Screenshot = Key.F8, ShowUI = Key.F4
|
||||
ToggleVSyncMode = Key.F1,
|
||||
Screenshot = Key.F8,
|
||||
ShowUI = Key.F4
|
||||
}),
|
||||
(30, static cff =>
|
||||
{
|
||||
|
@ -275,10 +280,13 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
{
|
||||
config.Rumble = new RumbleConfigController
|
||||
{
|
||||
EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
|
||||
EnableRumble = false,
|
||||
StrongRumble = 1f,
|
||||
WeakRumble = 1f,
|
||||
};
|
||||
}
|
||||
}),
|
||||
}
|
||||
),
|
||||
(31, static cff => cff.BackendThreading = BackendThreading.Auto),
|
||||
(32, static cff => cff.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
|
@ -299,7 +307,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
};
|
||||
|
||||
cff.AudioVolume = 1;
|
||||
}),
|
||||
}
|
||||
),
|
||||
(34, static cff => cff.EnableInternetAccess = false),
|
||||
(35, static cff =>
|
||||
{
|
||||
|
@ -309,7 +318,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
config.RangeLeft = 1.0f;
|
||||
config.RangeRight = 1.0f;
|
||||
}
|
||||
}),
|
||||
}
|
||||
),
|
||||
|
||||
(36, static cff => cff.LoggingEnableTrace = false),
|
||||
(37, static cff => cff.ShowConsole = true),
|
||||
|
@ -320,7 +330,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
cff.ShowNames = true;
|
||||
cff.GridSize = 2;
|
||||
cff.LanguageCode = "en_US";
|
||||
}),
|
||||
}
|
||||
),
|
||||
(39,
|
||||
static cff => cff.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
|
@ -353,7 +364,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
cff.AntiAliasing = AntiAliasing.None;
|
||||
cff.ScalingFilter = ScalingFilter.Bilinear;
|
||||
cff.ScalingFilterLevel = 80;
|
||||
}),
|
||||
}
|
||||
),
|
||||
(45,
|
||||
static cff => cff.ShownFileTypes = new ShownFileTypes
|
||||
{
|
||||
|
@ -381,7 +393,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
{
|
||||
AppDataManager.FixMacOSConfigurationFolders();
|
||||
}
|
||||
}),
|
||||
}
|
||||
),
|
||||
(50, static cff => cff.EnableHardwareAcceleration = true),
|
||||
(51, static cff => cff.RememberWindowState = true),
|
||||
(52, static cff => cff.AutoloadDirs = []),
|
||||
|
@ -410,7 +423,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
};
|
||||
|
||||
cff.CustomVSyncInterval = 120;
|
||||
}),
|
||||
}
|
||||
),
|
||||
// 58 migration accidentally got skipped, but it worked with no issues somehow lol
|
||||
(59, static cff =>
|
||||
{
|
||||
|
@ -420,7 +434,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
// This was accidentally enabled by default when it was PRed. That is not what we want,
|
||||
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
||||
cff.IgnoreApplet = false;
|
||||
}),
|
||||
}
|
||||
),
|
||||
(60, static cff => cff.StartNoUI = false),
|
||||
(61, static cff =>
|
||||
{
|
||||
|
@ -434,7 +449,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
LedColor = new Color(255, 5, 1, 253).ToUInt32()
|
||||
};
|
||||
}
|
||||
}),
|
||||
}
|
||||
),
|
||||
(62, static cff => cff.RainbowSpeed = 1f),
|
||||
(63, static cff => cff.MatchSystemTime = false),
|
||||
(64, static cff => cff.LoggingEnableAvalonia = false),
|
||||
|
@ -460,7 +476,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
TurboMode = Key.Unbound,
|
||||
TurboModeWhileHeld = false
|
||||
};
|
||||
}),
|
||||
}
|
||||
),
|
||||
(69, static cff => cff.SkipUserProfiles = false)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enables printing FS access log messages
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableFsAccessLog { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enables log messages from Avalonia
|
||||
/// </summary>
|
||||
|
@ -320,7 +320,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// System Time Offset in Seconds
|
||||
/// </summary>
|
||||
public ReactiveObject<long> SystemTimeOffset { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Instead of setting the time via configuration, use the values provided by the system.
|
||||
/// </summary>
|
||||
|
@ -335,7 +335,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enables or disables persistent profiled translation cache
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnablePtc { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clock tick scalar, in percent points (100 = 1.0).
|
||||
/// </summary>
|
||||
|
@ -389,7 +389,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enable or disable ignoring missing services
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ignore Controller Applet
|
||||
/// </summary>
|
||||
|
@ -423,7 +423,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
EnablePtc.LogChangesToValue(nameof(EnablePtc));
|
||||
EnableLowPowerPtc = new ReactiveObject<bool>();
|
||||
EnableLowPowerPtc.LogChangesToValue(nameof(EnableLowPowerPtc));
|
||||
EnableLowPowerPtc.Event += (_, evnt)
|
||||
EnableLowPowerPtc.Event += (_, evnt)
|
||||
=> Optimizations.LowPower = evnt.NewValue;
|
||||
TickScalar = new ReactiveObject<long>();
|
||||
TickScalar.LogChangesToValue(nameof(TickScalar));
|
||||
|
@ -473,7 +473,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enable or disable mouse support (Independent from controllers binding)
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableMouse { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||
/// </summary>
|
||||
|
@ -490,7 +490,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// TODO: Implement a ReactiveList class.
|
||||
/// </summary>
|
||||
public ReactiveObject<List<InputConfig>> InputConfig { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The speed of spectrum cycling for the Rainbow LED feature.
|
||||
/// </summary>
|
||||
|
@ -676,8 +676,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
public string GetLdnServer()
|
||||
{
|
||||
string ldnServer = LdnServer;
|
||||
return string.IsNullOrEmpty(ldnServer)
|
||||
? SharedConstants.DefaultLanPlayHost
|
||||
return string.IsNullOrEmpty(ldnServer)
|
||||
? SharedConstants.DefaultLanPlayHost
|
||||
: ldnServer;
|
||||
}
|
||||
|
||||
|
@ -701,9 +701,9 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Show toggles for dirty hacks in the UI.
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> ShowDirtyHacks { get; private set; }
|
||||
|
||||
|
||||
public ReactiveObject<bool> Xc2MenuSoftlockFix { get; private set; }
|
||||
|
||||
|
||||
public ReactiveObject<bool> DisableNifmIsAnyInternetRequestAccepted { get; private set; }
|
||||
|
||||
public HacksSection()
|
||||
|
@ -717,15 +717,15 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
|
||||
private void HackChanged(object sender, ReactiveEventArgs<bool> rxe)
|
||||
{
|
||||
if (!ShowDirtyHacks)
|
||||
if (!ShowDirtyHacks)
|
||||
return;
|
||||
|
||||
|
||||
string newHacks = EnabledHacks.Select(x => x.Hack)
|
||||
.JoinToString(", ");
|
||||
|
||||
if (newHacks != _lastHackCollection)
|
||||
{
|
||||
RyuLogger.Info?.Print(LogClass.Configuration,
|
||||
RyuLogger.Info?.Print(LogClass.Configuration,
|
||||
$"EnabledDirtyHacks set to: [{newHacks}]", "LogValueChange");
|
||||
|
||||
_lastHackCollection = newHacks;
|
||||
|
@ -739,13 +739,13 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
get
|
||||
{
|
||||
List<EnabledDirtyHack> enabledHacks = [];
|
||||
|
||||
|
||||
if (Xc2MenuSoftlockFix)
|
||||
Apply(DirtyHack.Xc2MenuSoftlockFix);
|
||||
|
||||
|
||||
if (DisableNifmIsAnyInternetRequestAccepted)
|
||||
Apply(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted);
|
||||
|
||||
|
||||
return enabledHacks.ToArray();
|
||||
|
||||
void Apply(DirtyHack hack, int value = 0)
|
||||
|
@ -790,7 +790,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// The Multiplayer section
|
||||
/// </summary>
|
||||
public MultiplayerSection Multiplayer { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Dirty Hacks section
|
||||
/// </summary>
|
||||
|
@ -800,12 +800,12 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
/// Enables or disables Discord Rich Presence
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification.
|
||||
/// </summary>
|
||||
public ReactiveObject<UpdaterType> UpdateCheckerType { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How the emulator should behave when you click off/on the window.
|
||||
/// </summary>
|
||||
|
@ -865,8 +865,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
System.EnablePtc,
|
||||
System.TickScalar,
|
||||
System.EnableInternetAccess,
|
||||
System.EnableFsIntegrityChecks
|
||||
? IntegrityCheckLevel.ErrorOnInvalid
|
||||
System.EnableFsIntegrityChecks
|
||||
? IntegrityCheckLevel.ErrorOnInvalid
|
||||
: IntegrityCheckLevel.None,
|
||||
System.FsGlobalAccessLogMode,
|
||||
System.MatchSystemTime
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
NRO,
|
||||
NSO
|
||||
}
|
||||
|
||||
|
||||
public static class FileTypesExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -10,23 +10,23 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
ConfigurationState.Instance.Logger.EnableDebug.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableDebug.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Debug, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableStub.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableStub.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Stub, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableInfo.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableInfo.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Info, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableWarn.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableWarn.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Warning, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableError.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableError.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Error, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableTrace.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableTrace.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Trace, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableGuest.Event +=
|
||||
ConfigurationState.Instance.Logger.EnableGuest.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.Guest, e.NewValue);
|
||||
ConfigurationState.Instance.Logger.EnableFsAccessLog.Event +=
|
||||
(_, e) => Logger.SetEnable(LogLevel.AccessLog, e.NewValue);
|
||||
|
||||
|
||||
ConfigurationState.Instance.Logger.FilteredClasses.Event += (_, e) =>
|
||||
{
|
||||
bool noFilter = e.NewValue.Length == 0;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ryujinx.Ava.Systems.Configuration.System
|
|||
Korea,
|
||||
Taiwan,
|
||||
}
|
||||
|
||||
|
||||
public static class RegionEnumHelper
|
||||
{
|
||||
public static Region ToUI(this HLE.HOS.SystemState.RegionCode hleRegion)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Ava.Systems.Configuration.UI
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using DiscordRPC;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.Systems.PlayReport;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE;
|
||||
|
@ -42,7 +42,8 @@ namespace Ryujinx.Ava.Systems
|
|||
{
|
||||
Assets = new Assets
|
||||
{
|
||||
LargeImageKey = "ryujinx", LargeImageText = TruncateToByteLength(_description)
|
||||
LargeImageKey = "ryujinx",
|
||||
LargeImageText = TruncateToByteLength(_description)
|
||||
},
|
||||
Details = "Main Menu",
|
||||
State = "Idling",
|
||||
|
@ -122,14 +123,18 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
private static void HandlePlayReport(Horizon.Prepo.Types.PlayReport playReport)
|
||||
{
|
||||
if (_discordClient is null) return;
|
||||
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
||||
if (_discordPresencePlaying is null) return;
|
||||
if (_discordClient is null)
|
||||
return;
|
||||
if (!TitleIDs.CurrentApplication.Value.HasValue)
|
||||
return;
|
||||
if (_discordPresencePlaying is null)
|
||||
return;
|
||||
|
||||
FormattedValue formattedValue =
|
||||
PlayReports.Analyzer.Format(TitleIDs.CurrentApplication.Value, _currentApp, playReport);
|
||||
|
||||
if (!formattedValue.Handled) return;
|
||||
if (!formattedValue.Handled)
|
||||
return;
|
||||
|
||||
_discordPresencePlaying.Details = TruncateToByteLength(
|
||||
formattedValue.Reset
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
|
@ -71,14 +71,12 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
return AddSpec(transform(GameSpec.Create(tids)));
|
||||
|
||||
Logger.Notice.PrintMsg(LogClass.Application,
|
||||
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{
|
||||
tids.FormatCollection(
|
||||
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{tids.FormatCollection(
|
||||
x => x,
|
||||
separator: ", ",
|
||||
prefix: "[",
|
||||
suffix: "]"
|
||||
)
|
||||
}'");
|
||||
)}'");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -95,14 +93,12 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
return AddSpec(GameSpec.Create(tids).Apply(transform));
|
||||
|
||||
Logger.Notice.PrintMsg(LogClass.Application,
|
||||
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{
|
||||
tids.FormatCollection(
|
||||
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{tids.FormatCollection(
|
||||
x => x,
|
||||
separator: ", ",
|
||||
prefix: "[",
|
||||
suffix: "]"
|
||||
)
|
||||
}'");
|
||||
)}'");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -117,7 +113,6 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Runs the configured <see cref="FormatterSpec"/> for the specified game title ID.
|
||||
/// </summary>
|
||||
|
@ -133,7 +128,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
{
|
||||
if (!playReport.ReportData.IsDictionary)
|
||||
return FormattedValue.Unhandled;
|
||||
|
||||
|
||||
if (!TryGetSpec(runningGameId, out GameSpec spec))
|
||||
return FormattedValue.Unhandled;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace Ryujinx.Ava.Systems.PlayReport
|
||||
namespace Ryujinx.Ava.Systems.PlayReport
|
||||
{
|
||||
/// <summary>
|
||||
/// The delegate type that powers single value formatters.<br/>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using MsgPack;
|
||||
using MsgPack;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
@ -10,12 +10,12 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
{
|
||||
Matched = matched;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The currently running application's <see cref="ApplicationMetadata"/>.
|
||||
/// </summary>
|
||||
public ApplicationMetadata Application { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The entire play report.
|
||||
/// </summary>
|
||||
|
@ -26,7 +26,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
/// </summary>
|
||||
public T Matched { get; init; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The input data to a <see cref="SingleValueFormatter"/>,
|
||||
/// containing the currently running application's <see cref="ApplicationMetadata"/>,
|
||||
|
@ -65,7 +65,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
public SparseMultiValue(Dictionary<string, Value> matched) : base(matched)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public SparseMultiValue(Dictionary<string, MessagePackObject> matched) : base(Value.ConvertPackedObjectMap(matched))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using Humanizer;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
|
@ -19,7 +19,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
< -201d => "Exploring the Depths",
|
||||
_ => "Roaming Hyrule"
|
||||
};
|
||||
|
||||
|
||||
private static FormattedValue SkywardSwordHD_Rupees(SingleValue value)
|
||||
=> "rupee".ToQuantity(value.Matched.IntValue);
|
||||
|
||||
|
@ -59,13 +59,13 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
"Race" => "Racing",
|
||||
_ => FormattedValue.ForceReset
|
||||
};
|
||||
|
||||
|
||||
private static FormattedValue PokemonSV(MultiValue values)
|
||||
{
|
||||
|
||||
|
||||
string playStatus = values.Matched[0].BoxedValue is 0 ? "Playing Alone" : "Playing in a group";
|
||||
|
||||
FormattedValue locations = values.Matched[1].ToString() switch
|
||||
|
||||
FormattedValue locations = values.Matched[1].ToString() switch
|
||||
{
|
||||
// Base Game Locations
|
||||
"a_w01" => "South Area One",
|
||||
|
@ -97,8 +97,8 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
//TODO DLC Locations
|
||||
_ => FormattedValue.ForceReset
|
||||
};
|
||||
|
||||
return$"{playStatus} in {locations}";
|
||||
|
||||
return $"{playStatus} in {locations}";
|
||||
}
|
||||
|
||||
private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values)
|
||||
|
@ -121,7 +121,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
|
||||
if (values.Matched.ContainsKey("is_created"))
|
||||
{
|
||||
return "Edited a Custom Stage!";
|
||||
return "Edited a Custom Stage!";
|
||||
}
|
||||
|
||||
if (values.Matched.ContainsKey("adv_slot"))
|
||||
|
@ -179,97 +179,97 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
private static string SuperSmashBrosUltimate_Character(Value value) =>
|
||||
BinaryPrimitives.ReverseEndianness(
|
||||
BitConverter.ToInt64(((MsgPack.MessagePackExtendedTypeObject)value.BoxedValue).GetBody(), 0)) switch
|
||||
{
|
||||
0x0 => "Mario",
|
||||
0x1 => "Donkey Kong",
|
||||
0x2 => "Link",
|
||||
0x3 => "Samus",
|
||||
0x4 => "Dark Samus",
|
||||
0x5 => "Yoshi",
|
||||
0x6 => "Kirby",
|
||||
0x7 => "Fox",
|
||||
0x8 => "Pikachu",
|
||||
0x9 => "Luigi",
|
||||
0xA => "Ness",
|
||||
0xB => "Captain Falcon",
|
||||
0xC => "Jigglypuff",
|
||||
0xD => "Peach",
|
||||
0xE => "Daisy",
|
||||
0xF => "Bowser",
|
||||
0x10 => "Ice Climbers",
|
||||
0x11 => "Sheik",
|
||||
0x12 => "Zelda",
|
||||
0x13 => "Dr. Mario",
|
||||
0x14 => "Pichu",
|
||||
0x15 => "Falco",
|
||||
0x16 => "Marth",
|
||||
0x17 => "Lucina",
|
||||
0x18 => "Young Link",
|
||||
0x19 => "Ganondorf",
|
||||
0x1A => "Mewtwo",
|
||||
0x1B => "Roy",
|
||||
0x1C => "Chrom",
|
||||
0x1D => "Mr Game & Watch",
|
||||
0x1E => "Meta Knight",
|
||||
0x1F => "Pit",
|
||||
0x20 => "Dark Pit",
|
||||
0x21 => "Zero Suit Samus",
|
||||
0x22 => "Wario",
|
||||
0x23 => "Snake",
|
||||
0x24 => "Ike",
|
||||
0x25 => "Pokémon Trainer",
|
||||
0x26 => "Diddy Kong",
|
||||
0x27 => "Lucas",
|
||||
0x28 => "Sonic",
|
||||
0x29 => "King Dedede",
|
||||
0x2A => "Olimar",
|
||||
0x2B => "Lucario",
|
||||
0x2C => "R.O.B.",
|
||||
0x2D => "Toon Link",
|
||||
0x2E => "Wolf",
|
||||
0x2F => "Villager",
|
||||
0x30 => "Mega Man",
|
||||
0x31 => "Wii Fit Trainer",
|
||||
0x32 => "Rosalina & Luma",
|
||||
0x33 => "Little Mac",
|
||||
0x34 => "Greninja",
|
||||
0x35 => "Palutena",
|
||||
0x36 => "Pac-Man",
|
||||
0x37 => "Robin",
|
||||
0x38 => "Shulk",
|
||||
0x39 => "Bowser Jr.",
|
||||
0x3A => "Duck Hunt",
|
||||
0x3B => "Ryu",
|
||||
0x3C => "Ken",
|
||||
0x3D => "Cloud",
|
||||
0x3E => "Corrin",
|
||||
0x3F => "Bayonetta",
|
||||
0x40 => "Richter",
|
||||
0x41 => "Inkling",
|
||||
0x42 => "Ridley",
|
||||
0x43 => "King K. Rool",
|
||||
0x44 => "Simon",
|
||||
0x45 => "Isabelle",
|
||||
0x46 => "Incineroar",
|
||||
0x47 => "Mii Brawler",
|
||||
0x48 => "Mii Swordfighter",
|
||||
0x49 => "Mii Gunner",
|
||||
0x4A => "Piranha Plant",
|
||||
0x4B => "Joker",
|
||||
0x4C => "Hero",
|
||||
0x4D => "Banjo",
|
||||
0x4E => "Terry",
|
||||
0x4F => "Byleth",
|
||||
0x50 => "Min Min",
|
||||
0x51 => "Steve",
|
||||
0x52 => "Sephiroth",
|
||||
0x53 => "Pyra/Mythra",
|
||||
0x54 => "Kazuya",
|
||||
0x55 => "Sora",
|
||||
0xFE => "Random",
|
||||
0xFF => "Scripted Entity",
|
||||
_ => "Unknown"
|
||||
};
|
||||
{
|
||||
0x0 => "Mario",
|
||||
0x1 => "Donkey Kong",
|
||||
0x2 => "Link",
|
||||
0x3 => "Samus",
|
||||
0x4 => "Dark Samus",
|
||||
0x5 => "Yoshi",
|
||||
0x6 => "Kirby",
|
||||
0x7 => "Fox",
|
||||
0x8 => "Pikachu",
|
||||
0x9 => "Luigi",
|
||||
0xA => "Ness",
|
||||
0xB => "Captain Falcon",
|
||||
0xC => "Jigglypuff",
|
||||
0xD => "Peach",
|
||||
0xE => "Daisy",
|
||||
0xF => "Bowser",
|
||||
0x10 => "Ice Climbers",
|
||||
0x11 => "Sheik",
|
||||
0x12 => "Zelda",
|
||||
0x13 => "Dr. Mario",
|
||||
0x14 => "Pichu",
|
||||
0x15 => "Falco",
|
||||
0x16 => "Marth",
|
||||
0x17 => "Lucina",
|
||||
0x18 => "Young Link",
|
||||
0x19 => "Ganondorf",
|
||||
0x1A => "Mewtwo",
|
||||
0x1B => "Roy",
|
||||
0x1C => "Chrom",
|
||||
0x1D => "Mr Game & Watch",
|
||||
0x1E => "Meta Knight",
|
||||
0x1F => "Pit",
|
||||
0x20 => "Dark Pit",
|
||||
0x21 => "Zero Suit Samus",
|
||||
0x22 => "Wario",
|
||||
0x23 => "Snake",
|
||||
0x24 => "Ike",
|
||||
0x25 => "Pokémon Trainer",
|
||||
0x26 => "Diddy Kong",
|
||||
0x27 => "Lucas",
|
||||
0x28 => "Sonic",
|
||||
0x29 => "King Dedede",
|
||||
0x2A => "Olimar",
|
||||
0x2B => "Lucario",
|
||||
0x2C => "R.O.B.",
|
||||
0x2D => "Toon Link",
|
||||
0x2E => "Wolf",
|
||||
0x2F => "Villager",
|
||||
0x30 => "Mega Man",
|
||||
0x31 => "Wii Fit Trainer",
|
||||
0x32 => "Rosalina & Luma",
|
||||
0x33 => "Little Mac",
|
||||
0x34 => "Greninja",
|
||||
0x35 => "Palutena",
|
||||
0x36 => "Pac-Man",
|
||||
0x37 => "Robin",
|
||||
0x38 => "Shulk",
|
||||
0x39 => "Bowser Jr.",
|
||||
0x3A => "Duck Hunt",
|
||||
0x3B => "Ryu",
|
||||
0x3C => "Ken",
|
||||
0x3D => "Cloud",
|
||||
0x3E => "Corrin",
|
||||
0x3F => "Bayonetta",
|
||||
0x40 => "Richter",
|
||||
0x41 => "Inkling",
|
||||
0x42 => "Ridley",
|
||||
0x43 => "King K. Rool",
|
||||
0x44 => "Simon",
|
||||
0x45 => "Isabelle",
|
||||
0x46 => "Incineroar",
|
||||
0x47 => "Mii Brawler",
|
||||
0x48 => "Mii Swordfighter",
|
||||
0x49 => "Mii Gunner",
|
||||
0x4A => "Piranha Plant",
|
||||
0x4B => "Joker",
|
||||
0x4C => "Hero",
|
||||
0x4D => "Banjo",
|
||||
0x4E => "Terry",
|
||||
0x4F => "Byleth",
|
||||
0x50 => "Min Min",
|
||||
0x51 => "Steve",
|
||||
0x52 => "Sephiroth",
|
||||
0x53 => "Pyra/Mythra",
|
||||
0x54 => "Kazuya",
|
||||
0x55 => "Sora",
|
||||
0xFE => "Random",
|
||||
0xFF => "Scripted Entity",
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
private static string SuperSmashBrosUltimate_PlayerListing(SparseMultiValue values)
|
||||
{
|
||||
|
@ -295,16 +295,14 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
players = players.OrderBy(p => p.Rank ?? int.MaxValue).ToList();
|
||||
|
||||
return players.Count > 4
|
||||
? $"{players.Count} Players - {
|
||||
players.Take(3)
|
||||
? $"{players.Count} Players - {players.Take(3)
|
||||
.Select(p => $"{p.Character}({p.PlayerNumber}){RankMedal(p.Rank)}")
|
||||
.JoinToString(", ")
|
||||
}"
|
||||
.JoinToString(", ")}"
|
||||
: players
|
||||
.Select(p => $"{p.Character}({p.PlayerNumber}){RankMedal(p.Rank)}")
|
||||
.JoinToString(", ");
|
||||
|
||||
string RankMedal(int? rank) => rank switch
|
||||
static string RankMedal(int? rank) => rank switch
|
||||
{
|
||||
0 => "🥇",
|
||||
1 => "🥈",
|
||||
|
@ -371,7 +369,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
"m_9417_e" => Playing("Zero Wing"),
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Nintendo 64
|
||||
|
||||
"n_1653_e" or "n_1653_p" => Playing("1080º ™ Snowboarding"),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.Systems.PlayReport
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using MsgPack;
|
||||
using MsgPack;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -36,9 +36,8 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
: null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<FormatterSpecBase> ValueFormatters { get; } = [];
|
||||
|
||||
public List<FormatterSpecBase> ValueFormatters { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Add a value formatter to the current <see cref="GameSpec"/>
|
||||
|
@ -66,7 +65,9 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
SingleValueFormatter valueFormatter
|
||||
) => AddValueFormatter(new FormatterSpec
|
||||
{
|
||||
Priority = priority, ReportKeys = [reportKey], Formatter = valueFormatter
|
||||
Priority = priority,
|
||||
ReportKeys = [reportKey],
|
||||
Formatter = valueFormatter
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
|
@ -95,7 +96,9 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
MultiValueFormatter valueFormatter
|
||||
) => AddValueFormatter(new MultiFormatterSpec
|
||||
{
|
||||
Priority = priority, ReportKeys = reportKeys, Formatter = valueFormatter
|
||||
Priority = priority,
|
||||
ReportKeys = reportKeys,
|
||||
Formatter = valueFormatter
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
|
@ -130,7 +133,9 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
SparseMultiValueFormatter valueFormatter
|
||||
) => AddValueFormatter(new SparseMultiFormatterSpec
|
||||
{
|
||||
Priority = priority, ReportKeys = reportKeys, Formatter = valueFormatter
|
||||
Priority = priority,
|
||||
ReportKeys = reportKeys,
|
||||
Formatter = valueFormatter
|
||||
});
|
||||
|
||||
private GameSpec AddValueFormatter<T>(T formatterSpec) where T : FormatterSpecBase
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using MsgPack;
|
||||
using MsgPack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -130,7 +130,7 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
/// A delegate singleton you can use to always return <see cref="ForceReset"/> in a <see cref="MultiValueFormatter"/>.
|
||||
/// </summary>
|
||||
public static readonly MultiValueFormatter MultiAlwaysResets = _ => ForceReset;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A delegate singleton you can use to always return <see cref="ForceReset"/> in a <see cref="SparseMultiValueFormatter"/>.
|
||||
/// </summary>
|
||||
|
@ -142,14 +142,14 @@ namespace Ryujinx.Ava.Systems.PlayReport
|
|||
/// </summary>
|
||||
/// <param name="formattedValue">The string to always return for this delegate instance.</param>
|
||||
public static SingleValueFormatter SingleAlwaysReturns(string formattedValue) => _ => formattedValue;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A delegate factory you can use to always return the specified
|
||||
/// <paramref name="formattedValue"/> in a <see cref="MultiValueFormatter"/>.
|
||||
/// </summary>
|
||||
/// <param name="formattedValue">The string to always return for this delegate instance.</param>
|
||||
public static MultiValueFormatter MultiAlwaysReturns(string formattedValue) => _ => formattedValue;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A delegate factory you can use to always return the specified
|
||||
/// <paramref name="formattedValue"/> in a <see cref="SparseMultiValueFormatter"/>.
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||
|
||||
|
||||
public static void RebootAppWithGame(string gamePath, List<string> args)
|
||||
{
|
||||
_ = Reboot(gamePath, args);
|
||||
|
@ -37,10 +36,9 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
if (shouldRestart)
|
||||
{
|
||||
List<string> arguments = CommandLineState.Arguments.ToList();
|
||||
string executableDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
var dialogTask = taskDialog.ShowAsync(true);
|
||||
_ = taskDialog.ShowAsync(true);
|
||||
await Task.Delay(500);
|
||||
|
||||
// Find the process name.
|
||||
|
|
|
@ -32,9 +32,9 @@ namespace Ryujinx.Ava.Systems
|
|||
internal static class Updater
|
||||
{
|
||||
private static ReleaseChannels.Channel? _currentReleaseChannel;
|
||||
|
||||
|
||||
private const string GitHubApiUrl = "https://api.github.com";
|
||||
|
||||
|
||||
private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
@ -43,10 +43,10 @@ namespace Ryujinx.Ava.Systems
|
|||
private const int ConnectionCount = 4;
|
||||
|
||||
private static string _buildVer;
|
||||
|
||||
|
||||
|
||||
private static readonly string _platformExt = BuildPlatformExtension();
|
||||
|
||||
|
||||
private static string _buildUrl;
|
||||
private static long _buildSize;
|
||||
private static bool _updateSuccessful;
|
||||
|
@ -68,14 +68,14 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
return default;
|
||||
}
|
||||
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, "Checking for updates.");
|
||||
|
||||
|
||||
// Get latest version number from GitHub API
|
||||
try
|
||||
{
|
||||
using HttpClient jsonClient = ConstructHttpClient();
|
||||
|
||||
|
||||
if (_currentReleaseChannel == null)
|
||||
{
|
||||
ReleaseChannels releaseChannels = await ReleaseInformation.GetReleaseChannelsAsync(jsonClient);
|
||||
|
@ -84,7 +84,7 @@ namespace Ryujinx.Ava.Systems
|
|||
? releaseChannels.Canary
|
||||
: releaseChannels.Stable;
|
||||
}
|
||||
|
||||
|
||||
string fetchedJson = await jsonClient.GetStringAsync(_currentReleaseChannel.Value.GetLatestReleaseApiUrl());
|
||||
GithubReleasesJsonResponse fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse);
|
||||
_buildVer = fetched.TagName;
|
||||
|
@ -108,7 +108,7 @@ namespace Ryujinx.Ava.Systems
|
|||
OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, "Up to date.");
|
||||
|
||||
_running = false;
|
||||
|
@ -134,7 +134,7 @@ namespace Ryujinx.Ava.Systems
|
|||
OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, "Up to date.");
|
||||
|
||||
_running = false;
|
||||
|
@ -169,7 +169,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
return (currentVersion, newVersion);
|
||||
}
|
||||
|
||||
|
||||
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
|
||||
{
|
||||
if (_running)
|
||||
|
@ -181,7 +181,8 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
Optional<(Version, Version)> versionTuple = await CheckVersionAsync(showVersionUpToDate);
|
||||
|
||||
if (_running is false || !versionTuple.HasValue) return;
|
||||
if (_running is false || !versionTuple.HasValue)
|
||||
return;
|
||||
|
||||
(Version currentVersion, Version newVersion) = versionTuple.Value;
|
||||
|
||||
|
@ -198,7 +199,7 @@ namespace Ryujinx.Ava.Systems
|
|||
OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, "Up to date.");
|
||||
|
||||
_running = false;
|
||||
|
@ -229,9 +230,9 @@ namespace Ryujinx.Ava.Systems
|
|||
string newVersionString = ReleaseInformation.IsCanaryBuild
|
||||
? $"Canary {currentVersion} -> Canary {newVersion}"
|
||||
: $"{currentVersion} -> {newVersion}";
|
||||
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"Version found: {newVersionString}");
|
||||
|
||||
|
||||
RequestUserToUpdate:
|
||||
// Show a message asking the user if they want to update
|
||||
UserResult shouldUpdate = await ContentDialogHelper.CreateUpdaterChoiceDialog(
|
||||
|
@ -442,8 +443,8 @@ namespace Ryujinx.Ava.Systems
|
|||
// On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution.
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
using Process xattrProcess = Process.Start("xattr",
|
||||
[ "-d", "com.apple.quarantine", updateFile ]);
|
||||
using Process xattrProcess = Process.Start("xattr",
|
||||
["-d", "com.apple.quarantine", updateFile]);
|
||||
|
||||
xattrProcess.WaitForExit();
|
||||
}
|
||||
|
@ -491,7 +492,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
using HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result;
|
||||
using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result;
|
||||
using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
|
||||
using FileStream updateFileStream = File.Open(updateFile, FileMode.Create);
|
||||
|
||||
long totalBytes = response.Content.Headers.ContentLength.Value;
|
||||
long bytesWritten = 0;
|
||||
|
@ -538,7 +539,7 @@ namespace Ryujinx.Ava.Systems
|
|||
[SupportedOSPlatform("macos")]
|
||||
private static void ExtractTarGzipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
|
||||
{
|
||||
using Stream inStream = File.OpenRead(archivePath);
|
||||
using FileStream inStream = File.OpenRead(archivePath);
|
||||
using GZipInputStream gzipStream = new(inStream);
|
||||
using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
|
||||
|
||||
|
@ -781,7 +782,7 @@ namespace Ryujinx.Ava.Systems
|
|||
public static void CleanupUpdate() =>
|
||||
Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories)
|
||||
.ForEach(File.Delete);
|
||||
|
||||
|
||||
private static string BuildPlatformExtension()
|
||||
{
|
||||
if (RunningPlatform.IsMacOS)
|
||||
|
@ -800,7 +801,7 @@ namespace Ryujinx.Ava.Systems
|
|||
Architecture.X64 => "x64",
|
||||
_ => throw new PlatformNotSupportedException($"Unknown architecture {Enum.GetName(RunningPlatform.Architecture)}."),
|
||||
};
|
||||
|
||||
|
||||
string fileExtension = RunningPlatform.CurrentOS switch
|
||||
#pragma warning restore CS8509
|
||||
{
|
||||
|
|
|
@ -3,11 +3,11 @@ using Avalonia.Threading;
|
|||
using FluentAvalonia.UI.Controls;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
|
@ -179,11 +179,13 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
try
|
||||
{
|
||||
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||
SoftwareKeyboardUIArgs args = new();
|
||||
args.KeyboardMode = KeyboardMode.Default;
|
||||
args.InitialText = "Ryujinx";
|
||||
args.StringLengthMin = 1;
|
||||
args.StringLengthMax = 25;
|
||||
SoftwareKeyboardUIArgs args = new()
|
||||
{
|
||||
KeyboardMode = KeyboardMode.Default,
|
||||
InitialText = "Ryujinx",
|
||||
StringLengthMin = 1,
|
||||
StringLengthMax = 25
|
||||
};
|
||||
(UserResult result, string userInput) =
|
||||
await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args);
|
||||
if (result == UserResult.Ok)
|
||||
|
@ -220,7 +222,6 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
dialogCloseEvent.WaitOne();
|
||||
}
|
||||
|
||||
|
||||
public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
|
||||
{
|
||||
device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
|
||||
|
@ -240,7 +241,9 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
{
|
||||
ErrorAppletWindow msgDialog = new(_parent, buttons, message)
|
||||
{
|
||||
Title = title, WindowStartupLocation = WindowStartupLocation.CenterScreen, Width = 400
|
||||
Title = title,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
Width = 400
|
||||
};
|
||||
|
||||
object response = await msgDialog.Run();
|
||||
|
@ -291,7 +294,8 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
profiles.Add(new Models.UserProfile(guest, nav));
|
||||
ProfileSelectorDialogViewModel viewModel = new()
|
||||
{
|
||||
Profiles = profiles, SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
|
||||
Profiles = profiles,
|
||||
SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
|
||||
};
|
||||
(selected, _) = await ProfileSelectorDialog.ShowInputDialog(viewModel);
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
|
||||
{
|
||||
DataContext = ViewModel = viewModel;
|
||||
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private void Grid_PointerEntered(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (sender is Grid { DataContext: UserProfile profile })
|
||||
|
@ -61,7 +61,7 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
if (item is UserProfile originalItem)
|
||||
{
|
||||
UserProfileSft profile = new(originalItem.UserId, originalItem.Name, originalItem.Image);
|
||||
|
||||
|
||||
if (profile.UserId == ViewModel.SelectedUserId)
|
||||
{
|
||||
profile.AccountState = AccountState.Open;
|
||||
|
@ -98,13 +98,13 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
|
||||
UserId result = UserId.Null;
|
||||
bool input = false;
|
||||
|
||||
|
||||
contentDialog.Closed += Handler;
|
||||
|
||||
await ContentDialogHelper.ShowAsync(contentDialog);
|
||||
|
||||
return (result, input);
|
||||
|
||||
|
||||
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Result == ContentDialogResult.Primary)
|
||||
|
|
|
@ -7,12 +7,12 @@ using LibHac.Tools.FsSystem.NcaUtils;
|
|||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.HLE.HOS;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
|
||||
|
|
|
@ -154,12 +154,12 @@ namespace Ryujinx.Ava.UI.Controls
|
|||
|
||||
if (profile == null)
|
||||
{
|
||||
_ = Dispatcher.UIThread.InvokeAsync(async ()
|
||||
_ = Dispatcher.UIThread.InvokeAsync(async ()
|
||||
=> await ContentDialogHelper.CreateErrorDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogUserProfileDeletionWarningMessage]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AccountManager.OpenUser(profile.UserId);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Controls;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using System;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
|
@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.Controls
|
|||
public static readonly Bitmap Bitmap =
|
||||
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
|
||||
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
|
||||
|
||||
|
||||
public RyujinxLogo()
|
||||
{
|
||||
Margin = new Thickness(7, 7, 7, 0);
|
||||
|
|
|
@ -59,4 +59,4 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
=> new(action);
|
||||
public static RelayCommand CreateConditional(Func<bool> canExecute, Action action)
|
||||
=> new(action, canExecute);
|
||||
|
||||
|
||||
public static RelayCommand<T> Create<T>(Action<T?> action)
|
||||
=> new(action);
|
||||
public static RelayCommand<T> CreateConditional<T>(Predicate<T?> canExecute, Action<T?> action)
|
||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
=> new(action, AsyncRelayCommandOptions.AllowConcurrentExecutions);
|
||||
public static AsyncRelayCommand CreateSilentFail(Func<Task> action)
|
||||
=> new(action, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
|
||||
|
||||
|
||||
public static AsyncRelayCommand<T> Create<T>(Func<T?, Task> action)
|
||||
=> new(action, AsyncRelayCommandOptions.None);
|
||||
public static AsyncRelayCommand<T> CreateConcurrent<T>(Func<T?, Task> action)
|
||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
=> new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions);
|
||||
public static AsyncRelayCommand CreateSilentFailConditional(Func<bool> canExecute, Func<Task> action)
|
||||
=> new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
|
||||
|
||||
|
||||
public static AsyncRelayCommand<T> CreateConditional<T>(Predicate<T?> canExecute, Func<T?, Task> action)
|
||||
=> new(action, canExecute, AsyncRelayCommandOptions.None);
|
||||
public static AsyncRelayCommand<T> CreateConcurrentConditional<T>(Predicate<T?> canExecute, Func<T?, Task> action)
|
||||
|
|
|
@ -23,13 +23,13 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
|
||||
|
||||
public static ContentDialog ApplyStyles(
|
||||
this ContentDialog contentDialog,
|
||||
double closeButtonWidth = 80,
|
||||
this ContentDialog contentDialog,
|
||||
double closeButtonWidth = 80,
|
||||
HorizontalAlignment buttonSpaceAlignment = HorizontalAlignment.Right)
|
||||
{
|
||||
Style closeButton = new(x => x.Name("CloseButton"));
|
||||
closeButton.Setters.Add(new Setter(Layoutable.WidthProperty, closeButtonWidth));
|
||||
|
||||
|
||||
Style closeButtonParent = new(x => x.Name("CommandSpace"));
|
||||
closeButtonParent.Setters.Add(new Setter(Layoutable.HorizontalAlignmentProperty, buttonSpaceAlignment));
|
||||
|
||||
|
@ -281,7 +281,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Important);
|
||||
|
||||
|
||||
internal static async Task<UserResult> CreateUpdaterUpToDateInfoDialog(string primary, string secondaryText)
|
||||
=> await ShowTextDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle],
|
||||
|
@ -339,7 +339,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
|
||||
return response == UserResult.Yes;
|
||||
}
|
||||
|
||||
|
||||
internal static async Task<UserResult> CreateUpdaterChoiceDialog(string title, string primary, string secondaryText)
|
||||
{
|
||||
if (_isChoiceDialogOpen)
|
||||
|
@ -403,7 +403,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
Position = parent.PointToScreen(new Point()),
|
||||
ShowInTaskbar = false,
|
||||
};
|
||||
|
||||
|
||||
#if DEBUG
|
||||
_contentDialogOverlayWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
|
||||
#endif
|
||||
|
@ -480,7 +480,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
await dialogWindow.ShowDialog(_contentDialogOverlayWindow ?? mainWindow ?? GetMainWindow());
|
||||
}
|
||||
|
||||
private static Window GetMainWindow()
|
||||
private static MainWindow GetMainWindow()
|
||||
{
|
||||
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,5 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
{
|
||||
keyString = key.ToString();
|
||||
}
|
||||
|
||||
break;
|
||||
case GamepadInputId gamepadInputId:
|
||||
if (_gamepadInputIdMap.TryGetValue(gamepadInputId, out localeKey))
|
||||
|
@ -160,6 +161,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
{
|
||||
keyString = gamepadInputId.ToString();
|
||||
}
|
||||
|
||||
break;
|
||||
case StickInputId stickInputId:
|
||||
if (_stickInputIdMap.TryGetValue(stickInputId, out localeKey))
|
||||
|
@ -170,6 +172,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
{
|
||||
keyString = stickInputId.ToString();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
{
|
||||
if (value is not ApplicationData { HasLdnGames: true } applicationData)
|
||||
return "";
|
||||
|
||||
|
||||
return new StringBuilder()
|
||||
.AppendLine(
|
||||
LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Media;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
|
@ -15,8 +15,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
public object Convert(object value, Type _, object __, CultureInfo ___)
|
||||
=> value.Cast<LocaleKeys>() switch
|
||||
{
|
||||
LocaleKeys.CompatibilityListNothing or
|
||||
LocaleKeys.CompatibilityListBoots or
|
||||
LocaleKeys.CompatibilityListNothing or
|
||||
LocaleKeys.CompatibilityListBoots or
|
||||
LocaleKeys.CompatibilityListMenus => Brushes.Red,
|
||||
LocaleKeys.CompatibilityListIngame => Brushes.DarkOrange,
|
||||
_ => Brushes.ForestGreen
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
}
|
||||
|
||||
return app.PercentageProgress != null ? String.Empty :
|
||||
app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] :
|
||||
app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] :
|
||||
app.Trimmable & app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusPartialLabel] :
|
||||
app.Trimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusTrimmableLabel] :
|
||||
app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusUntrimmableLabel] :
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
}
|
||||
|
||||
return app.PercentageProgress != null ? null :
|
||||
app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() :
|
||||
app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() :
|
||||
null;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
{
|
||||
SKColor color = GetColor(image);
|
||||
|
||||
|
||||
// We don't want colors that are too dark.
|
||||
// If the color is too dark, make it brighter by reducing the range
|
||||
// and adding a constant color.
|
||||
|
|
|
@ -15,19 +15,20 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
|
||||
internal class LoggerAdapter : ILogSink
|
||||
{
|
||||
private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog;
|
||||
|
||||
private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog;
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
AvaLogger.Sink = new LoggerAdapter();
|
||||
ConfigurationState.Instance.Logger.EnableAvaloniaLog.Event
|
||||
ConfigurationState.Instance.Logger.EnableAvaloniaLog.Event
|
||||
+= (_, e) => _avaloniaLogsEnabled = e.NewValue;
|
||||
}
|
||||
|
||||
private static RyuLogger.Log? GetLog(AvaLogLevel level, string area)
|
||||
{
|
||||
if (!_avaloniaLogsEnabled) return null;
|
||||
|
||||
if (!_avaloniaLogsEnabled)
|
||||
return null;
|
||||
|
||||
return level switch
|
||||
{
|
||||
AvaLogLevel.Verbose => RyuLogger.Debug,
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
|
||||
public static void ShowError(string message) =>
|
||||
ShowError(
|
||||
LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
|
||||
LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
|
||||
$"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}"
|
||||
);
|
||||
|
||||
|
@ -73,8 +73,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
title,
|
||||
text,
|
||||
NotificationType.Information,
|
||||
waitingExit,
|
||||
onClick,
|
||||
waitingExit,
|
||||
onClick,
|
||||
onClose);
|
||||
|
||||
public static void ShowSuccess(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
||||
|
@ -82,8 +82,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
title,
|
||||
text,
|
||||
NotificationType.Success,
|
||||
waitingExit,
|
||||
onClick,
|
||||
waitingExit,
|
||||
onClick,
|
||||
onClose);
|
||||
|
||||
public static void ShowWarning(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
||||
|
@ -91,8 +91,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
title,
|
||||
text,
|
||||
NotificationType.Warning,
|
||||
waitingExit,
|
||||
onClick,
|
||||
waitingExit,
|
||||
onClick,
|
||||
onClose);
|
||||
|
||||
public static void ShowError(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
||||
|
@ -100,8 +100,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
title,
|
||||
text,
|
||||
NotificationType.Error,
|
||||
waitingExit,
|
||||
onClick,
|
||||
waitingExit,
|
||||
onClick,
|
||||
onClose);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
IdcArrow = 32512,
|
||||
}
|
||||
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
public enum WindowsMessages : uint
|
||||
{
|
||||
NcHitTest = 0x0084,
|
||||
|
|
|
@ -33,4 +33,4 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,21 +46,21 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
|
||||
[ObservableProperty] private GamepadInputId _buttonMinus;
|
||||
[ObservableProperty] private GamepadInputId _buttonPlus;
|
||||
|
||||
|
||||
[ObservableProperty] private GamepadInputId _buttonA;
|
||||
[ObservableProperty] private GamepadInputId _buttonB;
|
||||
[ObservableProperty] private GamepadInputId _buttonX;
|
||||
[ObservableProperty] private GamepadInputId _buttonY;
|
||||
|
||||
|
||||
[ObservableProperty] private GamepadInputId _buttonZl;
|
||||
[ObservableProperty] private GamepadInputId _buttonZr;
|
||||
|
||||
|
||||
[ObservableProperty] private GamepadInputId _buttonL;
|
||||
[ObservableProperty] private GamepadInputId _buttonR;
|
||||
|
||||
|
||||
[ObservableProperty] private GamepadInputId _leftButtonSl;
|
||||
[ObservableProperty] private GamepadInputId _leftButtonSr;
|
||||
|
||||
|
||||
[ObservableProperty] private GamepadInputId _rightButtonSl;
|
||||
[ObservableProperty] private GamepadInputId _rightButtonSr;
|
||||
|
||||
|
@ -73,17 +73,17 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
[ObservableProperty] private float _triggerThreshold;
|
||||
|
||||
[ObservableProperty] private bool _enableMotion;
|
||||
|
||||
|
||||
[ObservableProperty] private bool _enableRumble;
|
||||
|
||||
|
||||
[ObservableProperty] private bool _enableLedChanging;
|
||||
|
||||
|
||||
[ObservableProperty] private Color _ledColor;
|
||||
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
|
||||
private bool _turnOffLed;
|
||||
|
||||
|
||||
public bool TurnOffLed
|
||||
{
|
||||
get => _turnOffLed;
|
||||
|
@ -94,9 +94,9 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool _useRainbowLed;
|
||||
|
||||
|
||||
public bool UseRainbowLed
|
||||
{
|
||||
get => _useRainbowLed;
|
||||
|
@ -183,7 +183,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
WeakRumble = controllerInput.Rumble.WeakRumble;
|
||||
StrongRumble = controllerInput.Rumble.StrongRumble;
|
||||
}
|
||||
|
||||
|
||||
if (controllerInput.Led != null)
|
||||
{
|
||||
EnableLedChanging = controllerInput.Led.EnableLed;
|
||||
|
@ -204,7 +204,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
StandardControllerInputConfig config = new()
|
||||
{
|
||||
Id = Id,
|
||||
Name = Name,
|
||||
Name = Name,
|
||||
Backend = InputBackendType.GamepadSDL2,
|
||||
PlayerIndex = PlayerIndex,
|
||||
ControllerType = ControllerType,
|
||||
|
|
|
@ -29,24 +29,24 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
[ObservableProperty] private Key _dpadDown;
|
||||
[ObservableProperty] private Key _dpadLeft;
|
||||
[ObservableProperty] private Key _dpadRight;
|
||||
|
||||
|
||||
[ObservableProperty] private Key _buttonMinus;
|
||||
[ObservableProperty] private Key _buttonPlus;
|
||||
|
||||
|
||||
[ObservableProperty] private Key _buttonA;
|
||||
[ObservableProperty] private Key _buttonB;
|
||||
[ObservableProperty] private Key _buttonX;
|
||||
[ObservableProperty] private Key _buttonY;
|
||||
|
||||
|
||||
[ObservableProperty] private Key _buttonL;
|
||||
[ObservableProperty] private Key _buttonR;
|
||||
|
||||
|
||||
[ObservableProperty] private Key _buttonZl;
|
||||
[ObservableProperty] private Key _buttonZr;
|
||||
|
||||
|
||||
[ObservableProperty] private Key _leftButtonSl;
|
||||
[ObservableProperty] private Key _leftButtonSr;
|
||||
|
||||
|
||||
[ObservableProperty] private Key _rightButtonSl;
|
||||
[ObservableProperty] private Key _rightButtonSr;
|
||||
|
||||
|
|
|
@ -96,9 +96,9 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
public float UiStickRightX => ClampVector(UiStickRight).Item1;
|
||||
public float UiStickRightY => ClampVector(UiStickRight).Item2;
|
||||
|
||||
public int UiStickCircumference => DrawStickCircumference;
|
||||
public int UiCanvasSize => DrawStickCanvasSize;
|
||||
public int UiStickBorderSize => DrawStickBorderSize;
|
||||
public static int UiStickCircumference => DrawStickCircumference;
|
||||
public static int UiCanvasSize => DrawStickCanvasSize;
|
||||
public static int UiStickBorderSize => DrawStickBorderSize;
|
||||
|
||||
public float? UiDeadzoneLeft => _gamepadConfig?.DeadzoneLeft * DrawStickCanvasSize - DrawStickCircumference;
|
||||
public float? UiDeadzoneRight => _gamepadConfig?.DeadzoneRight * DrawStickCanvasSize - DrawStickCircumference;
|
||||
|
@ -158,14 +158,17 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
{
|
||||
leftBuffer.Item1 += 1;
|
||||
}
|
||||
|
||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickLeft))
|
||||
{
|
||||
leftBuffer.Item1 -= 1;
|
||||
}
|
||||
|
||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickUp))
|
||||
{
|
||||
leftBuffer.Item2 += 1;
|
||||
}
|
||||
|
||||
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickDown))
|
||||
{
|
||||
leftBuffer.Item2 -= 1;
|
||||
|
@ -175,14 +178,17 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
{
|
||||
rightBuffer.Item1 += 1;
|
||||
}
|
||||
|
||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickLeft))
|
||||
{
|
||||
rightBuffer.Item1 -= 1;
|
||||
}
|
||||
|
||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickUp))
|
||||
{
|
||||
rightBuffer.Item2 += 1;
|
||||
}
|
||||
|
||||
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickDown))
|
||||
{
|
||||
rightBuffer.Item2 -= 1;
|
||||
|
@ -191,6 +197,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
UiStickLeft = leftBuffer;
|
||||
UiStickRight = rightBuffer;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DeviceType.Controller:
|
||||
|
@ -201,6 +208,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||
leftBuffer = controller.GetStick((StickInputId)GamepadConfig.LeftJoystick);
|
||||
rightBuffer = controller.GetStick((StickInputId)GamepadConfig.RightJoystick);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DeviceType.None:
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Ava.UI.Models
|
|||
public string Path { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public string FormattedName =>
|
||||
public string FormattedName =>
|
||||
InSd && ulong.TryParse(Name, NumberStyles.HexNumber, null, out ulong applicationId)
|
||||
? $"Atmosphère: {RyujinxApp.MainWindow.ApplicationLibrary.GetNameForApplicationId(applicationId)}"
|
||||
: Name;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using Gommon;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Ncm;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
|
@ -23,10 +23,10 @@ namespace Ryujinx.Ava.UI.Models
|
|||
ShaderCount = shaderCount;
|
||||
}
|
||||
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is not StatusUpdatedEventArgs suea) return false;
|
||||
if (obj is not StatusUpdatedEventArgs suea)
|
||||
return false;
|
||||
return
|
||||
VSyncMode == suea.VSyncMode &&
|
||||
VolumeStatus == suea.VolumeStatus &&
|
||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Models
|
|||
ShaderCount == suea.ShaderCount;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
public override int GetHashCode()
|
||||
=> HashCode.Combine(VSyncMode, VolumeStatus, AspectRatio, DockedMode, FifoStatus, GameStatus, ShaderCount);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
private IPlatformHandle CreateLinux(IPlatformHandle control)
|
||||
private PlatformHandle CreateLinux(IPlatformHandle control)
|
||||
{
|
||||
if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan)
|
||||
{
|
||||
|
@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
IPlatformHandle CreateWin32(IPlatformHandle control)
|
||||
PlatformHandle CreateWin32(IPlatformHandle control)
|
||||
{
|
||||
_className = "NativeWindow-" + Guid.NewGuid();
|
||||
|
||||
|
@ -171,7 +171,7 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
IPlatformHandle CreateMacOS()
|
||||
PlatformHandle CreateMacOS()
|
||||
{
|
||||
// Create a new CAMetalLayer.
|
||||
ObjectiveC.Object layerObject = new("CAMetalLayer");
|
||||
|
@ -215,11 +215,9 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
void DestroyMacOS()
|
||||
static void DestroyMacOS()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
|
@ -36,8 +36,8 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
EmbeddedWindowOpenGL => GraphicsBackend.OpenGl,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;
|
||||
|
|
|
@ -8,11 +8,11 @@ using Avalonia.Threading;
|
|||
using FluentAvalonia.UI.Windowing;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.Ava
|
|||
public class RyujinxApp : Application
|
||||
{
|
||||
public static event Action ThemeChanged;
|
||||
|
||||
|
||||
internal static string FormatTitle(LocaleKeys? windowTitleKey = null, bool includeVersion = true)
|
||||
=> windowTitleKey is null
|
||||
? $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)}"
|
||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.Ava
|
|||
public static MainWindow MainWindow => Current!
|
||||
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()
|
||||
.MainWindow.Cast<MainWindow>();
|
||||
|
||||
|
||||
public static IClassicDesktopStyleApplicationLifetime AppLifetime => Current!
|
||||
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>();
|
||||
|
||||
|
@ -48,7 +48,6 @@ namespace Ryujinx.Ava
|
|||
public static void SetTaskbarProgressValue(ulong current, ulong total) => MainWindow.PlatformFeatures.SetTaskBarProgressBarValue(current, total);
|
||||
public static void SetTaskbarProgressValue(long current, long total) => SetTaskbarProgressValue(Convert.ToUInt64(current), Convert.ToUInt64(total));
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
Name = FormatTitle();
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
[ObservableProperty] private Bitmap _gitLabLogo;
|
||||
[ObservableProperty] private Bitmap _discordLogo;
|
||||
[ObservableProperty] private string _version;
|
||||
|
||||
|
||||
public string Developers => "GreemDev, LotP";
|
||||
|
||||
public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz");
|
||||
|
@ -37,9 +37,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private void UpdateLogoTheme(string theme)
|
||||
{
|
||||
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
|
||||
|
||||
|
||||
string themeName = isDarkTheme ? "Dark" : "Light";
|
||||
|
||||
|
||||
DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName));
|
||||
GitLabLogo = LoadBitmap(LogoPathFormat.Format("GitLab", themeName));
|
||||
}
|
||||
|
@ -49,10 +49,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
public void Dispose()
|
||||
{
|
||||
RyujinxApp.ThemeChanged -= Ryujinx_ThemeChanged;
|
||||
|
||||
|
||||
GitLabLogo.Dispose();
|
||||
DiscordLogo.Dispose();
|
||||
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.PlayReport;
|
||||
|
@ -20,8 +20,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer);
|
||||
public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension);
|
||||
public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString);
|
||||
|
||||
public string FormattedLdnInfo =>
|
||||
|
||||
public string FormattedLdnInfo =>
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" +
|
||||
$"\n" +
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Gommon;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Systems;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System;
|
||||
|
@ -19,15 +19,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid)))
|
||||
: _currentEntries;
|
||||
|
||||
public CompatibilityViewModel() {}
|
||||
|
||||
public CompatibilityViewModel() { }
|
||||
|
||||
private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __)
|
||||
=> _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
|
||||
|
||||
public CompatibilityViewModel(ApplicationLibrary appLibrary)
|
||||
{
|
||||
_appLibrary = appLibrary;
|
||||
|
||||
|
||||
AppCountUpdated(null, null);
|
||||
|
||||
_appLibrary.ApplicationCountUpdated += AppCountUpdated;
|
||||
|
@ -38,7 +38,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
GC.SuppressFinalize(this);
|
||||
_appLibrary.ApplicationCountUpdated -= AppCountUpdated;
|
||||
}
|
||||
|
||||
|
||||
private bool _onlyShowOwnedGames = true;
|
||||
|
||||
public bool OnlyShowOwnedGames
|
||||
|
@ -69,9 +69,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
private void SetEntries(IEnumerable<CompatibilityEntry> entries)
|
||||
{
|
||||
#pragma warning disable MVVMTK0034
|
||||
_currentEntries = entries.ToList();
|
||||
#pragma warning restore MVVMTK0034
|
||||
OnPropertyChanged(nameof(CurrentEntries));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System.Linq;
|
||||
|
@ -8,10 +8,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
public partial class DlcSelectViewModel : BaseModel
|
||||
{
|
||||
[ObservableProperty] private DownloadableContentModel[] _dlcs;
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
[ObservableProperty] private DownloadableContentModel? _selectedDlc;
|
||||
#nullable disable
|
||||
|
||||
#nullable disable
|
||||
|
||||
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
|
||||
{
|
||||
_dlcs = appLibrary.FindDlcsFor(titleId)
|
||||
|
|
|
@ -6,8 +6,8 @@ using DynamicData;
|
|||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
|
@ -103,7 +103,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
// NOTE(jpr): this works around a bug where calling _views.Clear also clears SelectedDownloadableContents for
|
||||
// some reason. so we save the items here and add them back after
|
||||
DownloadableContentModel[] items = SelectedDownloadableContents.ToArray();
|
||||
|
||||
|
||||
Views.Clear();
|
||||
Views.AddRange(view);
|
||||
|
||||
|
@ -119,7 +119,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
if (arg is DownloadableContentModel content)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(_search) || content.FileName.ToLower().Contains(_search.ToLower()) || content.TitleIdStr.ToLower().Contains(_search.ToLower());
|
||||
return string.IsNullOrWhiteSpace(_search) || content.FileName.Contains(_search, System.StringComparison.OrdinalIgnoreCase) || content.TitleIdStr.Contains(_search, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -253,12 +253,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
return Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await ContentDialogHelper.ShowTextDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Checkmark);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool _isLeft;
|
||||
public bool IsLeft
|
||||
{
|
||||
|
@ -59,11 +59,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
}
|
||||
|
||||
public bool HasSides => IsLeft ^ IsRight;
|
||||
|
||||
|
||||
[ObservableProperty] private SvgImage _image;
|
||||
|
||||
|
||||
public InputViewModel ParentModel { get; }
|
||||
|
||||
|
||||
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config, StickVisualizer visualizer)
|
||||
{
|
||||
ParentModel = model;
|
||||
|
@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
else
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
|
@ -91,17 +91,17 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
}
|
||||
|
||||
public async void ShowMotionConfig()
|
||||
{
|
||||
{
|
||||
await MotionInputView.Show(this);
|
||||
ParentModel.IsModified = true;
|
||||
}
|
||||
|
||||
public async void ShowRumbleConfig()
|
||||
{
|
||||
{
|
||||
await RumbleInputView.Show(this);
|
||||
ParentModel.IsModified = true;
|
||||
}
|
||||
|
||||
|
||||
public async void ShowLedConfig()
|
||||
{
|
||||
await LedInputView.Show(this);
|
||||
|
|
|
@ -6,11 +6,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
|
@ -67,12 +67,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
private set
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
|
||||
_selectedGamepad = value;
|
||||
|
||||
if (ConfigViewModel is ControllerInputViewModel { Config.UseRainbowLed: true })
|
||||
Rainbow.Updated += (ref Color color) => _selectedGamepad.SetLed((uint)color.ToArgb());
|
||||
|
||||
|
||||
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
public bool IsModified
|
||||
{
|
||||
get => _isModified;
|
||||
set
|
||||
set
|
||||
{
|
||||
_isModified = value;
|
||||
OnPropertyChanged();
|
||||
|
@ -149,11 +149,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
set
|
||||
{
|
||||
if (IsModified)
|
||||
{
|
||||
{
|
||||
_playerIdChoose = value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IsModified = false;
|
||||
_playerId = value;
|
||||
_isChangeTrackingActive = false;
|
||||
|
@ -163,6 +163,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
_playerId = PlayerIndex.Player1;
|
||||
|
||||
}
|
||||
|
||||
_isLoaded = false;
|
||||
LoadConfiguration();
|
||||
LoadDevice();
|
||||
|
@ -216,11 +217,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
IsLeft = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
LoadInputDriver();
|
||||
LoadProfiles();
|
||||
}
|
||||
|
||||
|
||||
OnPropertyChanged();
|
||||
NotifyChanges();
|
||||
}
|
||||
|
@ -287,7 +288,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public InputConfig Config { get; set; }
|
||||
|
||||
public InputViewModel(UserControl owner) : this()
|
||||
|
@ -348,7 +348,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
{
|
||||
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void FindPairedDeviceInConfigFile()
|
||||
|
@ -356,7 +355,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
// This function allows you to output a message about the device configuration found in the file
|
||||
// NOTE: if the configuration is found, we display the message "Waiting for controller connection",
|
||||
// but only if the id gamepad belongs to the selected player
|
||||
|
||||
|
||||
NotificationIsVisible = Config != null && Devices.FirstOrDefault(d => d.Id == Config.Id).Id != Config.Id && Config.PlayerIndex == PlayerId;
|
||||
if (NotificationIsVisible)
|
||||
{
|
||||
|
@ -369,10 +368,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
NotificationText = $"{LocaleManager.Instance[LocaleKeys.ControllerSettingsWaitingConnectDevice].Format(Config.Name, Config.Id)}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void MarkAsChanged()
|
||||
{
|
||||
//If tracking is active, then allow changing the modifier
|
||||
|
@ -383,7 +380,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void UnlinkDevice()
|
||||
{
|
||||
// "Disabled" mode is available after unbinding the device
|
||||
|
@ -392,7 +388,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
IsModified = true;
|
||||
}
|
||||
|
||||
|
||||
public void LoadDevice()
|
||||
{
|
||||
if (Config == null || Config.Backend == InputBackendType.Invalid)
|
||||
|
@ -479,10 +474,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
LoadDevices();
|
||||
|
||||
IsModified = true;
|
||||
RevertChanges();
|
||||
RevertChanges();
|
||||
|
||||
_isChangeTrackingActive = true;// Enable configuration change tracking
|
||||
|
||||
|
||||
}
|
||||
|
||||
private string GetCurrentGamepadId()
|
||||
|
@ -557,6 +552,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
{
|
||||
return $"{GetShortGamepadName(gamepad.Name)} ({controllerNumber})";
|
||||
}
|
||||
|
||||
string GetUniqueGamepadName(IGamepad gamepad, ref int controllerNumber)
|
||||
{
|
||||
string name = GetGamepadName(gamepad, controllerNumber);
|
||||
|
@ -565,6 +561,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
controllerNumber++;
|
||||
name = GetGamepadName(gamepad, controllerNumber);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -790,7 +787,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
}
|
||||
|
||||
public void LoadProfileButton()
|
||||
{
|
||||
{
|
||||
LoadProfile();
|
||||
IsModified = true;
|
||||
}
|
||||
|
@ -824,6 +821,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
{
|
||||
ProfilesList.RemoveAt(index);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -860,58 +858,57 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
|
||||
public async void SaveProfile()
|
||||
{
|
||||
|
||||
if (Device == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfigViewModel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
|
||||
if (Device == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (validFileName)
|
||||
{
|
||||
string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
|
||||
if (ConfigViewModel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InputConfig config = null;
|
||||
if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
|
||||
|
||||
if (IsKeyboard)
|
||||
{
|
||||
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
|
||||
}
|
||||
else if (IsController)
|
||||
{
|
||||
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
|
||||
|
||||
config.ControllerType = Controllers[_controller].Type;
|
||||
if (validFileName)
|
||||
{
|
||||
string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
|
||||
|
||||
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
|
||||
InputConfig config = null;
|
||||
|
||||
await File.WriteAllTextAsync(path, jsonString);
|
||||
if (IsKeyboard)
|
||||
{
|
||||
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
|
||||
}
|
||||
else if (IsController)
|
||||
{
|
||||
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
|
||||
}
|
||||
|
||||
LoadProfiles();
|
||||
config.ControllerType = Controllers[_controller].Type;
|
||||
|
||||
ProfileChoose = ProfileName; // Show new profile
|
||||
}
|
||||
else
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
|
||||
}
|
||||
}
|
||||
|
||||
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
|
||||
|
||||
await File.WriteAllTextAsync(path, jsonString);
|
||||
|
||||
LoadProfiles();
|
||||
|
||||
ProfileChoose = ProfileName; // Show new profile
|
||||
}
|
||||
else
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async void RemoveProfile()
|
||||
|
@ -947,7 +944,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
{
|
||||
LoadConfiguration(); // configuration preload is required if the paired gamepad was disconnected but was changed to another gamepad
|
||||
Device = Devices.ToList().FindIndex(d => d.Id == RevertDeviceId);
|
||||
|
||||
|
||||
LoadDevice();
|
||||
LoadConfiguration();
|
||||
|
||||
|
@ -957,7 +954,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
|
||||
public void Save()
|
||||
{
|
||||
|
||||
|
||||
if (!IsModified)
|
||||
{
|
||||
return; //If the input settings were not touched, then do nothing
|
||||
|
@ -967,7 +964,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
|
||||
RevertDeviceId = Devices[Device].Id; // Remember selected device after saving
|
||||
|
||||
List <InputConfig> newConfig = [];
|
||||
List<InputConfig> newConfig = [];
|
||||
|
||||
newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using Avalonia.Media;
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Humanizer;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
@ -11,22 +11,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
public partial class LedInputViewModel : BaseModel
|
||||
{
|
||||
public required InputViewModel ParentModel { get; init; }
|
||||
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
{
|
||||
if (!EnableLedChanging) return;
|
||||
if (!EnableLedChanging)
|
||||
return;
|
||||
|
||||
if (TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(LedColor.ToUInt32());
|
||||
});
|
||||
|
||||
|
||||
[ObservableProperty] private bool _enableLedChanging;
|
||||
[ObservableProperty] private Color _ledColor;
|
||||
|
||||
public string RainbowSpeedText => RainbowSpeed.ToString(CultureInfo.CurrentCulture).Truncate(4, string.Empty);
|
||||
|
||||
|
||||
public float RainbowSpeed
|
||||
{
|
||||
get => ConfigurationState.Instance.Hid.RainbowSpeed;
|
||||
|
@ -37,11 +38,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
OnPropertyChanged(nameof(RainbowSpeedText));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
|
||||
private bool _turnOffLed;
|
||||
|
||||
|
||||
public bool TurnOffLed
|
||||
{
|
||||
get => _turnOffLed;
|
||||
|
@ -52,9 +53,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool _useRainbowLed;
|
||||
|
||||
|
||||
public bool UseRainbowLed
|
||||
{
|
||||
get => _useRainbowLed;
|
||||
|
|
|
@ -20,15 +20,15 @@ using Ryujinx.Ava.Common.Locale;
|
|||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Systems;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Models.Generic;
|
||||
using Ryujinx.Ava.UI.Renderer;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
|
@ -86,9 +86,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
[ObservableProperty] private Brush _progressBarForegroundColor;
|
||||
[ObservableProperty] private Brush _progressBarBackgroundColor;
|
||||
[ObservableProperty] private Brush _vSyncModeColor;
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
[ObservableProperty] private byte[]? _selectedIcon;
|
||||
#nullable disable
|
||||
#nullable disable
|
||||
[ObservableProperty] private int _statusBarProgressMaximum;
|
||||
[ObservableProperty] private int _statusBarProgressValue;
|
||||
[ObservableProperty] private string _statusBarProgressStatusText;
|
||||
|
@ -118,7 +118,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
if (Updater.CanUpdate(true))
|
||||
await Updater.BeginUpdateAsync(true);
|
||||
});
|
||||
|
||||
|
||||
private bool _showTotalTimePlayed;
|
||||
private bool _showLoadProgress;
|
||||
private bool _isGameRunning;
|
||||
|
@ -140,7 +140,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private int _customVSyncIntervalPercentageProxy;
|
||||
private ApplicationData _listSelectedApplication;
|
||||
private ApplicationData _gridSelectedApplication;
|
||||
|
||||
|
||||
// Key is Title ID
|
||||
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
|
||||
|
||||
|
@ -157,9 +157,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
.Sort(GetComparer())
|
||||
.OnItemAdded(_ => OnPropertyChanged(nameof(AppsObservableList)))
|
||||
.OnItemRemoved(_ => OnPropertyChanged(nameof(AppsObservableList)))
|
||||
#pragma warning disable MVVMTK0034 // Event to update is fired below
|
||||
.Bind(out _appsObservableList);
|
||||
#pragma warning restore MVVMTK0034
|
||||
|
||||
_rendererWaitEvent = new AutoResetEvent(false);
|
||||
|
||||
|
@ -205,7 +203,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
#if DEBUG
|
||||
topLevel.AttachDevTools(new KeyGesture(Avalonia.Input.Key.F12, KeyModifiers.Control));
|
||||
#endif
|
||||
|
||||
|
||||
Window.ApplicationLibrary.TotalTimePlayedRecalculated += TotalTimePlayed_Recalculated;
|
||||
}
|
||||
|
||||
|
@ -327,7 +325,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ApplicationData ListSelectedApplication
|
||||
{
|
||||
get => _listSelectedApplication;
|
||||
|
@ -335,13 +333,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
_listSelectedApplication = value;
|
||||
|
||||
#pragma warning disable MVVMTK0034
|
||||
if (_listSelectedApplication != null && _listAppContextMenu == null)
|
||||
if (_listSelectedApplication != null && ListAppContextMenu == null)
|
||||
|
||||
ListAppContextMenu = new ApplicationContextMenu();
|
||||
else if (_listSelectedApplication == null && _listAppContextMenu != null)
|
||||
else if (_listSelectedApplication == null && ListAppContextMenu != null)
|
||||
ListAppContextMenu = null!;
|
||||
#pragma warning restore MVVMTK0034
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
|
@ -354,13 +350,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
_gridSelectedApplication = value;
|
||||
|
||||
#pragma warning disable MVVMTK0034
|
||||
if (_gridSelectedApplication != null && _gridAppContextMenu == null)
|
||||
if (_gridSelectedApplication != null && GridAppContextMenu == null)
|
||||
GridAppContextMenu = new ApplicationContextMenu();
|
||||
else if (_gridSelectedApplication == null && _gridAppContextMenu != null)
|
||||
else if (_gridSelectedApplication == null && GridAppContextMenu != null)
|
||||
GridAppContextMenu = null!;
|
||||
#pragma warning restore MVVMTK0034
|
||||
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +374,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
ListSelectedApplication = value;
|
||||
GridSelectedApplication = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||
|
@ -395,7 +389,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
|
||||
|
||||
public bool ShowCustomVSyncIntervalPicker
|
||||
public bool ShowCustomVSyncIntervalPicker
|
||||
=> _isGameRunning && AppHost.Device.VSyncMode == VSyncMode.Custom;
|
||||
|
||||
public void UpdateVSyncIntervalPicker()
|
||||
|
@ -416,6 +410,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
AppHost.Device.CustomVSyncInterval = newInterval;
|
||||
AppHost.Device.UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
OnPropertyChanged((nameof(CustomVSyncInterval)));
|
||||
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
|
||||
}
|
||||
|
@ -447,6 +442,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
AppHost.Device.CustomVSyncInterval = value;
|
||||
AppHost.Device.UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
|
||||
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
|
||||
OnPropertyChanged();
|
||||
|
@ -579,7 +575,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public bool ShowNames
|
||||
{
|
||||
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
|
||||
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
|
||||
set
|
||||
{
|
||||
ConfigurationState.Instance.UI.ShowNames.Value = value;
|
||||
|
@ -762,7 +758,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
#region PrivateMethods
|
||||
|
||||
private static IComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
|
||||
private static SortExpressionComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
|
||||
ascending
|
||||
? SortExpressionComparer<ApplicationData>.Ascending(selector)
|
||||
: SortExpressionComparer<ApplicationData>.Descending(selector);
|
||||
|
@ -791,15 +787,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
private void RefreshGrid()
|
||||
{
|
||||
Applications.ToObservableChangeSet()
|
||||
var appsList = Applications.ToObservableChangeSet()
|
||||
.Filter(Filter)
|
||||
.Sort(GetComparer())
|
||||
#pragma warning disable MVVMTK0034
|
||||
.Bind(out _appsObservableList)
|
||||
#pragma warning restore MVVMTK0034
|
||||
.Bind(out var apps)
|
||||
.AsObservableList();
|
||||
|
||||
OnPropertyChanged(nameof(AppsObservableList));
|
||||
AppsObservableList = apps;
|
||||
}
|
||||
|
||||
private bool Filter(object arg)
|
||||
|
@ -874,10 +868,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, firmwareVersion.VersionString);
|
||||
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
dialogTitle,
|
||||
message,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
string.Empty,
|
||||
dialogTitle,
|
||||
message,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, message);
|
||||
|
@ -996,7 +990,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
waitingDialog.Close();
|
||||
|
||||
string message = ex.Message;
|
||||
if(ex is FormatException)
|
||||
if (ex is FormatException)
|
||||
{
|
||||
message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename);
|
||||
}
|
||||
|
@ -1054,6 +1048,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
CacheLoadStatus = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case ShaderCacheLoadingState shaderCacheState:
|
||||
CacheLoadStatus = $"{current} / {total}";
|
||||
|
@ -1074,6 +1069,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
CacheLoadStatus = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
|
||||
|
@ -1110,7 +1106,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
_rendererWaitEvent.WaitOne();
|
||||
|
||||
AppHost?.Start();
|
||||
|
||||
|
||||
AppHost?.DisposeContext();
|
||||
}
|
||||
|
||||
|
@ -1190,11 +1186,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
await ContentDialogHelper.ShowTextDialog(
|
||||
LocaleManager.Instance[numAdded > 0 || numRemoved > 0 ? LocaleKeys.RyujinxConfirm : LocaleKeys.RyujinxInfo],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Checkmark);
|
||||
});
|
||||
}
|
||||
|
@ -1388,7 +1384,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OpenHelper.OpenFolder(screenshotsDir);
|
||||
}
|
||||
|
||||
|
@ -1578,15 +1574,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public bool InitializeUserConfig(ApplicationData application)
|
||||
{
|
||||
// Code where conditions will be met before loading the user configuration (Global Config)
|
||||
BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value;
|
||||
// Code where conditions will be met before loading the user configuration (Global Config)
|
||||
string BackendThreadingInit = Program.BackendThreadingArg;
|
||||
|
||||
if (BackendThreadingInit is null)
|
||||
{
|
||||
BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
||||
}
|
||||
|
||||
BackendThreadingInit ??= ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
||||
|
||||
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
|
||||
string idGame = application.IdBaseString;
|
||||
if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat))
|
||||
|
@ -1599,13 +1591,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
|
||||
{
|
||||
|
||||
List<string> Arguments = new List<string>
|
||||
List<string> Arguments = new()
|
||||
{
|
||||
"--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading
|
||||
};
|
||||
|
||||
Rebooter.RebootAppWithGame(application.Path, Arguments);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1635,7 +1627,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
#if RELEASE
|
||||
await PerformanceCheck();
|
||||
#endif
|
||||
|
||||
|
||||
Logger.RestartTime();
|
||||
|
||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id);
|
||||
|
@ -1680,7 +1672,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
||||
gameThread.Start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void SwitchToRenderer(bool startFullscreen) =>
|
||||
|
@ -1801,7 +1793,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void ToggleFullscreen()
|
||||
{
|
||||
if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs)
|
||||
|
@ -1963,7 +1954,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
#endregion
|
||||
|
||||
#region Context Menu commands
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> RunApplication { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => viewModel.LoadApplication(viewModel.SelectedApplication));
|
||||
|
@ -1982,7 +1973,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
viewModel.RefreshView();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
public static RelayCommand<MainWindowViewModel> CreateApplicationShortcut { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => ShortcutHelper.CreateAppShortcut(
|
||||
|
@ -1991,7 +1982,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
viewModel.SelectedApplication.IdString,
|
||||
viewModel.SelectedApplication.Icon
|
||||
));
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> EditGameConfiguration { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
async viewModel =>
|
||||
|
@ -2058,7 +2049,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
viewModel.SelectedApplication.Path
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> OpenModManager { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => ModManagerView.Show(
|
||||
|
@ -2086,11 +2077,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
OpenHelper.OpenFolder(titleModsPath);
|
||||
});
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> TrimXci { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path));
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> PurgePtcCache { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
async viewModel =>
|
||||
|
@ -2280,7 +2271,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
OpenHelper.OpenFolder(shaderCacheDir);
|
||||
});
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> ExtractApplicationExeFs { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
async viewModel =>
|
||||
|
@ -2350,7 +2341,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
png.SaveTo(fileStream);
|
||||
});
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||
using DynamicData;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
|
@ -131,12 +131,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
.Filter(Filter)
|
||||
.Bind(out ReadOnlyObservableCollection<ModModel> view).AsObservableList();
|
||||
|
||||
#pragma warning disable MVVMTK0034 // Event to update is fired below
|
||||
_views.Clear();
|
||||
_views.AddRange(view);
|
||||
#pragma warning restore MVVMTK0034
|
||||
Views.Clear();
|
||||
Views.AddRange(view);
|
||||
|
||||
SelectedMods = new(Views.Where(x => x.Enabled));
|
||||
SelectedMods = [.. Views.Where(x => x.Enabled)];
|
||||
|
||||
OnPropertyChanged(nameof(ModCount));
|
||||
OnPropertyChanged(nameof(Views));
|
||||
|
@ -147,7 +145,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
if (arg is ModModel content)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(_search) || content.Name.ToLower().Contains(_search.ToLower());
|
||||
return string.IsNullOrWhiteSpace(_search) || content.Name.Contains(_search, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -215,6 +213,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
Mods.Remove(model);
|
||||
OnPropertyChanged(nameof(ModCount));
|
||||
}
|
||||
|
||||
Sort();
|
||||
}
|
||||
|
||||
|
@ -312,7 +311,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public void EnableAll()
|
||||
{
|
||||
SelectedMods = new(Mods);
|
||||
SelectedMods = [.. Mods];
|
||||
}
|
||||
|
||||
public void DisableAll()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
|
||||
|
@ -8,8 +8,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
private readonly SettingsViewModel _baseViewModel;
|
||||
|
||||
public SettingsHacksViewModel() {}
|
||||
|
||||
public SettingsHacksViewModel() { }
|
||||
|
||||
public SettingsHacksViewModel(SettingsViewModel settingsVm)
|
||||
{
|
||||
_baseViewModel = settingsVm;
|
||||
|
@ -17,20 +17,20 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
|
||||
[ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted;
|
||||
|
||||
|
||||
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
|
||||
{
|
||||
sb.AppendLine(
|
||||
"This hack applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
|
||||
.AppendLine();
|
||||
|
||||
|
||||
sb.AppendLine("From the issue on GitHub:").AppendLine();
|
||||
sb.Append(
|
||||
"When clicking very fast from game main menu to 2nd submenu, " +
|
||||
"there is a low chance that the game will softlock, " +
|
||||
"the submenu won't show up, while background music is still there.");
|
||||
});
|
||||
|
||||
|
||||
public static string NifmDisableIsAnyInternetRequestAcceptedTooltip { get; } = Lambda.String(sb =>
|
||||
{
|
||||
sb.AppendLine(
|
||||
|
|
|
@ -9,12 +9,12 @@ using Ryujinx.Audio.Backends.OpenAL;
|
|||
using Ryujinx.Audio.Backends.SDL2;
|
||||
using Ryujinx.Audio.Backends.SoundIo;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.Systems.Configuration.System;
|
||||
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
|
@ -72,10 +72,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
public SettingsHacksViewModel DirtyHacks { get; }
|
||||
|
||||
private readonly bool _isGameRunning;
|
||||
private Bitmap _gameIcon;
|
||||
private string _gameTitle;
|
||||
private string _gamePath;
|
||||
private string _gameId;
|
||||
private readonly Bitmap _gameIcon;
|
||||
private readonly string _gameTitle;
|
||||
private readonly string _gamePath;
|
||||
private readonly string _gameId;
|
||||
public bool IsGameRunning => _isGameRunning;
|
||||
public Bitmap GameIcon => _gameIcon;
|
||||
public string GamePath => _gamePath;
|
||||
|
@ -142,9 +142,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||
|
||||
|
||||
public int FocusLostActionType { get; set; }
|
||||
|
||||
|
||||
public VSyncMode VSyncMode
|
||||
{
|
||||
get => _vSyncMode;
|
||||
|
@ -188,6 +188,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
VSyncMode = VSyncMode.Custom;
|
||||
}
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
@ -201,15 +202,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
int newPercent = (int)((value / 60f) * 100);
|
||||
_customVSyncIntervalPercentageProxy = newPercent;
|
||||
OnPropertiesChanged(
|
||||
nameof(CustomVSyncIntervalPercentageProxy),
|
||||
nameof(CustomVSyncIntervalPercentageProxy),
|
||||
nameof(CustomVSyncIntervalPercentageText));
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
public bool EnablePptc { get; set; }
|
||||
public bool EnableLowPowerPptc { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public long TurboMultiplier
|
||||
{
|
||||
get => _turboModeMultiplier;
|
||||
|
@ -218,13 +219,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
if (_turboModeMultiplier != value)
|
||||
{
|
||||
_turboModeMultiplier = value;
|
||||
|
||||
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged((nameof(TurboMultiplierPercentageText)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string TurboMultiplierPercentageText => $"{TurboMultiplier}%";
|
||||
|
||||
public bool EnableInternetAccess { get; set; }
|
||||
|
@ -345,7 +346,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public AvaloniaList<string> NetworkInterfaceList
|
||||
{
|
||||
get => new(_networkInterfaces.Keys);
|
||||
get => [.. _networkInterfaces.Keys];
|
||||
}
|
||||
|
||||
public HotkeyConfig KeyboardHotkey { get; set; }
|
||||
|
@ -374,39 +375,37 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
|
||||
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
Task.Run(LoadTimeZones);
|
||||
|
||||
|
||||
DirtyHacks = new SettingsHacksViewModel(this);
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel(
|
||||
VirtualFileSystem virtualFileSystem,
|
||||
VirtualFileSystem virtualFileSystem,
|
||||
ContentManager contentManager,
|
||||
bool gameRunning,
|
||||
string gamePath,
|
||||
string gameName,
|
||||
string gameId,
|
||||
byte[] gameIconData,
|
||||
string gameName,
|
||||
string gameId,
|
||||
byte[] gameIconData,
|
||||
bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
|
||||
|
||||
if (gameIconData != null && gameIconData.Length > 0)
|
||||
{
|
||||
using (var ms = new MemoryStream(gameIconData))
|
||||
{
|
||||
_gameIcon = new Bitmap(ms);
|
||||
}
|
||||
using var ms = new MemoryStream(gameIconData);
|
||||
_gameIcon = new Bitmap(ms);
|
||||
}
|
||||
|
||||
_isGameRunning = gameRunning;
|
||||
_gamePath = gamePath;
|
||||
_gameTitle = gameName;
|
||||
_gameTitle = gameName;
|
||||
_gameId = gameId;
|
||||
|
||||
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
|
||||
|
@ -414,7 +413,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
string gameDir = Program.GetDirGameUserConfig(gameId, false, true);
|
||||
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
||||
{
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||
}
|
||||
|
||||
LoadCurrentConfiguration(); // Needed to load custom configuration
|
||||
|
@ -443,8 +442,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
Task.Run(LoadAvailableGpus);
|
||||
|
||||
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
||||
LoadCurrentConfiguration();
|
||||
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
||||
LoadCurrentConfiguration();
|
||||
|
||||
DirtyHacks = new SettingsHacksViewModel(this);
|
||||
}
|
||||
|
@ -811,7 +810,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public void DeleteConfigGame()
|
||||
{
|
||||
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
|
||||
string gameDir = Program.GetDirGameUserConfig(GameId, false, false);
|
||||
|
||||
if (File.Exists(gameDir))
|
||||
{
|
||||
|
@ -839,8 +838,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public AsyncRelayCommand ResetButton => Commands.Create(async () =>
|
||||
{
|
||||
if (!WantsToReset) return;
|
||||
|
||||
if (!WantsToReset)
|
||||
return;
|
||||
|
||||
CloseWindow?.Invoke();
|
||||
ConfigurationState.Instance.LoadDefault();
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
|
|
|
@ -5,8 +5,8 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -178,17 +178,17 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
ApplicationLibrary.SaveTitleUpdatesForGame(ApplicationData, updates);
|
||||
}
|
||||
|
||||
private Task ShowNewUpdatesAddedDialog(int numAdded)
|
||||
private Task<UserResult> ShowNewUpdatesAddedDialog(int numAdded)
|
||||
{
|
||||
string msg = string.Format(LocaleManager.Instance[LocaleKeys.UpdateWindowUpdateAddedMessage], numAdded);
|
||||
return Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
return Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
await ContentDialogHelper.ShowTextDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Checkmark
|
||||
));
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private static byte[] DecompressYaz0(Stream stream)
|
||||
private static byte[] DecompressYaz0(MemoryStream stream)
|
||||
{
|
||||
using BinaryReader reader = new(stream);
|
||||
|
||||
|
|
|
@ -43,10 +43,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
.Sort(GetComparer())
|
||||
.Bind(out ReadOnlyObservableCollection<SaveModel> view).AsObservableList();
|
||||
|
||||
#pragma warning disable MVVMTK0034
|
||||
_views.Clear();
|
||||
_views.AddRange(view);
|
||||
#pragma warning restore MVVMTK0034
|
||||
Views.Clear();
|
||||
Views.AddRange(view);
|
||||
OnPropertyChanged(nameof(Views));
|
||||
}
|
||||
|
||||
|
@ -54,13 +52,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
if (arg is SaveModel save)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
|
||||
return string.IsNullOrWhiteSpace(Search) || save.Title.Contains(Search, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private IComparer<SaveModel> GetComparer()
|
||||
private SortExpressionComparer<SaveModel> GetComparer()
|
||||
{
|
||||
return SortIndex switch
|
||||
{
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
using Avalonia.Collections;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData;
|
||||
using Gommon;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
@ -36,10 +36,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
|
||||
private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary;
|
||||
private Optional<XCITrimmerFileModel> _processingApplication = null;
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
|
||||
private readonly AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
|
||||
private MainWindowViewModel _mainWindowViewModel;
|
||||
private readonly AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
|
||||
private readonly MainWindowViewModel _mainWindowViewModel;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private string _search;
|
||||
private ProcessingMode _processingMode;
|
||||
|
@ -93,12 +93,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private void SortingChanged()
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(IsSortedByName),
|
||||
nameof(IsSortedBySaved),
|
||||
nameof(SortingAscending),
|
||||
nameof(SortingField),
|
||||
nameof(IsSortedByName),
|
||||
nameof(IsSortedBySaved),
|
||||
nameof(SortingAscending),
|
||||
nameof(SortingField),
|
||||
nameof(SortingFieldName));
|
||||
|
||||
|
||||
SortAndFilter();
|
||||
}
|
||||
|
||||
|
@ -110,13 +110,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private void ApplicationsChanged()
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(AllXCIFiles),
|
||||
nameof(Status),
|
||||
nameof(PotentialSavings),
|
||||
nameof(ActualSavings),
|
||||
nameof(CanTrim),
|
||||
nameof(AllXCIFiles),
|
||||
nameof(Status),
|
||||
nameof(PotentialSavings),
|
||||
nameof(ActualSavings),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim));
|
||||
|
||||
|
||||
DisplayedChanged();
|
||||
SortAndFilter();
|
||||
}
|
||||
|
@ -124,9 +124,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private void SelectionChanged(bool displayedChanged = true)
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim),
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim),
|
||||
nameof(SelectedXCIFiles));
|
||||
|
||||
if (displayedChanged)
|
||||
|
@ -136,10 +136,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
private void ProcessingChanged()
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(Processing),
|
||||
nameof(Cancel),
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(Processing),
|
||||
nameof(Cancel),
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim));
|
||||
}
|
||||
|
||||
|
@ -245,8 +245,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
if (arg is XCITrimmerFileModel content)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(_search)
|
||||
|| content.Name.ToLower().Contains(_search.ToLower())
|
||||
|| content.Path.ToLower().Contains(_search.ToLower());
|
||||
|| content.Name.Contains(_search, System.StringComparison.OrdinalIgnoreCase)
|
||||
|| content.Path.Contains(_search, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -254,7 +254,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
|
||||
{
|
||||
private XciTrimmerViewModel _viewModel;
|
||||
private readonly XciTrimmerViewModel _viewModel;
|
||||
|
||||
public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel)
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
|||
public static async Task Show()
|
||||
{
|
||||
using AboutWindowViewModel viewModel = new();
|
||||
|
||||
|
||||
ContentDialog contentDialog = new()
|
||||
{
|
||||
PrimaryButtonText = string.Empty,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -30,12 +30,12 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
|||
|
||||
await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles(160, HorizontalAlignment.Center));
|
||||
}
|
||||
|
||||
|
||||
public ApplicationDataView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not Button { Content: TextBlock playabilityLabel })
|
||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
|||
|
||||
if (RyujinxApp.AppLifetime.Windows.TryGetFirst(x => x is ContentDialogOverlayWindow, out Window window))
|
||||
window.Close(ContentDialogResult.None);
|
||||
|
||||
|
||||
await CompatibilityListWindow.Show((string)playabilityLabel.Tag);
|
||||
}
|
||||
|
||||
|
@ -54,15 +54,15 @@ namespace Ryujinx.Ava.UI.Views.Dialog
|
|||
|
||||
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
||||
return;
|
||||
|
||||
|
||||
ApplicationData appData = RyujinxApp.MainWindow.ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
||||
if (appData is null)
|
||||
return;
|
||||
|
||||
|
||||
await clipboard.SetTextAsync(appData.IdString);
|
||||
|
||||
|
||||
NotificationHelper.ShowInformation(
|
||||
"Copied Title ID",
|
||||
"Copied Title ID",
|
||||
$"{appData.Name} ({appData.IdString})");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using FluentAvalonia.UI.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Dialog
|
||||
|
|
|
@ -4,9 +4,9 @@ using Avalonia.Styling;
|
|||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Helper;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ using Avalonia.Interactivity;
|
|||
using Avalonia.Styling;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Common.Helper;
|
||||
using System.Threading.Tasks;
|
||||
using Button = Avalonia.Controls.Button;
|
||||
|
|
|
@ -4,9 +4,9 @@ using Avalonia.Styling;
|
|||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Helper;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
};
|
||||
|
||||
if (!float.IsNaN(_changeSlider) && _changeSlider != (float)check.Value)
|
||||
{
|
||||
{
|
||||
FlagInputConfigChanged();
|
||||
|
||||
_changeSlider = (float)check.Value;
|
||||
|
@ -83,7 +83,6 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton button)
|
||||
|
@ -104,7 +103,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
this.Focus(NavigationMethod.Pointer);
|
||||
|
||||
PointerPressed += MouseClick;
|
||||
|
||||
|
||||
ControllerInputViewModel viewModel = (DataContext as ControllerInputViewModel);
|
||||
|
||||
IKeyboard keyboard =
|
||||
|
@ -225,8 +224,8 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
PointerPressed -= MouseClick;
|
||||
}
|
||||
|
||||
private IButtonAssigner CreateButtonAssigner(bool forStick) =>
|
||||
new GamepadButtonAssigner(
|
||||
private GamepadButtonAssigner CreateButtonAssigner(bool forStick) =>
|
||||
new(
|
||||
ViewModel.ParentModel.SelectedGamepad,
|
||||
(ViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold,
|
||||
forStick);
|
||||
|
@ -234,11 +233,12 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
|
||||
|
||||
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
|
||||
{
|
||||
gamepad?.ClearLed();
|
||||
}
|
||||
|
||||
_currentAssigner?.Cancel();
|
||||
_currentAssigner = null;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
LocaleManager.Instance[LocaleKeys.Cancel],
|
||||
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
|
||||
|
||||
|
||||
if (result == UserResult.Yes)
|
||||
{
|
||||
ViewModel.Save();
|
||||
|
@ -61,14 +60,14 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
ViewModel.IsModified = true;
|
||||
ViewModel.PlayerId = ((PlayerModel)e.AddedItems[0])!.Id;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ViewModel.IsModified = false;
|
||||
ViewModel.PlayerId = ViewModel.PlayerIdChoose;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
|
|
|
@ -9,8 +9,8 @@ using Ryujinx.Ava.UI.Helpers;
|
|||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Button = Ryujinx.Input.Button;
|
||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
|
@ -45,9 +45,9 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
|
||||
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not ToggleButton button)
|
||||
if (sender is not ToggleButton button)
|
||||
return;
|
||||
|
||||
|
||||
if (button.IsChecked is true)
|
||||
{
|
||||
if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
|
||||
|
@ -65,7 +65,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
|
||||
IKeyboard keyboard =
|
||||
(IKeyboard)ViewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IButtonAssigner assigner =
|
||||
IButtonAssigner assigner =
|
||||
new KeyboardKeyAssigner((IKeyboard)ViewModel.ParentModel.SelectedGamepad);
|
||||
|
||||
_currentAssigner.ButtonAssigned += (_, be) =>
|
||||
|
@ -205,7 +205,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
|
||||
if (_currentAssigner != null)
|
||||
{
|
||||
Dictionary<string, Action> buttonActions = new Dictionary<string, Action>
|
||||
Dictionary<string, Action> buttonActions = new()
|
||||
{
|
||||
{ "ButtonZl", () => ViewModel.Config.ButtonZl = Key.Unbound },
|
||||
{ "ButtonL", () => ViewModel.Config.ButtonL = Key.Unbound },
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Avalonia;
|
||||
using Avalonia;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
|
@ -20,27 +20,32 @@ namespace Ryujinx.UI.Views.Input
|
|||
LedColor = viewModel.Config.LedColor,
|
||||
UseRainbowLed = viewModel.Config.UseRainbowLed,
|
||||
};
|
||||
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
|
||||
{
|
||||
if (!args.NewColor.HasValue) return;
|
||||
if (!ViewModel.EnableLedChanging) return;
|
||||
if (ViewModel.TurnOffLed) return;
|
||||
|
||||
if (!args.NewColor.HasValue)
|
||||
return;
|
||||
if (!ViewModel.EnableLedChanging)
|
||||
return;
|
||||
if (ViewModel.TurnOffLed)
|
||||
return;
|
||||
|
||||
ViewModel.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (!ViewModel.EnableLedChanging) return;
|
||||
if (ViewModel.TurnOffLed) return;
|
||||
|
||||
if (!ViewModel.EnableLedChanging)
|
||||
return;
|
||||
if (ViewModel.TurnOffLed)
|
||||
return;
|
||||
|
||||
ViewModel.ParentModel.SelectedGamepad.SetLed(ViewModel.LedColor.ToUInt32());
|
||||
}
|
||||
|
||||
|
||||
public static async Task Show(ControllerInputViewModel viewModel)
|
||||
{
|
||||
LedInputView content = new(viewModel);
|
||||
|
|
|
@ -6,14 +6,14 @@ using Gommon;
|
|||
using LibHac.Common;
|
||||
using LibHac.Ns;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Utilities;
|
||||
|
@ -52,13 +52,13 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
|
||||
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;
|
||||
|
||||
FaqMenuItem.Command =
|
||||
SetupGuideMenuItem.Command =
|
||||
FaqMenuItem.Command =
|
||||
SetupGuideMenuItem.Command =
|
||||
LdnGuideMenuItem.Command = Commands.Create<string>(OpenHelper.OpenUrl);
|
||||
|
||||
WindowSize720PMenuItem.Command =
|
||||
WindowSize1080PMenuItem.Command =
|
||||
WindowSize1440PMenuItem.Command =
|
||||
|
||||
WindowSize720PMenuItem.Command =
|
||||
WindowSize1080PMenuItem.Command =
|
||||
WindowSize1440PMenuItem.Command =
|
||||
WindowSize2160PMenuItem.Command = Commands.Create<string>(ChangeWindowSize);
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
{
|
||||
string tr = locales.Locales[index].Translations[language];
|
||||
languageName = string.IsNullOrEmpty(tr)
|
||||
? language
|
||||
? language
|
||||
: tr;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
await StyleableAppWindow.ShowAsync(Window.SettingsWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
bool customConfigExists = File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString));
|
||||
|
||||
if (!ViewModel.IsGameRunning || !customConfigExists)
|
||||
|
@ -157,12 +157,12 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
}
|
||||
|
||||
public AppletMetadata MiiApplet => new(ViewModel.ContentManager, "miiEdit", 0x0100000000001009);
|
||||
|
||||
|
||||
public async Task OpenMiiApplet()
|
||||
{
|
||||
if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct<ApplicationControlProperty> nacpData))
|
||||
if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct<ApplicationControlProperty> nacpData))
|
||||
return;
|
||||
|
||||
|
||||
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
private void ChangeWindowSize(string resolution)
|
||||
{
|
||||
(int resolutionWidth, int resolutionHeight) = resolution.Split(' ', 2)
|
||||
.Into(parts =>
|
||||
.Into(parts =>
|
||||
(int.Parse(parts[0]), int.Parse(parts[1]))
|
||||
);
|
||||
|
||||
|
@ -237,6 +237,6 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
}
|
||||
|
||||
public void CloseWindow() => Window.Close();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ using Avalonia.Input;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Misc
|
||||
|
|
|
@ -2,10 +2,10 @@ using Avalonia.Controls;
|
|||
using Avalonia.Input;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Misc
|
|||
if (sender is ListBox { SelectedItem: ApplicationData selected })
|
||||
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
|
||||
}
|
||||
|
||||
|
||||
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not Button { Content: TextBlock playabilityLabel })
|
||||
|
@ -46,15 +46,15 @@ namespace Ryujinx.Ava.UI.Views.Misc
|
|||
|
||||
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
||||
return;
|
||||
|
||||
|
||||
ApplicationData appData = ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
||||
if (appData is null)
|
||||
return;
|
||||
|
||||
|
||||
await clipboard.SetTextAsync(appData.IdString);
|
||||
|
||||
|
||||
NotificationHelper.ShowInformation(
|
||||
"Copied Title ID",
|
||||
"Copied Title ID",
|
||||
$"{appData.Name} ({appData.IdString})");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers;
|
|||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Button = Ryujinx.Input.Button;
|
||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
public partial class SettingsHotkeysView : RyujinxControl<SettingsViewModel>
|
||||
{
|
||||
private ButtonKeyAssigner _currentAssigner;
|
||||
private readonly IGamepadDriver _avaloniaKeyboardDriver;
|
||||
private readonly AvaloniaKeyboardDriver _avaloniaKeyboardDriver;
|
||||
|
||||
public SettingsHotkeysView()
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
{
|
||||
DeleteBind();
|
||||
}
|
||||
|
||||
|
||||
_currentAssigner?.Cancel(shouldUnbind);
|
||||
|
||||
PointerPressed -= MouseClick;
|
||||
|
@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
|
||||
if (_currentAssigner != null)
|
||||
{
|
||||
Dictionary<string, Action> buttonActions = new Dictionary<string, Action>
|
||||
Dictionary<string, Action> buttonActions = new()
|
||||
{
|
||||
{ "ToggleVSyncMode", () => viewModel.KeyboardHotkey.ToggleVSyncMode = Key.Unbound },
|
||||
{ "Screenshot", () => viewModel.KeyboardHotkey.Screenshot = Key.Unbound },
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path))
|
||||
{
|
||||
directories.Add(path);
|
||||
|
||||
|
||||
addDirBox.Clear();
|
||||
|
||||
ViewModel.GameListNeedsRefresh = true;
|
||||
|
@ -44,7 +44,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
if (folder.HasValue)
|
||||
{
|
||||
directories.Add(folder.Value.Path.LocalPath);
|
||||
|
||||
|
||||
ViewModel.GameListNeedsRefresh = true;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue