diff --git a/src/Ryujinx.Common/Configuration/DirtyHack.cs b/src/Ryujinx.Common/Configuration/DirtyHack.cs index 3959c0a99..71ac88f56 100644 --- a/src/Ryujinx.Common/Configuration/DirtyHack.cs +++ b/src/Ryujinx.Common/Configuration/DirtyHack.cs @@ -9,7 +9,8 @@ namespace Ryujinx.Common.Configuration public enum DirtyHack : byte { Xc2MenuSoftlockFix = 1, - ShaderTranslationDelay = 2 + // ShaderTranslationDelay = 2 + NifmServiceDisableIsAnyInternetRequestAccepted = 3 } public readonly struct EnabledDirtyHack(DirtyHack hack, int value) diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs index 82be1572f..76a8a7126 100644 --- a/src/Ryujinx.Common/TitleIDs.cs +++ b/src/Ryujinx.Common/TitleIDs.cs @@ -1,7 +1,4 @@ using Gommon; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Helper; -using System; using System.Linq; namespace Ryujinx.Common diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs index 96e71cd07..d669caba1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs @@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm // CreateGeneralServiceOld() -> object public ResultCode CreateGeneralServiceOld(ServiceCtx context) { - MakeObject(context, new IGeneralService()); + MakeObject(context, new IGeneralService(context)); return ResultCode.Success; } @@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm // CreateGeneralService(u64, pid) -> object public ResultCode CreateGeneralService(ServiceCtx context) { - MakeObject(context, new IGeneralService()); + MakeObject(context, new IGeneralService(context)); return ResultCode.Success; } diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs index a5a822db3..dd4efce6e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs @@ -1,4 +1,5 @@ using Ryujinx.Common; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService; @@ -17,12 +18,12 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService private UnicastIPAddressInformation _targetAddressInfoCache = null; private string _cacheChosenInterface = null; - public IGeneralService() + public IGeneralService(ServiceCtx context) { _generalServiceDetail = new GeneralServiceDetail { ClientId = GeneralServiceManager.Count, - IsAnyInternetRequestAccepted = true, // NOTE: Why not accept any internet request? + IsAnyInternetRequestAccepted = !context.Device.DirtyHacks.IsEnabled(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted), // NOTE: Why not accept any internet request? }; NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs index b442cf802..660803714 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs @@ -1,6 +1,5 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy; -using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index e64cae4d5..28e0af060 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -3823,28 +3823,53 @@ } }, { - "ID": "SettingsTabGeneralShowTitleBar", + "ID": "SettingsTabGeneralShowOldUI", "Translations": { "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Show Title Bar (Requires restart)", - "es_ES": "Mostrar Barra de Título (Requiere reinicio)", - "fr_FR": "Afficher Barre de Titre (Nécessite redémarrage)", + "en_US": "Show Original UI Style (Requires restart)", + "es_ES": "", + "fr_FR": "", "he_IL": "", - "it_IT": "Mostra barra del titolo (Richiede il riavvio)", + "it_IT": "", "ja_JP": "", - "ko_KR": "제목 표시줄 표시(다시 시작해야 함)", - "no_NO": "Vis tittellinje (krever omstart)", + "ko_KR": "", + "no_NO": "Vis original UI-stil (krever omstart)", "pl_PL": "", - "pt_BR": "Mostrar Barra de Título (Requer reinicialização)", - "ru_RU": "Показать строку заголовка (требуется перезапуск)", - "sv_SE": "Visa titelrad (kräver omstart)", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", "th_TH": "", "tr_TR": "", - "uk_UA": "Показувати рядок заголовка (Потрібен перезапуск)", - "zh_CN": "显示标题栏 (需要重启)", - "zh_TW": "顯示「標題列」 (需要重新開啟Ryujinx)" + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "SettingsTabGeneralShowOldUIToolTip", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Show the older Avalonia Ryujinx UI reminiscent of Ryujinx 1.1.1403. This is enabled by default on platforms that are not Windows.\nThe classic-style title bar is back and major window layout reworkings are reversed; such as the settings navigation placement above this tooltip.", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "Vis det eldre Avalonia Ryujinx-grensesnittet som minner om Ryujinx 1.1.1403. Dette er aktivert som standard på plattformer som ikke er Windows.\nTittellinjen i klassisk stil er tilbake, og store omarbeidinger av vindusoppsettet er reversert, for eksempel plasseringen av innstillingsnavigasjonen over dette verktøytipset.", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" } }, { diff --git a/src/Ryujinx/Common/LocaleManager.cs b/src/Ryujinx/Common/LocaleManager.cs index 9aa82a4a5..d116fe709 100644 --- a/src/Ryujinx/Common/LocaleManager.cs +++ b/src/Ryujinx/Common/LocaleManager.cs @@ -38,8 +38,8 @@ namespace Ryujinx.Ava.Common.Locale { LocaleKeys.RyujinxConfirm, [RyujinxApp.FullAppName] }, { LocaleKeys.RyujinxUpdater, [RyujinxApp.FullAppName] }, { LocaleKeys.RyujinxRebooter, [RyujinxApp.FullAppName] }, - { LocaleKeys.CompatibilityListSearchBoxWatermarkWithCount, [CompatibilityCsv.Entries.Length] }, - { LocaleKeys.CompatibilityListTitle, [CompatibilityCsv.Entries.Length] } + { LocaleKeys.CompatibilityListSearchBoxWatermarkWithCount, [CompatibilityDatabase.Entries.Length] }, + { LocaleKeys.CompatibilityListTitle, [CompatibilityDatabase.Entries.Length] } }); Load(); diff --git a/src/Ryujinx/Common/Markup/MarkupExtensions.cs b/src/Ryujinx/Common/Markup/MarkupExtensions.cs index 9e8ff00ef..2c8290847 100644 --- a/src/Ryujinx/Common/Markup/MarkupExtensions.cs +++ b/src/Ryujinx/Common/Markup/MarkupExtensions.cs @@ -24,4 +24,17 @@ namespace Ryujinx.Ava.Common.Markup protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension) => bindingExtension.Source = LocaleManager.Instance; } + + internal class WindowTitleExtension(LocaleKeys key, bool includeVersion) : BasicMarkupExtension + { + 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) + => bindingExtension.Source = LocaleManager.Instance; + } } diff --git a/src/Ryujinx/Common/XCITrimmerLog.cs b/src/Ryujinx/Common/XCITrimmerLog.cs index b661d918d..751831a66 100644 --- a/src/Ryujinx/Common/XCITrimmerLog.cs +++ b/src/Ryujinx/Common/XCITrimmerLog.cs @@ -26,9 +26,9 @@ namespace Ryujinx.Ava.Common internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog { - private readonly XCITrimmerViewModel _viewModel; + private readonly XciTrimmerViewModel _viewModel; - public TrimmerWindow(XCITrimmerViewModel viewModel) + public TrimmerWindow(XciTrimmerViewModel viewModel) { _viewModel = viewModel; } diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs index 7ff0a5259..751a86571 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs @@ -2,6 +2,7 @@ using DiscordRPC; using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Ava; +using Ryujinx.Ava.Systems; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Hid; @@ -11,7 +12,6 @@ using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.GAL.Multithreading; using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.Vulkan; using Ryujinx.HLE; diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index c24725b5c..016cc348a 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -5,6 +5,7 @@ using Gommon; using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.MaterialDesign; +using Ryujinx.Ava.Systems; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index 698b392ee..1f9642466 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -91,10 +91,12 @@ Always THIRDPARTY.md + False Always LICENSE.txt + False diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs similarity index 99% rename from src/Ryujinx/AppHost.cs rename to src/Ryujinx/Systems/AppHost.cs index b50eb6912..455afaf45 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -6,7 +6,6 @@ using Avalonia.Threading; using DiscordRPC; using LibHac.Common; using LibHac.Ns; -using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL2; @@ -35,11 +34,9 @@ using Ryujinx.Graphics.GAL.Multithreading; using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.Vulkan; -using Ryujinx.HLE; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; -using Ryujinx.HLE.HOS.SystemState; using Ryujinx.Input; using Ryujinx.Input.HLE; using SkiaSharp; @@ -62,7 +59,7 @@ using Size = Avalonia.Size; using Switch = Ryujinx.HLE.Switch; using VSyncMode = Ryujinx.Common.Configuration.VSyncMode; -namespace Ryujinx.Ava +namespace Ryujinx.Ava.Systems { internal class AppHost { @@ -470,7 +467,7 @@ namespace Ryujinx.Ava Dispatcher.UIThread.InvokeAsync(() => { - _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar); + _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI); }); _viewModel.SetUiProgressHandlers(Device); @@ -872,7 +869,7 @@ namespace Ryujinx.Ava Device?.System.TogglePauseEmulation(false); _viewModel.IsPaused = false; - _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar); + _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI); Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed"); } @@ -881,7 +878,7 @@ namespace Ryujinx.Ava Device?.System.TogglePauseEmulation(true); _viewModel.IsPaused = true; - _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar, LocaleManager.Instance[LocaleKeys.Paused]); + _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]); Logger.Info?.Print(LogClass.Emulation, "Emulation was paused"); } diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs index e04ea454a..0819b86b8 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs @@ -36,7 +36,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary { _id = value; - Compatibility = CompatibilityCsv.Find(value); + Compatibility = CompatibilityDatabase.Find(value); RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec) ? gameSpec : default(Optional); diff --git a/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs b/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs index 6c80c1924..21d24ff2d 100644 --- a/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs +++ b/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace Ryujinx.Ava.Systems.AppLibrary { diff --git a/src/Ryujinx/Systems/CompatibilityCsv.cs b/src/Ryujinx/Systems/CompatibilityDatabase.cs similarity index 82% rename from src/Ryujinx/Systems/CompatibilityCsv.cs rename to src/Ryujinx/Systems/CompatibilityDatabase.cs index 9bab87d9f..bfc7ba903 100644 --- a/src/Ryujinx/Systems/CompatibilityCsv.cs +++ b/src/Ryujinx/Systems/CompatibilityDatabase.cs @@ -11,24 +11,9 @@ using System.Text; namespace Ryujinx.Ava.Systems { - public struct ColumnIndices(Func, int> getIndex) + public class CompatibilityDatabase { - public const string TitleIdCol = "\"title_id\""; - public const string GameNameCol = "\"game_name\""; - public const string LabelsCol = "\"labels\""; - public const string StatusCol = "\"status\""; - public const string LastUpdatedCol = "\"last_updated\""; - - public readonly int TitleId = getIndex(TitleIdCol); - public readonly int GameName = getIndex(GameNameCol); - public readonly int Labels = getIndex(LabelsCol); - public readonly int Status = getIndex(StatusCol); - public readonly int LastUpdated = getIndex(LastUpdatedCol); - } - - public class CompatibilityCsv - { - static CompatibilityCsv() => Load(); + static CompatibilityDatabase() => Load(); public static void Load() { @@ -65,16 +50,6 @@ namespace Ryujinx.Ava.Systems public static CompatibilityEntry Find(ulong titleId) => Find(titleId.ToString("X16")); - - public static LocaleKeys? GetStatus(string titleId) - => Find(titleId)?.Status; - - public static LocaleKeys? GetStatus(ulong titleId) => GetStatus(titleId.ToString("X16")); - - public static string GetLabels(string titleId) - => Find(titleId)?.FormattedIssueLabels; - - public static string GetLabels(ulong titleId) => GetLabels(titleId.ToString("X16")); } public class CompatibilityEntry @@ -135,6 +110,7 @@ namespace Ryujinx.Ava.Systems public string FormattedIssueLabels => Labels .Select(FormatLabelName) + .Where(x => x != null) .JoinToString(", "); public override string ToString() => @@ -158,7 +134,6 @@ namespace Ryujinx.Ava.Systems "gui" => "GUI", "help wanted" => "Help Wanted", "horizon" => "Horizon", - "infra" => "Project Infra", "invalid" => "Invalid", "kernel" => "Kernel", "ldn" => "LDN", @@ -172,9 +147,9 @@ namespace Ryujinx.Ava.Systems "ldn-untested" => "LDN Untested", "ldn-broken" => "LDN Broken", "ldn-partial" => "Partial LDN", - "nvdec" => "NVDEC", - "services" => "NX Services", - "services-horizon" => "Horizon OS Services", + "nvdec" => "GPU Video Decoding", + "services" => "HLE Services", + "services-horizon" => "New HLE Services", "slow" => "Runs Slow", "crash" => "Crashes", "deadlock" => "Deadlock", @@ -182,7 +157,7 @@ namespace Ryujinx.Ava.Systems "opengl" => "OpenGL", "opengl-backend-bug" => "OpenGL Backend Bug", "vulkan-backend-bug" => "Vulkan Backend Bug", - "mac-bug" => "Mac-specific Bug(s)", + "mac-bug" => "Mac-specific Problems", "amd-vendor-bug" => "AMD GPU Bug", "intel-vendor-bug" => "Intel GPU Bug", "loader-allocator" => "Loader Allocator", @@ -191,18 +166,22 @@ namespace Ryujinx.Ava.Systems "UE4" => "Unreal Engine 4", "homebrew" => "Homebrew Content", "online-broken" => "Online Broken", - _ => Capitalize(labelName) + _ => null }; + } + + public struct ColumnIndices(Func, int> getIndex) + { + private const string TitleIdCol = "\"title_id\""; + private const string GameNameCol = "\"game_name\""; + private const string LabelsCol = "\"labels\""; + private const string StatusCol = "\"status\""; + private const string LastUpdatedCol = "\"last_updated\""; - public static string Capitalize(string value) - { - if (value == string.Empty) - return string.Empty; - - char firstChar = value[0]; - string rest = value[1..]; - - return $"{char.ToUpper(firstChar)}{rest}"; - } + public readonly int TitleId = getIndex(TitleIdCol); + public readonly int GameName = getIndex(GameNameCol); + public readonly int Labels = getIndex(LabelsCol); + public readonly int Status = getIndex(StatusCol); + public readonly int LastUpdated = getIndex(LastUpdatedCol); } } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs index 042f95c46..c5315ab12 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// /// The current version of the file format /// - public const int CurrentVersion = 67; + public const int CurrentVersion = 68; /// /// Version of the configuration file format diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index fcea6dbf0..b10cc3926 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -46,12 +46,11 @@ namespace Ryujinx.Ava.Systems.Configuration EnableDiscordIntegration.Value = cff.EnableDiscordIntegration; - CheckUpdatesOnStart.Value = shouldLoadFromFile ? cff.CheckUpdatesOnStart : CheckUpdatesOnStart.Value; // Get from global config only UpdateCheckerType.Value = shouldLoadFromFile ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only FocusLostActionType.Value = cff.FocusLostActionType; ShowConfirmExit.Value = shouldLoadFromFile ? cff.ShowConfirmExit : ShowConfirmExit.Value; // Get from global config only RememberWindowState.Value = shouldLoadFromFile ? cff.RememberWindowState : RememberWindowState.Value; // Get from global config only - ShowTitleBar.Value = shouldLoadFromFile ? cff.ShowTitleBar : ShowTitleBar.Value; // Get from global config only + 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; @@ -161,9 +160,7 @@ namespace Ryujinx.Ava.Systems.Configuration DirtyHacks hacks = new (cff.DirtyHacks ?? []); Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix); - - Hacks.EnableShaderTranslationDelay.Value = hacks.IsEnabled(DirtyHack.ShaderTranslationDelay); - Hacks.ShaderTranslationDelay.Value = hacks[DirtyHack.ShaderTranslationDelay].CoerceAtLeast(0); + } if (configurationFileUpdated) @@ -442,6 +439,8 @@ namespace Ryujinx.Ava.Systems.Configuration (65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off), (66, static cff => cff.DisableInputWhenOutOfFocus = false), (67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing) + // 68 was the version that added per-game configs; the file structure did not change + // the version was increased so external tools could know that your Ryujinx version has per-game config capabilities. ); } } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs index 4d8a75de9..b52c624e3 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs @@ -11,7 +11,6 @@ using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; using Ryujinx.HLE; -using Ryujinx.HLE.HOS.SystemState; using System.Collections.Generic; using System.Linq; using RyuLogger = Ryujinx.Common.Logging.Logger; @@ -684,18 +683,15 @@ namespace Ryujinx.Ava.Systems.Configuration public ReactiveObject Xc2MenuSoftlockFix { get; private set; } - public ReactiveObject EnableShaderTranslationDelay { get; private set; } - - public ReactiveObject ShaderTranslationDelay { get; private set; } + public ReactiveObject DisableNifmIsAnyInternetRequestAccepted { get; private set; } public HacksSection() { ShowDirtyHacks = new ReactiveObject(); Xc2MenuSoftlockFix = new ReactiveObject(); Xc2MenuSoftlockFix.Event += HackChanged; - EnableShaderTranslationDelay = new ReactiveObject(); - EnableShaderTranslationDelay.Event += HackChanged; - ShaderTranslationDelay = new ReactiveObject(); + DisableNifmIsAnyInternetRequestAccepted = new ReactiveObject(); + DisableNifmIsAnyInternetRequestAccepted.Event += HackChanged; } private void HackChanged(object sender, ReactiveEventArgs rxe) @@ -726,8 +722,8 @@ namespace Ryujinx.Ava.Systems.Configuration if (Xc2MenuSoftlockFix) Apply(DirtyHack.Xc2MenuSoftlockFix); - if (EnableShaderTranslationDelay) - Apply(DirtyHack.ShaderTranslationDelay, ShaderTranslationDelay); + if (DisableNifmIsAnyInternetRequestAccepted) + Apply(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted); return enabledHacks.ToArray(); @@ -783,11 +779,6 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enables or disables Discord Rich Presence /// public ReactiveObject EnableDiscordIntegration { get; private set; } - - /// - /// Checks for updates when Ryujinx starts when enabled - /// - public ReactiveObject CheckUpdatesOnStart { get; private set; } /// /// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification. @@ -810,9 +801,9 @@ namespace Ryujinx.Ava.Systems.Configuration public ReactiveObject RememberWindowState { get; private set; } /// - /// Enables or disables the redesigned title bar + /// Disable the new title bar layout & window layout changes. /// - public ReactiveObject ShowTitleBar { get; private set; } + public ReactiveObject ShowOldUI { get; private set; } /// /// Enables hardware-accelerated rendering for Avalonia @@ -833,15 +824,14 @@ namespace Ryujinx.Ava.Systems.Configuration Hid = new HidSection(); Multiplayer = new MultiplayerSection(); Hacks = new HacksSection(); - EnableDiscordIntegration = new ReactiveObject(); - CheckUpdatesOnStart = new ReactiveObject(); UpdateCheckerType = new ReactiveObject(); FocusLostActionType = new ReactiveObject(); + HideCursor = new ReactiveObject(); + EnableDiscordIntegration = new ReactiveObject(); ShowConfirmExit = new ReactiveObject(); RememberWindowState = new ReactiveObject(); - ShowTitleBar = new ReactiveObject(); + ShowOldUI = new ReactiveObject(); EnableHardwareAcceleration = new ReactiveObject(); - HideCursor = new ReactiveObject(); } public HleConfiguration CreateHleConfiguration() => diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.cs index 811c0b971..6fe35c744 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.cs @@ -56,12 +56,11 @@ namespace Ryujinx.Ava.Systems.Configuration MatchSystemTime = System.MatchSystemTime, DockedMode = System.EnableDockedMode, EnableDiscordIntegration = EnableDiscordIntegration, - CheckUpdatesOnStart = CheckUpdatesOnStart, UpdateCheckerType = UpdateCheckerType, FocusLostActionType = FocusLostActionType, ShowConfirmExit = ShowConfirmExit, RememberWindowState = RememberWindowState, - ShowTitleBar = ShowTitleBar, + ShowTitleBar = ShowOldUI, EnableHardwareAcceleration = EnableHardwareAcceleration, HideCursor = HideCursor, VSyncMode = Graphics.VSyncMode, @@ -183,7 +182,7 @@ namespace Ryujinx.Ava.Systems.Configuration FocusLostActionType.Value = FocusLostType.DoNothing; ShowConfirmExit.Value = true; RememberWindowState.Value = true; - ShowTitleBar.Value = !OperatingSystem.IsWindows(); + ShowOldUI.Value = !OperatingSystem.IsWindows(); EnableHardwareAcceleration.Value = true; HideCursor.Value = HideCursorMode.OnIdle; Graphics.VSyncMode.Value = VSyncMode.Switch; diff --git a/src/Ryujinx/DiscordIntegrationModule.cs b/src/Ryujinx/Systems/DiscordIntegrationModule.cs similarity index 98% rename from src/Ryujinx/DiscordIntegrationModule.cs rename to src/Ryujinx/Systems/DiscordIntegrationModule.cs index 142261d72..8a3b42ac8 100644 --- a/src/Ryujinx/DiscordIntegrationModule.cs +++ b/src/Ryujinx/Systems/DiscordIntegrationModule.cs @@ -9,10 +9,9 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE; using Ryujinx.HLE.Loaders.Processes; using Ryujinx.Horizon; -using Ryujinx.Horizon.Prepo.Types; using System.Text; -namespace Ryujinx.Ava +namespace Ryujinx.Ava.Systems { public static class DiscordIntegrationModule { @@ -124,7 +123,7 @@ namespace Ryujinx.Ava _currentApp = null; } - private static void HandlePlayReport(PlayReport playReport) + private static void HandlePlayReport(Horizon.Prepo.Types.PlayReport playReport) { if (_discordClient is null) return; if (!TitleIDs.CurrentApplication.Value.HasValue) return; diff --git a/src/Ryujinx/Rebooter.cs b/src/Ryujinx/Systems/Rebooter.cs similarity index 96% rename from src/Ryujinx/Rebooter.cs rename to src/Ryujinx/Systems/Rebooter.cs index 8c7755a4c..4b149e9e3 100644 --- a/src/Ryujinx/Rebooter.cs +++ b/src/Ryujinx/Systems/Rebooter.cs @@ -1,8 +1,6 @@ using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; -using SkiaSharp; using System; using System.Collections.Generic; using System.Diagnostics; @@ -10,7 +8,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -namespace Ryujinx.Ava +namespace Ryujinx.Ava.Systems { internal static class Rebooter { diff --git a/src/Ryujinx/Updater.cs b/src/Ryujinx/Systems/Updater.cs similarity index 99% rename from src/Ryujinx/Updater.cs rename to src/Ryujinx/Systems/Updater.cs index 7ca5e885a..850bacc60 100644 --- a/src/Ryujinx/Updater.cs +++ b/src/Ryujinx/Systems/Updater.cs @@ -27,7 +27,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace Ryujinx.Ava +namespace Ryujinx.Ava.Systems { internal static class Updater { diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index 9635582c8..64377ba51 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -9,10 +9,10 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Ava.UI.Views.Misc; 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; @@ -80,13 +80,13 @@ namespace Ryujinx.Ava.UI.Controls public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args) { if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await TitleUpdateWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); + await TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); } public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args) { if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await DownloadableContentManagerWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); + await DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); } public async void OpenCheatManager_Click(object sender, RoutedEventArgs args) @@ -127,7 +127,7 @@ namespace Ryujinx.Ava.UI.Controls public async void OpenModManager_Click(object sender, RoutedEventArgs args) { if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await ModManagerWindow.Show( + await ModManagerView.Show( viewModel.SelectedApplication.Id, viewModel.SelectedApplication.IdBase, viewModel.ApplicationLibrary, diff --git a/src/Ryujinx/UI/Controls/StatusBarSeparator.cs b/src/Ryujinx/UI/Controls/MiniVerticalSeparator.cs similarity index 100% rename from src/Ryujinx/UI/Controls/StatusBarSeparator.cs rename to src/Ryujinx/UI/Controls/MiniVerticalSeparator.cs diff --git a/src/Ryujinx/UI/Controls/RyujinxLogo.cs b/src/Ryujinx/UI/Controls/RyujinxLogo.cs new file mode 100644 index 000000000..89b89f311 --- /dev/null +++ b/src/Ryujinx/UI/Controls/RyujinxLogo.cs @@ -0,0 +1,28 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Media.Imaging; +using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.UI.ViewModels; +using System.Reflection; + +namespace Ryujinx.Ava.UI.Controls +{ + public class RyujinxLogo : Image + { + // The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions. + // For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left. + // The border gets reduced to colored pixels in the 4 corners. + 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); + Height = 25; + Width = 25; + Source = Bitmap; + IsVisible = !ConfigurationState.Instance.ShowOldUI; + } + } +} diff --git a/src/Ryujinx/UI/Windows/IconColorPicker.cs b/src/Ryujinx/UI/Helpers/IconColorPicker.cs similarity index 98% rename from src/Ryujinx/UI/Windows/IconColorPicker.cs rename to src/Ryujinx/UI/Helpers/IconColorPicker.cs index ca9ac2c05..b6ee8bbbf 100644 --- a/src/Ryujinx/UI/Windows/IconColorPicker.cs +++ b/src/Ryujinx/UI/Helpers/IconColorPicker.cs @@ -2,9 +2,9 @@ using SkiaSharp; using System; using System.Collections.Generic; -namespace Ryujinx.Ava.UI.Windows +namespace Ryujinx.Ava.UI.Helpers { - static class IconColorPicker + public static class IconColorPicker { private const int ColorsPerLine = 64; private const int TotalColors = ColorsPerLine * ColorsPerLine; diff --git a/src/Ryujinx/RyujinxApp.axaml b/src/Ryujinx/UI/RyujinxApp.axaml similarity index 100% rename from src/Ryujinx/RyujinxApp.axaml rename to src/Ryujinx/UI/RyujinxApp.axaml diff --git a/src/Ryujinx/RyujinxApp.axaml.cs b/src/Ryujinx/UI/RyujinxApp.axaml.cs similarity index 98% rename from src/Ryujinx/RyujinxApp.axaml.cs rename to src/Ryujinx/UI/RyujinxApp.axaml.cs index 0a0f0a13c..2f460f2b3 100644 --- a/src/Ryujinx/RyujinxApp.axaml.cs +++ b/src/Ryujinx/UI/RyujinxApp.axaml.cs @@ -7,12 +7,12 @@ using Avalonia.Styling; using Avalonia.Threading; using FluentAvalonia.UI.Windowing; using Gommon; -using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Helpers; 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; @@ -150,7 +150,7 @@ namespace Ryujinx.Ava private async void AboutRyujinx_OnClick(object sender, EventArgs e) { - await AboutWindow.Show(); + await AboutView.Show(); } } } diff --git a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs index 07aa84c04..6e1bd7ce3 100644 --- a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs @@ -3,7 +3,6 @@ using Avalonia.Styling; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using Gommon; -using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Systems.Configuration; using System; diff --git a/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs b/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs index d6c10044d..1965fee69 100644 --- a/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs @@ -1,17 +1,17 @@ using Gommon; using Ryujinx.Ava.Systems; using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.UI.Windows; +using System; using System.Collections.Generic; using System.Linq; namespace Ryujinx.Ava.UI.ViewModels { - public class CompatibilityViewModel : BaseModel + public class CompatibilityViewModel : BaseModel, IDisposable { - private bool _onlyShowOwnedGames = true; + private readonly ApplicationLibrary _appLibrary; - private IEnumerable _currentEntries = CompatibilityCsv.Entries; + private IEnumerable _currentEntries = CompatibilityDatabase.Entries; private string[] _ownedGameTitleIds = []; public IEnumerable CurrentEntries => OnlyShowOwnedGames @@ -20,15 +20,27 @@ namespace Ryujinx.Ava.UI.ViewModels : _currentEntries; public CompatibilityViewModel() {} + + private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __) + => _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray(); public CompatibilityViewModel(ApplicationLibrary appLibrary) { - appLibrary.ApplicationCountUpdated += (_, _) - => _ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray(); + _appLibrary = appLibrary; - _ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray(); + AppCountUpdated(null, null); + + _appLibrary.ApplicationCountUpdated += AppCountUpdated; } + void IDisposable.Dispose() + { + GC.SuppressFinalize(this); + _appLibrary.ApplicationCountUpdated -= AppCountUpdated; + } + + private bool _onlyShowOwnedGames = true; + public bool OnlyShowOwnedGames { get => _onlyShowOwnedGames; @@ -46,11 +58,11 @@ namespace Ryujinx.Ava.UI.ViewModels { if (string.IsNullOrEmpty(searchTerm)) { - SetEntries(CompatibilityCsv.Entries); + SetEntries(CompatibilityDatabase.Entries); return; } - SetEntries(CompatibilityCsv.Entries.Where(x => + SetEntries(CompatibilityDatabase.Entries.Where(x => x.GameName.ContainsIgnoreCase(searchTerm) || x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm)))); } diff --git a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs index 96da58b5d..f8be4b2ce 100644 --- a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs @@ -1,9 +1,5 @@ using Avalonia.Svg.Skia; using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using FluentAvalonia.UI.Controls; -using Ryujinx.Ava.Input; -using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Views.Input; using Ryujinx.Common.Utilities; diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 1e7480b11..b0cd6a556 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -3,7 +3,6 @@ using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; using Avalonia.Media; -using Avalonia.Media.Imaging; using Avalonia.Platform.Storage; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; @@ -17,6 +16,7 @@ using LibHac.Ns; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; +using Ryujinx.Ava.Systems; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; @@ -46,7 +46,6 @@ using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; -using System.Reflection; using System.Threading; using System.Threading.Tasks; using Key = Ryujinx.Input.Key; @@ -137,13 +136,6 @@ namespace Ryujinx.Ava.UI.ViewModels // Key is Title ID public SafeDictionary LdnData = []; - // The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions. - // For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left. - // The border gets reduced to colored pixels in the 4 corners. - public static readonly Bitmap IconBitmap = - new(Assembly.GetAssembly(typeof(MainWindowViewModel))! - .GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!); - public MainWindow Window { get; init; } internal AppHost AppHost { get; set; } @@ -1794,7 +1786,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (WindowState is not WindowState.Normal) { WindowState = WindowState.Normal; - Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowTitleBar; + Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowOldUI; if (IsGameRunning) { diff --git a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs index 816e85c98..022b7481e 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs @@ -16,11 +16,12 @@ 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 fix applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.") + "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(); @@ -29,5 +30,14 @@ namespace Ryujinx.Ava.UI.ViewModels "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( + "This hack simply sets 'IsAnyInternetRequestAccepted' to 'false' when initializing the Nifm IGeneralService.") + .AppendLine(); + + sb.Append("Lets DOOM 2016 go in game."); + }); } } diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index aa6b34922..a092e97f2 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -130,11 +130,10 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS(); public bool EnableDiscordIntegration { get; set; } - public bool CheckUpdatesOnStart { get; set; } public bool ShowConfirmExit { get; set; } public bool IgnoreApplet { get; set; } public bool RememberWindowState { get; set; } - public bool ShowTitleBar { get; set; } + public bool ShowOldUI { get; set; } public int HideCursor { get; set; } public int UpdateCheckerType { get; set; } public bool EnableDockedMode { get; set; } @@ -537,10 +536,9 @@ namespace Ryujinx.Ava.UI.ViewModels // User Interface EnableDiscordIntegration = config.EnableDiscordIntegration; - CheckUpdatesOnStart = config.CheckUpdatesOnStart; ShowConfirmExit = config.ShowConfirmExit; RememberWindowState = config.RememberWindowState; - ShowTitleBar = config.ShowTitleBar; + ShowOldUI = config.ShowOldUI; HideCursor = (int)config.HideCursor.Value; UpdateCheckerType = (int)config.UpdateCheckerType.Value; FocusLostActionType = (int)config.FocusLostActionType.Value; @@ -646,10 +644,9 @@ namespace Ryujinx.Ava.UI.ViewModels // User Interface config.EnableDiscordIntegration.Value = EnableDiscordIntegration; - config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart; config.ShowConfirmExit.Value = ShowConfirmExit; config.RememberWindowState.Value = RememberWindowState; - config.ShowTitleBar.Value = ShowTitleBar; + config.ShowOldUI.Value = ShowOldUI; config.HideCursor.Value = (HideCursorMode)HideCursor; config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType; config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType; @@ -760,6 +757,8 @@ namespace Ryujinx.Ava.UI.ViewModels // Dirty Hacks config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix; + config.Hacks.DisableNifmIsAnyInternetRequestAccepted.Value = + DirtyHacks.NifmDisableIsAnyInternetRequestAccepted; config.ToFileFormat().SaveConfig(Program.ConfigurationPath); diff --git a/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs b/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs similarity index 98% rename from src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs rename to src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs index a48efcbd5..2085ffe26 100644 --- a/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs @@ -16,7 +16,7 @@ using static Ryujinx.Common.Utilities.XCIFileTrimmer; namespace Ryujinx.Ava.UI.ViewModels { - public class XCITrimmerViewModel : BaseModel + public class XciTrimmerViewModel : BaseModel { private const long _bytesPerMB = 1024 * 1024; private enum ProcessingMode @@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.ViewModels private SortField _sortField = SortField.Name; private bool _sortAscending = true; - public XCITrimmerViewModel(MainWindowViewModel mainWindowViewModel) + public XciTrimmerViewModel(MainWindowViewModel mainWindowViewModel) { _logger = new XCITrimmerLog.TrimmerWindow(this); _mainWindowViewModel = mainWindowViewModel; @@ -254,9 +254,9 @@ namespace Ryujinx.Ava.UI.ViewModels private class CompareXCITrimmerFiles : IComparer { - private XCITrimmerViewModel _viewModel; + private XciTrimmerViewModel _viewModel; - public CompareXCITrimmerFiles(XCITrimmerViewModel ViewModel) + public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel) { _viewModel = ViewModel; } diff --git a/src/Ryujinx/UI/Windows/AboutWindow.axaml b/src/Ryujinx/UI/Views/Dialog/AboutView.axaml similarity index 99% rename from src/Ryujinx/UI/Windows/AboutWindow.axaml rename to src/Ryujinx/UI/Views/Dialog/AboutView.axaml index e215cf27e..4c3da21e4 100644 --- a/src/Ryujinx/UI/Windows/AboutWindow.axaml +++ b/src/Ryujinx/UI/Views/Dialog/AboutView.axaml @@ -1,5 +1,5 @@ + public partial class AboutView : RyujinxControl { - public AboutWindow() + public AboutView() { InitializeComponent(); @@ -34,7 +32,7 @@ namespace Ryujinx.Ava.UI.Windows PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose], - Content = new AboutWindow { ViewModel = viewModel } + Content = new AboutView { ViewModel = viewModel } }; await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles()); diff --git a/src/Ryujinx/UI/Views/Misc/ApplicationDataView.axaml b/src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml similarity index 99% rename from src/Ryujinx/UI/Views/Misc/ApplicationDataView.axaml rename to src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml index a36b637ec..7ba4ad784 100644 --- a/src/Ryujinx/UI/Views/Misc/ApplicationDataView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml @@ -7,7 +7,7 @@ xmlns:ui="using:FluentAvalonia.UI.Controls" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Ryujinx.Ava.UI.Views.Misc.ApplicationDataView" + x:Class="Ryujinx.Ava.UI.Views.Dialog.ApplicationDataView" x:DataType="viewModels:ApplicationDataViewModel"> { diff --git a/src/Ryujinx/UI/Views/Misc/DlcSelectView.axaml b/src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml similarity index 98% rename from src/Ryujinx/UI/Views/Misc/DlcSelectView.axaml rename to src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml index f44bc3261..05d1f7ae5 100644 --- a/src/Ryujinx/UI/Views/Misc/DlcSelectView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml @@ -7,7 +7,7 @@ xmlns:models="using:Ryujinx.Ava.Common.Models" xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Ryujinx.Ava.UI.Views.Misc.DlcSelectView" + x:Class="Ryujinx.Ava.UI.Views.Dialog.DlcSelectView" x:DataType="viewModels:DlcSelectViewModel"> { diff --git a/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml similarity index 99% rename from src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml rename to src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml index e2c4fe16e..8b97a4822 100644 --- a/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml +++ b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml @@ -1,5 +1,5 @@ { - public DownloadableContentManagerViewModel ViewModel; - - public DownloadableContentManagerWindow() + public DownloadableContentManagerView() { - DataContext = this; - - InitializeComponent(); - } - - public DownloadableContentManagerWindow(ApplicationLibrary applicationLibrary, ApplicationData applicationData) - { - DataContext = ViewModel = new DownloadableContentManagerViewModel(applicationLibrary, applicationData); - InitializeComponent(); } @@ -36,8 +26,11 @@ namespace Ryujinx.Ava.UI.Windows PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = string.Empty, - Content = new DownloadableContentManagerWindow(applicationLibrary, applicationData), Title = string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowTitle], applicationData.Name, applicationData.IdBaseString), + Content = new DownloadableContentManagerView + { + ViewModel = new DownloadableContentManagerViewModel(applicationLibrary, applicationData) + } }; Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType()); diff --git a/src/Ryujinx/UI/Windows/ModManagerWindow.axaml b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml similarity index 99% rename from src/Ryujinx/UI/Windows/ModManagerWindow.axaml rename to src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml index 40ce6d6b5..ee913b56d 100644 --- a/src/Ryujinx/UI/Windows/ModManagerWindow.axaml +++ b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml @@ -10,7 +10,7 @@ Width="500" Height="380" mc:Ignorable="d" - x:Class="Ryujinx.Ava.UI.Windows.ModManagerWindow" + x:Class="Ryujinx.Ava.UI.Views.Dialog.ModManagerView" x:CompileBindings="True" x:DataType="viewModels:ModManagerViewModel" Focusable="True"> diff --git a/src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs similarity index 88% rename from src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs rename to src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs index e51d1ca4a..8735e2911 100644 --- a/src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs @@ -7,27 +7,17 @@ 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; -namespace Ryujinx.Ava.UI.Windows +namespace Ryujinx.Ava.UI.Views.Dialog { - public partial class ModManagerWindow : UserControl + public partial class ModManagerView : RyujinxControl { - public readonly ModManagerViewModel ViewModel; - - public ModManagerWindow() + public ModManagerView() { - DataContext = this; - - InitializeComponent(); - } - - public ModManagerWindow(ulong titleId, ulong titleIdBase, ApplicationLibrary applicationLibrary) - { - DataContext = ViewModel = new ModManagerViewModel(titleId, titleIdBase, applicationLibrary); - InitializeComponent(); } @@ -38,7 +28,10 @@ namespace Ryujinx.Ava.UI.Windows PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = string.Empty, - Content = new ModManagerWindow(titleId, titleIdBase, appLibrary), + Content = new ModManagerView + { + ViewModel = new ModManagerViewModel(titleId, titleIdBase, appLibrary) + }, Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowTitle], titleName, titleId.ToString("X16")), }; diff --git a/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml b/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml similarity index 99% rename from src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml rename to src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml index 4da727db5..ba3e85e8b 100644 --- a/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml +++ b/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml @@ -1,5 +1,5 @@ { - public readonly TitleUpdateViewModel ViewModel; - - public TitleUpdateWindow() + public TitleUpdateManagerView() { - DataContext = this; - - InitializeComponent(); - } - - public TitleUpdateWindow(ApplicationLibrary applicationLibrary, ApplicationData applicationData) - { - DataContext = ViewModel = new TitleUpdateViewModel(applicationLibrary, applicationData); - InitializeComponent(); } @@ -36,8 +26,11 @@ namespace Ryujinx.Ava.UI.Windows PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = string.Empty, - Content = new TitleUpdateWindow(applicationLibrary, applicationData), Title = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.GameUpdateWindowHeading, applicationData.Name, applicationData.IdBaseString), + Content = new TitleUpdateManagerView + { + ViewModel = new TitleUpdateViewModel(applicationLibrary, applicationData) + } }; Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType()); diff --git a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml b/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml similarity index 98% rename from src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml rename to src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml index e3bdabbf5..d149d246c 100644 --- a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml +++ b/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml @@ -1,5 +1,5 @@ @@ -151,7 +151,7 @@ HorizontalAlignment="Stretch" VerticalAlignment="Center" CornerRadius="5" - IsVisible="{Binding $parent[UserControl].((viewModels:XCITrimmerViewModel)DataContext).Processing}" + IsVisible="{Binding $parent[UserControl].((viewModels:XciTrimmerViewModel)DataContext).Processing}" Maximum="100" Minimum="0" Value="{Binding PercentageProgress}" /> diff --git a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs b/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml.cs similarity index 81% rename from src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs rename to src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml.cs index e02ff6279..8fb8c151c 100644 --- a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml.cs @@ -4,27 +4,17 @@ using Avalonia.Styling; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; +using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.ViewModels; using System; using System.Threading.Tasks; -namespace Ryujinx.Ava.UI.Windows +namespace Ryujinx.Ava.UI.Views.Dialog { - public partial class XCITrimmerWindow : UserControl + public partial class XciTrimmerView : RyujinxControl { - public XCITrimmerViewModel ViewModel; - - public XCITrimmerWindow() + public XciTrimmerView() { - DataContext = this; - - InitializeComponent(); - } - - public XCITrimmerWindow(MainWindowViewModel mainWindowViewModel) - { - DataContext = ViewModel = new XCITrimmerViewModel(mainWindowViewModel); - InitializeComponent(); } @@ -35,7 +25,10 @@ namespace Ryujinx.Ava.UI.Windows PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = string.Empty, - Content = new XCITrimmerWindow(RyujinxApp.MainWindow.ViewModel), + Content = new XciTrimmerView + { + ViewModel = new XciTrimmerViewModel(RyujinxApp.MainWindow.ViewModel) + }, Title = LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle] }; @@ -70,7 +63,7 @@ namespace Ryujinx.Ava.UI.Windows public void Sort_Checked(object sender, RoutedEventArgs args) { if (sender is RadioButton { Tag: string sortField }) - ViewModel.SortingField = Enum.Parse(sortField); + ViewModel.SortingField = Enum.Parse(sortField); } public void Order_Checked(object sender, RoutedEventArgs args) diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml index 555ded9fc..3fba2b804 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml @@ -4,10 +4,10 @@ xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" + xmlns:pt="using:Projektanker.Icons.Avalonia" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" d:DesignHeight="800" @@ -507,65 +507,49 @@ CornerRadius="5" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"> - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs index 3252ee7e2..916ada37e 100644 --- a/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs @@ -1,5 +1,4 @@ using Avalonia; -using Avalonia.Controls; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; diff --git a/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs index 329b9128e..2a83d1008 100644 --- a/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs @@ -1,4 +1,3 @@ -using Avalonia.Controls; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; diff --git a/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs index 2745ceac7..347d011d5 100644 --- a/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs @@ -1,4 +1,3 @@ -using Avalonia.Controls; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 1da91c388..61f5c1e50 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -6,18 +6,16 @@ xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" mc:Ignorable="d" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" + xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" x:DataType="viewModels:MainWindowViewModel" x:Class="Ryujinx.Ava.UI.Views.Main.MainMenuBarView"> - + CompatibilityListWindow.Show()); UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand; @@ -226,7 +223,7 @@ namespace Ryujinx.Ava.UI.Views.Main // Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024) double barsHeight = ((Window.StatusBarHeight + Window.MenuBarHeight) + - (ConfigurationState.Instance.ShowTitleBar ? (int)Window.TitleBar.Height : 0)); + (ConfigurationState.Instance.ShowOldUI ? (int)Window.TitleBar.Height : 0)); double windowWidthScaled = (resolutionWidth * Program.WindowScaleFactor); double windowHeightScaled = ((resolutionHeight + barsHeight) * Program.WindowScaleFactor); diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs index f8c4c48a2..8341dd92a 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs @@ -1,5 +1,4 @@ using Avalonia; -using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Threading; diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml index 4cf96366a..229f9e866 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml @@ -29,7 +29,7 @@ + Text="Highly specific hacks & tricks to alleviate performance issues, crashing, or freezing. Can cause issues." /> + + + + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs index d3d1537e0..46693374a 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -3,7 +3,9 @@ using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.LogicalTree; +using Avalonia.Threading; using Ryujinx.Ava.Input; +using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Input; @@ -13,7 +15,7 @@ using Key = Ryujinx.Common.Configuration.Hid.Key; namespace Ryujinx.Ava.UI.Views.Settings { - public partial class SettingsHotkeysView : UserControl + public partial class SettingsHotkeysView : RyujinxControl { private ButtonKeyAssigner _currentAssigner; private readonly IGamepadDriver _avaloniaKeyboardDriver; @@ -78,45 +80,49 @@ namespace Ryujinx.Ava.UI.Views.Settings { if (e.ButtonValue.HasValue) { - SettingsViewModel viewModel = (DataContext) as SettingsViewModel; Button buttonValue = e.ButtonValue.Value; - switch (button.Name) + Dispatcher.UIThread.Post(() => { - case "ToggleVSyncMode": - viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType(); - break; - case "Screenshot": - viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType(); - break; - case "ShowUI": - viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType(); - break; - case "Pause": - viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType(); - break; - case "ToggleMute": - viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType(); - break; - case "ResScaleUp": - viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType(); - break; - case "ResScaleDown": - viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType(); - break; - case "VolumeUp": - viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType(); - break; - case "VolumeDown": - viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType(); - break; - case "CustomVSyncIntervalIncrement": - viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType(); - break; - case "CustomVSyncIntervalDecrement": - viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType(); - break; - } + switch (button.Name) + { + case "ToggleVSyncMode": + ViewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType(); + break; + case "Screenshot": + ViewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType(); + break; + case "ShowUI": + ViewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType(); + break; + case "Pause": + ViewModel.KeyboardHotkey.Pause = buttonValue.AsHidType(); + break; + case "ToggleMute": + ViewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType(); + break; + case "ResScaleUp": + ViewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType(); + break; + case "ResScaleDown": + ViewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType(); + break; + case "VolumeUp": + ViewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType(); + break; + case "VolumeDown": + ViewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType(); + break; + case "CustomVSyncIntervalIncrement": + ViewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = + buttonValue.AsHidType(); + break; + case "CustomVSyncIntervalDecrement": + ViewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = + buttonValue.AsHidType(); + break; + } + }); } }; diff --git a/src/Ryujinx/UI/Views/Settings/SettingsNetworkView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsNetworkView.axaml.cs index c4987702c..934fcf142 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsNetworkView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsNetworkView.axaml.cs @@ -1,15 +1,13 @@ -using Avalonia.Controls; using Avalonia.Interactivity; +using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.ViewModels; using System; namespace Ryujinx.Ava.UI.Views.Settings { - public partial class SettingsNetworkView : UserControl + public partial class SettingsNetworkView : RyujinxControl { private readonly Random _random; - - public SettingsViewModel ViewModel; public SettingsNetworkView() { diff --git a/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml index dd6858ee6..a52fe5fbe 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml @@ -191,16 +191,16 @@ IsEnabled="{Binding !IsGameTitleNotNull}" Opacity="{Binding PanelOpacity}" Orientation="Horizontal"> - - + ToolTip.Tip="{ext:Locale MatchTimeTooltip}"> + + + { - public SettingsViewModel ViewModel; - public SettingsSystemView() { InitializeComponent(); diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml index 7dd5211a7..ad05efd06 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml @@ -6,7 +6,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" - xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common" mc:Ignorable="d" x:DataType="viewModels:SettingsViewModel"> @@ -19,245 +18,265 @@ HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> - - - - - - - - - - - - - - - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - + Margin="10" + Spacing="10" + Grid.Column="2" + Orientation="Vertical" HorizontalAlignment="Stretch"> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs index 2b0e57cb5..fb839a473 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs @@ -3,10 +3,10 @@ using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Platform.Storage; using Gommon; +using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -14,20 +14,18 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.UI.Views.Settings { - public partial class SettingsUiView : UserControl + public partial class SettingsUiView : RyujinxControl { - public SettingsViewModel ViewModel; - public SettingsUiView() { InitializeComponent(); AddGameDirButton.Command = - Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories, true)); + Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories)); AddAutoloadDirButton.Command = - Commands.Create(() => AddDirButton(AutoloadDirPathBox, ViewModel.AutoloadDirectories, false)); + Commands.Create(() => AddDirButton(AutoloadDirPathBox, ViewModel.AutoloadDirectories)); } - private async Task AddDirButton(TextBox addDirBox, AvaloniaList directories, bool isGameList) + private async Task AddDirButton(TextBox addDirBox, AvaloniaList directories) { string path = addDirBox.Text; diff --git a/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs index afd102d07..eb1cf58bb 100644 --- a/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs @@ -8,7 +8,6 @@ using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; using Ryujinx.HLE.HOS.Services.Account.Acc; -using System; using UserProfile = Ryujinx.Ava.UI.Models.UserProfile; namespace Ryujinx.Ava.UI.Views.User diff --git a/src/Ryujinx/UI/Views/User/UserRecovererView.axaml.cs b/src/Ryujinx/UI/Views/User/UserRecovererView.axaml.cs index 34dc3edab..d1fd70e9b 100644 --- a/src/Ryujinx/UI/Views/User/UserRecovererView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserRecovererView.axaml.cs @@ -1,4 +1,3 @@ -using Avalonia.Controls; using Avalonia.Interactivity; using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Navigation; diff --git a/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs b/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs index 8aff9c5f9..edbbd595b 100644 --- a/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs @@ -1,4 +1,3 @@ -using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Threading; using FluentAvalonia.UI.Controls; diff --git a/src/Ryujinx/UI/Windows/AmiiboWindow.axaml b/src/Ryujinx/UI/Windows/AmiiboWindow.axaml index ce410923d..ad77a9b6b 100644 --- a/src/Ryujinx/UI/Windows/AmiiboWindow.axaml +++ b/src/Ryujinx/UI/Windows/AmiiboWindow.axaml @@ -6,6 +6,7 @@ xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" + xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="350" @@ -23,7 +24,25 @@ - + + + + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Windows/AmiiboWindow.axaml.cs b/src/Ryujinx/UI/Windows/AmiiboWindow.axaml.cs index 8c76b8e2f..2d6eb4716 100644 --- a/src/Ryujinx/UI/Windows/AmiiboWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/AmiiboWindow.axaml.cs @@ -1,13 +1,14 @@ using Avalonia.Interactivity; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models.Amiibo; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.ViewModels; namespace Ryujinx.Ava.UI.Windows { public partial class AmiiboWindow : StyleableAppWindow { - public AmiiboWindow(bool showAll, string lastScannedAmiiboId, string titleId) + public AmiiboWindow(bool showAll, string lastScannedAmiiboId, string titleId) : base(true, 40) { DataContext = ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId) { @@ -16,6 +17,9 @@ namespace Ryujinx.Ava.UI.Windows InitializeComponent(); + FlushControls.IsVisible = !ConfigurationState.Instance.ShowOldUI; + NormalControls.IsVisible = ConfigurationState.Instance.ShowOldUI; + Title = RyujinxApp.FormatTitle(LocaleKeys.Amiibo); } diff --git a/src/Ryujinx/UI/Windows/CheatWindow.axaml b/src/Ryujinx/UI/Windows/CheatWindow.axaml index 32f914019..49b13048f 100644 --- a/src/Ryujinx/UI/Windows/CheatWindow.axaml +++ b/src/Ryujinx/UI/Windows/CheatWindow.axaml @@ -6,6 +6,7 @@ xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows" + xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" Width="600" Height="750" MinWidth="500" @@ -20,38 +21,81 @@ - - - + + + + + + + + + + + + + + - + ToolTip.Tip="{ext:WindowTitle CompatibilityListTitle, False}"/> @@ -40,7 +40,7 @@ - ShowAsync(new CompatibilityListWindow + public static async Task Show(string titleId = null) + { + using CompatibilityViewModel compatWindow = new(RyujinxApp.MainWindow.ViewModel.ApplicationLibrary); + + await ShowAsync(new CompatibilityListWindow { - DataContext = new CompatibilityViewModel(RyujinxApp.MainWindow.ViewModel.ApplicationLibrary), + DataContext = compatWindow, SearchBoxFlush = { Text = titleId ?? string.Empty }, SearchBoxNormal = { Text = titleId ?? string.Empty } }); + } - public CompatibilityListWindow() : base(useCustomTitleBar: true) + public CompatibilityListWindow() : base(useCustomTitleBar: true, 37) { Title = RyujinxApp.FormatTitle(LocaleKeys.CompatibilityListTitle); - TitleBar.Height = 37; - InitializeComponent(); - - RyuLogo.Source = MainWindowViewModel.IconBitmap; - FlushControls.IsVisible = !ConfigurationState.Instance.ShowTitleBar; - NormalControls.IsVisible = ConfigurationState.Instance.ShowTitleBar; + + FlushControls.IsVisible = !ConfigurationState.Instance.ShowOldUI; + NormalControls.IsVisible = ConfigurationState.Instance.ShowOldUI; } // ReSharper disable once UnusedMember.Local diff --git a/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml b/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml index 6dcd13755..f51f14c1e 100644 --- a/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml +++ b/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml @@ -13,7 +13,7 @@ xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common" Width="1100" Height="910" - MinWidth="800" + MinWidth="1037" MinHeight="480" WindowStartupLocation="CenterOwner" x:DataType="viewModels:SettingsViewModel" diff --git a/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs b/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs index 8e2761bff..0d172ff59 100644 --- a/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs @@ -1,25 +1,9 @@ -using Avalonia; using Avalonia.Controls; -using Avalonia.Controls.Shapes; -using Avalonia.Input; -using Avalonia.Media.Imaging; -using FluentAvalonia.Core; using FluentAvalonia.UI.Controls; -using Projektanker.Icons.Avalonia; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Ava.UI.ViewModels.Input; -using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.Configuration; -using Ryujinx.Common.Configuration; -using Ryujinx.HLE.FileSystem; -using Ryujinx.HLE.HOS.SystemState; -using Ryujinx.Input; using System; -using System.IO; using System.Linq; -using Key = Avalonia.Input.Key; namespace Ryujinx.Ava.UI.Windows diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 512a93f26..4f5cb13d3 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -7,13 +7,12 @@ using Avalonia.Platform; using Avalonia.Threading; using DynamicData; using FluentAvalonia.UI.Controls; -using FluentAvalonia.UI.Windowing; using Gommon; using LibHac.Ns; -using LibHac.Tools.FsSystem; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; +using Ryujinx.Ava.Systems; using Ryujinx.Ava.UI.Applet; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; @@ -97,7 +96,7 @@ namespace Ryujinx.Ava.UI.Windows TitleBar.Height = MenuBarHeight; // Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024) - TitleBarHeight = (ConfigurationState.Instance.ShowTitleBar ? TitleBar.Height : 0); + TitleBarHeight = (ConfigurationState.Instance.ShowOldUI ? TitleBar.Height : 0); ApplicationList.DataContext = DataContext; ApplicationGrid.DataContext = DataContext; diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml b/src/Ryujinx/UI/Windows/SettingsWindow.axaml index 54ca4cbbd..15d174123 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml @@ -11,10 +11,11 @@ xmlns:settings="clr-namespace:Ryujinx.Ava.UI.Views.Settings" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common" + xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" Width="1100" - Height="927" - MinWidth="800" + MinWidth="844" MinHeight="480" + Title="{ext:WindowTitle Settings}" WindowStartupLocation="CenterOwner" x:DataType="viewModels:SettingsViewModel" mc:Ignorable="d" @@ -22,13 +23,20 @@ - + + + + - + @@ -41,12 +49,11 @@ @@ -108,7 +115,7 @@ -