From c19c8bbadea027e4f31a0739fac0f2a27fbe6dbf Mon Sep 17 00:00:00 2001 From: Theun de Bruijn Date: Thu, 6 Jul 2023 20:10:15 +1000 Subject: [PATCH 1/4] Headless: Add support for fullscreen option (#5339) * Headless: Added support for fullscreen option * Headless: cleanup of fullscreen support * Headless: fullscreen support : implemented proposed changes * Headless: fullscreen support: cleanup * Headless: fullscreen support: fix for OpenGL scaling * Headless: fullscreen support: cleanup * Headless: fullscreen support: cleanup * Headless: fullscreen support: add. macOS fullscreen fix * Headless: fullscreen support: cleanup * Headless: fullscreen support: cleanup * Headless: fullscreen support: cleanup --- .../OpenGL/OpenGLWindow.cs | 18 ++++++++++++++++-- src/Ryujinx.Headless.SDL2/Options.cs | 3 +++ src/Ryujinx.Headless.SDL2/Program.cs | 5 +++++ src/Ryujinx.Headless.SDL2/WindowBase.cs | 19 ++++++++++++++----- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs b/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs index 199f723e9..355dcf6c7 100644 --- a/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs +++ b/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs @@ -151,8 +151,22 @@ namespace Ryujinx.Headless.SDL2.OpenGL GL.Clear(ClearBufferMask.ColorBufferBit); SwapBuffers(); - Renderer?.Window.SetSize(DefaultWidth, DefaultHeight); - MouseDriver.SetClientSize(DefaultWidth, DefaultHeight); + if (IsFullscreen) + { + // NOTE: grabbing the main display's dimensions directly as OpenGL doesn't scale along like the VulkanWindow. + // we might have to amend this if people run this on a non-primary display set to a different resolution. + SDL_Rect displayBounds; + SDL_GetDisplayBounds(0, out displayBounds); + + Renderer?.Window.SetSize(displayBounds.w, displayBounds.h); + MouseDriver.SetClientSize(displayBounds.w, displayBounds.h); + } + + else + { + Renderer?.Window.SetSize(DefaultWidth, DefaultHeight); + MouseDriver.SetClientSize(DefaultWidth, DefaultHeight); + } } protected override void InitializeRenderer() { } diff --git a/src/Ryujinx.Headless.SDL2/Options.cs b/src/Ryujinx.Headless.SDL2/Options.cs index 86a6c63c4..e44cedec9 100644 --- a/src/Ryujinx.Headless.SDL2/Options.cs +++ b/src/Ryujinx.Headless.SDL2/Options.cs @@ -14,6 +14,9 @@ namespace Ryujinx.Headless.SDL2 [Option("profile", Required = false, HelpText = "Set the user profile to launch the game with.")] public string UserProfile { get; set; } + [Option("fullscreen", Required = false, HelpText = "Launch the game in fullscreen mode.")] + public bool IsFullscreen { get; set; } + // Input [Option("input-profile-1", Required = false, HelpText = "Set the input profile in use for Player 1.")] diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 39eae14a8..98cc5abf4 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -64,6 +64,9 @@ namespace Ryujinx.Headless.SDL2 { Version = ReleaseInformation.GetVersion(); + // Make process DPI aware for proper window sizing on high-res screens. + ForceDpiAware.Windows(); + Console.Title = $"Ryujinx Console {Version} (Headless SDL2)"; if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux()) @@ -592,6 +595,8 @@ namespace Ryujinx.Headless.SDL2 _window = window; + _window.IsFullscreen = options.IsFullscreen; + _emulationContext = InitializeEmulationContext(window, renderer, options); SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion(); diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs index 2fcd00f86..c542a4e61 100644 --- a/src/Ryujinx.Headless.SDL2/WindowBase.cs +++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs @@ -55,6 +55,7 @@ namespace Ryujinx.Headless.SDL2 public IHostUiTheme HostUiTheme { get; } public int Width { get; private set; } public int Height { get; private set; } + public bool IsFullscreen { get; set; } protected SDL2MouseDriver MouseDriver; private readonly InputManager _inputManager; @@ -158,7 +159,9 @@ namespace Ryujinx.Headless.SDL2 string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})"; string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; - WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, DefaultFlags | GetWindowFlags()); + SDL_WindowFlags fullscreenFlag = IsFullscreen ? SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP : 0; + + WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, DefaultFlags | fullscreenFlag | GetWindowFlags()); if (WindowHandle == IntPtr.Zero) { @@ -185,10 +188,16 @@ namespace Ryujinx.Headless.SDL2 switch (evnt.window.windowEvent) { case SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED: - Width = evnt.window.data1; - Height = evnt.window.data2; - Renderer?.Window.SetSize(Width, Height); - MouseDriver.SetClientSize(Width, Height); + // Unlike on Windows, this event fires on macOS when triggering fullscreen mode. + // And promptly crashes the process because `Renderer?.window.SetSize` is undefined. + // As we don't need this to fire in either case we can test for isFullscreen. + if (!IsFullscreen) + { + Width = evnt.window.data1; + Height = evnt.window.data2; + Renderer?.Window.SetSize(Width, Height); + MouseDriver.SetClientSize(Width, Height); + } break; case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE: From 2b5abac809dacb351ec69e322732d45ea01a4d65 Mon Sep 17 00:00:00 2001 From: SuperSamus <40663462+SuperSamus@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:11:26 +0200 Subject: [PATCH 2/4] sdl: set `SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS` to 0 (#5433) Nintendo controllers notoriously have the A/B and X/Y buttons swapped, compared to the standard. In order to combat this, when setting the default controller layout, Ryujinx checks whether the controller name contains "Nintendo", and swaps the mapping accordingly. However, the reason the mapping is inverted in the first place is because SDL has `SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS` set to 1 by default. By setting it to 0, the mapping will be based on the buttons' position instead. So, by doing it (and removing the `isNintendoStyle` variable), we get the following advantages: - The mapping will be the same on all controllers, removing the need to adjust custom mappings depending on what controller is used - Users who already set `SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS` to 0 globally for other games/applications (like me) won't have a wrong default mapping - Checking whether the controller name contains "Nintendo" is ugly Disadvantages: - Breaks the controller configuration for existing users who are using a Nintendo controller --- .../UI/ViewModels/ControllerInputViewModel.cs | 10 ++++------ src/Ryujinx.Headless.SDL2/Program.cs | 10 ++++------ src/Ryujinx.SDL2.Common/SDL2Driver.cs | 1 + src/Ryujinx/Ui/Windows/ControllerWindow.cs | 10 ++++------ 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs index fda58504e..8b5dbcef0 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs @@ -597,8 +597,6 @@ namespace Ryujinx.Ava.UI.ViewModels } else if (activeDevice.Type == DeviceType.Controller) { - bool isNintendoStyle = Devices.ToList().Find(x => x.Id == activeDevice.Id).Name.Contains("Nintendo"); - string id = activeDevice.Id.Split(" ")[0]; config = new StandardControllerInputConfig @@ -633,10 +631,10 @@ namespace Ryujinx.Ava.UI.ViewModels }, RightJoycon = new RightJoyconCommonConfig { - ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B, - ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A, - ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y, - ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X, + ButtonA = ConfigGamepadInputId.B, + ButtonB = ConfigGamepadInputId.A, + ButtonX = ConfigGamepadInputId.Y, + ButtonY = ConfigGamepadInputId.X, ButtonPlus = ConfigGamepadInputId.Plus, ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 98cc5abf4..ffcac9ed5 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -195,8 +195,6 @@ namespace Ryujinx.Headless.SDL2 } else { - bool isNintendoStyle = gamepadName.Contains("Nintendo"); - config = new StandardControllerInputConfig { Version = InputConfig.CurrentVersion, @@ -232,10 +230,10 @@ namespace Ryujinx.Headless.SDL2 RightJoycon = new RightJoyconCommonConfig { - ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B, - ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A, - ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y, - ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X, + ButtonA = ConfigGamepadInputId.B, + ButtonB = ConfigGamepadInputId.A, + ButtonX = ConfigGamepadInputId.Y, + ButtonY = ConfigGamepadInputId.X, ButtonPlus = ConfigGamepadInputId.Plus, ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs index 2642b26fa..3411fa041 100644 --- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs +++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs @@ -60,6 +60,7 @@ namespace Ryujinx.SDL2.Common SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); + SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); diff --git a/src/Ryujinx/Ui/Windows/ControllerWindow.cs b/src/Ryujinx/Ui/Windows/ControllerWindow.cs index ebf22ab60..2993e1f23 100644 --- a/src/Ryujinx/Ui/Windows/ControllerWindow.cs +++ b/src/Ryujinx/Ui/Windows/ControllerWindow.cs @@ -1035,8 +1035,6 @@ namespace Ryujinx.Ui.Windows } else if (_inputDevice.ActiveId.StartsWith("controller")) { - bool isNintendoStyle = _inputDevice.ActiveText.Contains("Nintendo"); - config = new StandardControllerInputConfig { Version = InputConfig.CurrentVersion, @@ -1072,10 +1070,10 @@ namespace Ryujinx.Ui.Windows RightJoycon = new RightJoyconCommonConfig { - ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B, - ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A, - ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y, - ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X, + ButtonA = ConfigGamepadInputId.B, + ButtonB = ConfigGamepadInputId.A, + ButtonX = ConfigGamepadInputId.Y, + ButtonY = ConfigGamepadInputId.X, ButtonPlus = ConfigGamepadInputId.Plus, ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, From 8a363b5df2387bd254a3dd48bfd3c9884ff74dab Mon Sep 17 00:00:00 2001 From: Mary Date: Thu, 6 Jul 2023 18:08:14 +0200 Subject: [PATCH 3/4] Revert "sdl: set `SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS` to 0 (#5433)" (#5439) This reverts commit 2b5abac809dacb351ec69e322732d45ea01a4d65. --- .../UI/ViewModels/ControllerInputViewModel.cs | 10 ++++++---- src/Ryujinx.Headless.SDL2/Program.cs | 10 ++++++---- src/Ryujinx.SDL2.Common/SDL2Driver.cs | 1 - src/Ryujinx/Ui/Windows/ControllerWindow.cs | 10 ++++++---- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs index 8b5dbcef0..fda58504e 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs @@ -597,6 +597,8 @@ namespace Ryujinx.Ava.UI.ViewModels } else if (activeDevice.Type == DeviceType.Controller) { + bool isNintendoStyle = Devices.ToList().Find(x => x.Id == activeDevice.Id).Name.Contains("Nintendo"); + string id = activeDevice.Id.Split(" ")[0]; config = new StandardControllerInputConfig @@ -631,10 +633,10 @@ namespace Ryujinx.Ava.UI.ViewModels }, RightJoycon = new RightJoyconCommonConfig { - ButtonA = ConfigGamepadInputId.B, - ButtonB = ConfigGamepadInputId.A, - ButtonX = ConfigGamepadInputId.Y, - ButtonY = ConfigGamepadInputId.X, + ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B, + ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A, + ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y, + ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X, ButtonPlus = ConfigGamepadInputId.Plus, ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index ffcac9ed5..98cc5abf4 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -195,6 +195,8 @@ namespace Ryujinx.Headless.SDL2 } else { + bool isNintendoStyle = gamepadName.Contains("Nintendo"); + config = new StandardControllerInputConfig { Version = InputConfig.CurrentVersion, @@ -230,10 +232,10 @@ namespace Ryujinx.Headless.SDL2 RightJoycon = new RightJoyconCommonConfig { - ButtonA = ConfigGamepadInputId.B, - ButtonB = ConfigGamepadInputId.A, - ButtonX = ConfigGamepadInputId.Y, - ButtonY = ConfigGamepadInputId.X, + ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B, + ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A, + ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y, + ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X, ButtonPlus = ConfigGamepadInputId.Plus, ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs index 3411fa041..2642b26fa 100644 --- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs +++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs @@ -60,7 +60,6 @@ namespace Ryujinx.SDL2.Common SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); diff --git a/src/Ryujinx/Ui/Windows/ControllerWindow.cs b/src/Ryujinx/Ui/Windows/ControllerWindow.cs index 2993e1f23..ebf22ab60 100644 --- a/src/Ryujinx/Ui/Windows/ControllerWindow.cs +++ b/src/Ryujinx/Ui/Windows/ControllerWindow.cs @@ -1035,6 +1035,8 @@ namespace Ryujinx.Ui.Windows } else if (_inputDevice.ActiveId.StartsWith("controller")) { + bool isNintendoStyle = _inputDevice.ActiveText.Contains("Nintendo"); + config = new StandardControllerInputConfig { Version = InputConfig.CurrentVersion, @@ -1070,10 +1072,10 @@ namespace Ryujinx.Ui.Windows RightJoycon = new RightJoyconCommonConfig { - ButtonA = ConfigGamepadInputId.B, - ButtonB = ConfigGamepadInputId.A, - ButtonX = ConfigGamepadInputId.Y, - ButtonY = ConfigGamepadInputId.X, + ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B, + ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A, + ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y, + ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X, ButtonPlus = ConfigGamepadInputId.Plus, ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, From 6c515e18228b93c4d856129ba55a692e830cbdaa Mon Sep 17 00:00:00 2001 From: TSRBerry <20988865+TSRBerry@users.noreply.github.com> Date: Fri, 7 Jul 2023 23:03:27 +0200 Subject: [PATCH 4/4] [Ryujinx.Ava] Address dotnet-format issues (#5361) * dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Silence dotnet format IDE0059 warnings * Address or silence dotnet format IDE1006 warnings * Address dotnet format CA1816 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Make dotnet format succeed in style mode * Address dotnet format CA1401 warnings * Address remaining dotnet format analyzer warnings * Address review comments * dotnet-format fixes after rebase * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Format if-blocks correctly * Another rebase, another dotnet format run * Run dotnet format whitespace after rebase * Run dotnet format style after rebase * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Add comments to disabled warnings * Remove a few unused parameters * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Address IDE0260 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * dotnet format pass with new editorconfig * Fix naming style issues * Apply suggestions from code review Co-authored-by: Ac_K * Revert one suggestion * Second dotnet format pass and fix build issues * Final pass of dotnet format * Add trailing commas * Fix formatting issues * Keep unnecessary assignment in IconColorPicker.cs * Use using declarations and extend resource lifetimes * Fix rebase issues * Adjust comment spacing * Fix typo * Fix naming issues * Apply suggestions from code review Co-authored-by: Ac_K * Revert unintentional change * Remove unused file * Remove static keyword from ViewModels Binding of static members doesn't work and is silently ignored. --------- Co-authored-by: Ac_K --- src/Ryujinx.Ava/App.axaml.cs | 5 +- src/Ryujinx.Ava/AppHost.cs | 233 +++++------ src/Ryujinx.Ava/Common/ApplicationHelper.cs | 25 +- src/Ryujinx.Ava/Common/ApplicationSort.cs | 4 +- src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs | 4 +- .../Common/Locale/LocaleExtension.cs | 6 +- .../Common/Locale/LocaleManager.cs | 20 +- src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs | 28 +- .../Input/AvaloniaKeyboardDriver.cs | 20 +- .../Input/AvaloniaKeyboardMappingHelper.cs | 4 +- src/Ryujinx.Ava/Input/AvaloniaMouse.cs | 10 +- src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs | 44 +-- src/Ryujinx.Ava/Modules/Updater/Updater.cs | 200 +++++----- src/Ryujinx.Ava/Program.cs | 32 +- src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs | 13 +- .../Applet/AvaloniaDynamicTextInputHandler.cs | 8 +- .../UI/Applet/AvaloniaHostUiTheme.cs | 10 +- .../UI/Applet/ErrorAppletWindow.axaml.cs | 6 +- .../UI/Applet/SwkbdAppletDialog.axaml.cs | 20 +- .../Controls/ApplicationContextMenu.axaml.cs | 5 +- .../UI/Controls/ApplicationGridView.axaml.cs | 2 +- .../UI/Controls/ApplicationListView.axaml.cs | 2 +- .../UI/Controls/NavigationDialogHost.axaml.cs | 21 +- .../UI/Controls/UpdateWaitWindow.axaml.cs | 2 +- .../UI/Helpers/ApplicationOpenedEventArgs.cs | 2 +- .../UI/Helpers/BitmapArrayValueConverter.cs | 2 +- .../UI/Helpers/ButtonKeyAssigner.cs | 2 +- .../UI/Helpers/ContentDialogHelper.cs | 61 ++- .../UI/Helpers/GlyphValueConverter.cs | 17 +- src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs | 2 +- .../UI/Helpers/KeyValueConverter.cs | 2 +- src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs | 28 +- src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs | 4 +- .../UI/Helpers/NotificationHelper.cs | 8 +- .../UI/Helpers/NullableDateTimeConverter.cs | 2 +- .../UI/Helpers/OffscreenTextBox.cs | 10 +- src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs | 13 +- src/Ryujinx.Ava/UI/Helpers/UserResult.cs | 2 +- .../UI/Helpers/Win32NativeInterop.cs | 54 +-- src/Ryujinx.Ava/UI/Models/CheatModel.cs | 8 +- src/Ryujinx.Ava/UI/Models/CheatsList.cs | 6 +- src/Ryujinx.Ava/UI/Models/DeviceType.cs | 4 +- .../UI/Models/DownloadableContentModel.cs | 12 +- .../Models/Generic/LastPlayedSortComparer.cs | 2 +- .../UI/Models/InputConfiguration.cs | 298 +++++++------- .../UI/Models/ProfileImageModel.cs | 2 +- src/Ryujinx.Ava/UI/Models/SaveModel.cs | 13 +- .../UI/Models/StatusUpdatedEventArgs.cs | 2 +- src/Ryujinx.Ava/UI/Models/TempProfile.cs | 4 +- src/Ryujinx.Ava/UI/Models/TimeZone.cs | 2 +- src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs | 2 +- src/Ryujinx.Ava/UI/Models/UserProfile.cs | 5 +- src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs | 78 ++-- .../UI/Renderer/EmbeddedWindowOpenGL.cs | 2 +- .../UI/Renderer/EmbeddedWindowVulkan.cs | 4 +- .../UI/Renderer/OpenTKBindingsContext.cs | 2 +- .../UI/Renderer/RendererHost.axaml.cs | 8 +- .../UI/Renderer/SPBOpenGLContext.cs | 6 +- .../UI/ViewModels/AboutWindowViewModel.cs | 5 +- .../UI/ViewModels/AmiiboWindowViewModel.cs | 38 +- .../UI/ViewModels/AvatarProfileViewModel.cs | 363 ------------------ src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs | 2 +- .../UI/ViewModels/ControllerInputViewModel.cs | 111 +++--- .../DownloadableContentManagerViewModel.cs | 49 ++- .../UI/ViewModels/MainWindowViewModel.cs | 102 ++--- .../UI/ViewModels/MotionInputViewModel.cs | 2 +- .../UI/ViewModels/RumbleInputViewModel.cs | 2 +- .../UI/ViewModels/SettingsViewModel.cs | 7 +- .../UI/ViewModels/TitleUpdateViewModel.cs | 61 ++- .../UserFirmwareAvatarSelectorViewModel.cs | 166 ++++---- .../UserProfileImageSelectorViewModel.cs | 4 +- .../UI/ViewModels/UserProfileViewModel.cs | 9 +- .../UI/ViewModels/UserSaveManagerViewModel.cs | 25 +- .../Views/Input/ControllerInputView.axaml.cs | 4 +- .../UI/Views/Input/MotionInputView.axaml.cs | 8 +- .../UI/Views/Input/RumbleInputView.axaml.cs | 8 +- .../UI/Views/Main/MainMenuBarView.axaml.cs | 22 +- .../UI/Views/Main/MainStatusBarView.axaml.cs | 2 +- .../UI/Views/Main/MainViewControls.axaml.cs | 8 +- .../Views/Settings/SettingsAudioView.axaml.cs | 2 +- .../Views/Settings/SettingsCPUView.axaml.cs | 2 +- .../Settings/SettingsGraphicsView.axaml.cs | 2 +- .../Settings/SettingsHotkeysView.axaml.cs | 12 +- .../Views/Settings/SettingsInputView.axaml.cs | 2 +- .../Settings/SettingsLoggingView.axaml.cs | 2 +- .../Settings/SettingsNetworkView.axaml.cs | 2 +- .../Settings/SettingsSystemView.axaml.cs | 4 +- .../UI/Views/Settings/SettingsUIView.axaml | 2 +- .../UI/Views/Settings/SettingsUIView.axaml.cs | 19 +- .../UI/Views/User/UserEditorView.axaml.cs | 14 +- .../UserFirmwareAvatarSelectorView.axaml.cs | 5 +- .../UserProfileImageSelectorView.axaml.cs | 20 +- .../UI/Views/User/UserRecovererView.axaml.cs | 2 +- .../Views/User/UserSaveManagerView.axaml.cs | 19 +- .../UI/Views/User/UserSelectorView.axaml.cs | 7 +- .../UI/Windows/AboutWindow.axaml.cs | 11 +- .../UI/Windows/AmiiboWindow.axaml.cs | 9 +- .../UI/Windows/CheatWindow.axaml.cs | 20 +- .../ContentDialogOverlayWindow.axaml.cs | 7 +- .../DownloadableContentManagerWindow.axaml | 4 +- .../DownloadableContentManagerWindow.axaml.cs | 14 +- src/Ryujinx.Ava/UI/Windows/IconColorPicker.cs | 2 + .../UI/Windows/MainWindow.axaml.cs | 39 +- .../UI/Windows/SettingsWindow.axaml | 4 +- .../UI/Windows/SettingsWindow.axaml.cs | 6 +- src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs | 5 +- .../UI/Windows/TitleUpdateWindow.axaml.cs | 14 +- .../FileSystem/VirtualFileSystem.cs | 1 - 108 files changed, 1140 insertions(+), 1503 deletions(-) delete mode 100644 src/Ryujinx.Ava/UI/ViewModels/AvatarProfileViewModel.cs diff --git a/src/Ryujinx.Ava/App.axaml.cs b/src/Ryujinx.Ava/App.axaml.cs index e36cbfdd6..4ecc424a6 100644 --- a/src/Ryujinx.Ava/App.axaml.cs +++ b/src/Ryujinx.Ava/App.axaml.cs @@ -5,7 +5,6 @@ using Avalonia.Styling; using Avalonia.Threading; using FluentAvalonia.Styling; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Common; @@ -67,7 +66,7 @@ namespace Ryujinx.Ava if (result == UserResult.Yes) { - var path = Process.GetCurrentProcess().MainModule.FileName; + var path = Environment.ProcessPath; var proc = Process.Start(path, CommandLineState.Arguments); desktop.Shutdown(); Environment.Exit(0); @@ -151,4 +150,4 @@ namespace Ryujinx.Ava } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs index c2b1064be..7c1ce542c 100644 --- a/src/Ryujinx.Ava/AppHost.cs +++ b/src/Ryujinx.Ava/AppHost.cs @@ -1,4 +1,5 @@ using ARMeilleure.Translation; +using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; @@ -26,6 +27,7 @@ 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; @@ -41,7 +43,6 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SPB.Graphics.Exceptions; using SPB.Graphics.Vulkan; using System; using System.Collections.Generic; @@ -50,10 +51,12 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop; +using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing; using Image = SixLabors.ImageSharp.Image; using InputManager = Ryujinx.Input.HLE.InputManager; using Key = Ryujinx.Input.Key; using MouseButton = Ryujinx.Input.MouseButton; +using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter; using Size = Avalonia.Size; using Switch = Ryujinx.HLE.Switch; @@ -61,31 +64,31 @@ namespace Ryujinx.Ava { internal class AppHost { - private const int CursorHideIdleTime = 5; // Hide Cursor seconds. + private const int CursorHideIdleTime = 5; // Hide Cursor seconds. private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping. - private const int TargetFps = 60; - private const float VolumeDelta = 0.05f; + private const int TargetFps = 60; + private const float VolumeDelta = 0.05f; - private static readonly Cursor InvisibleCursor = new(StandardCursorType.None); - private readonly IntPtr InvisibleCursorWin; - private readonly IntPtr DefaultCursorWin; + private static readonly Cursor _invisibleCursor = new(StandardCursorType.None); + private readonly IntPtr _invisibleCursorWin; + private readonly IntPtr _defaultCursorWin; - private readonly long _ticksPerFrame; + private readonly long _ticksPerFrame; private readonly Stopwatch _chrono; - private long _ticks; + private long _ticks; - private readonly AccountManager _accountManager; + private readonly AccountManager _accountManager; private readonly UserChannelPersistence _userChannelPersistence; - private readonly InputManager _inputManager; + private readonly InputManager _inputManager; private readonly MainWindowViewModel _viewModel; - private readonly IKeyboard _keyboardInterface; - private readonly TopLevel _topLevel; - public RendererHost _rendererHost; + private readonly IKeyboard _keyboardInterface; + private readonly TopLevel _topLevel; + public RendererHost RendererHost; private readonly GraphicsDebugLevel _glLogLevel; - private float _newVolume; - private KeyboardHotkeyState _prevHotkeyState; + private float _newVolume; + private KeyboardHotkeyState _prevHotkeyState; private long _lastCursorMoveTime; private bool _isCursorInRenderer = true; @@ -94,14 +97,14 @@ namespace Ryujinx.Ava private bool _isActive; private bool _renderingStarted; - private ManualResetEvent _gpuDoneEvent; + private readonly ManualResetEvent _gpuDoneEvent; - private IRenderer _renderer; - private readonly Thread _renderingThread; + private IRenderer _renderer; + private readonly Thread _renderingThread; private readonly CancellationTokenSource _gpuCancellationTokenSource; private WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution; - private bool _dialogShown; + private bool _dialogShown; private readonly bool _isFirmwareTitle; private readonly object _lockObject = new(); @@ -109,55 +112,55 @@ namespace Ryujinx.Ava public event EventHandler AppExit; public event EventHandler StatusUpdatedEvent; - public VirtualFileSystem VirtualFileSystem { get; } - public ContentManager ContentManager { get; } - public NpadManager NpadManager { get; } + public VirtualFileSystem VirtualFileSystem { get; } + public ContentManager ContentManager { get; } + public NpadManager NpadManager { get; } public TouchScreenManager TouchScreenManager { get; } - public Switch Device { get; set; } + public Switch Device { get; set; } - public int Width { get; private set; } - public int Height { get; private set; } - public string ApplicationPath { get; private set; } - public bool ScreenshotRequested { get; set; } + public int Width { get; private set; } + public int Height { get; private set; } + public string ApplicationPath { get; private set; } + public bool ScreenshotRequested { get; set; } public AppHost( - RendererHost renderer, - InputManager inputManager, - string applicationPath, - VirtualFileSystem virtualFileSystem, - ContentManager contentManager, - AccountManager accountManager, + RendererHost renderer, + InputManager inputManager, + string applicationPath, + VirtualFileSystem virtualFileSystem, + ContentManager contentManager, + AccountManager accountManager, UserChannelPersistence userChannelPersistence, - MainWindowViewModel viewmodel, - TopLevel topLevel) + MainWindowViewModel viewmodel, + TopLevel topLevel) { - _viewModel = viewmodel; - _inputManager = inputManager; - _accountManager = accountManager; + _viewModel = viewmodel; + _inputManager = inputManager; + _accountManager = accountManager; _userChannelPersistence = userChannelPersistence; - _renderingThread = new Thread(RenderLoop) { Name = "GUI.RenderThread" }; - _lastCursorMoveTime = Stopwatch.GetTimestamp(); - _glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel; - _topLevel = topLevel; + _renderingThread = new Thread(RenderLoop) { Name = "GUI.RenderThread" }; + _lastCursorMoveTime = Stopwatch.GetTimestamp(); + _glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel; + _topLevel = topLevel; _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_topLevel, renderer)); _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0"); - NpadManager = _inputManager.CreateNpadManager(); + NpadManager = _inputManager.CreateNpadManager(); TouchScreenManager = _inputManager.CreateTouchScreenManager(); - ApplicationPath = applicationPath; - VirtualFileSystem = virtualFileSystem; - ContentManager = contentManager; + ApplicationPath = applicationPath; + VirtualFileSystem = virtualFileSystem; + ContentManager = contentManager; - _rendererHost = renderer; + RendererHost = renderer; - _chrono = new Stopwatch(); + _chrono = new Stopwatch(); _ticksPerFrame = Stopwatch.Frequency / TargetFps; if (ApplicationPath.StartsWith("@SystemContent")) { - ApplicationPath = _viewModel.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath); + ApplicationPath = VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath); _isFirmwareTitle = true; } @@ -170,21 +173,21 @@ namespace Ryujinx.Ava if (OperatingSystem.IsWindows()) { - InvisibleCursorWin = CreateEmptyCursor(); - DefaultCursorWin = CreateArrowCursor(); + _invisibleCursorWin = CreateEmptyCursor(); + _defaultCursorWin = CreateArrowCursor(); } ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState; - ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState; - ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState; - ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState; - ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState; - ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState; - ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAntiAliasing; - ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter; - ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel; + ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState; + ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState; + ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState; + ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState; + ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState; + ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAntiAliasing; + ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter; + ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel; - ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState; + ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState; _gpuCancellationTokenSource = new CancellationTokenSource(); _gpuDoneEvent = new ManualResetEvent(false); @@ -196,10 +199,10 @@ namespace Ryujinx.Ava { _lastCursorMoveTime = Stopwatch.GetTimestamp(); - if (_rendererHost.EmbeddedWindow.TransformedBounds != null) + if (RendererHost.EmbeddedWindow.TransformedBounds != null) { - var point = e.GetCurrentPoint(window).Position; - var bounds = _rendererHost.EmbeddedWindow.TransformedBounds.Value.Clip; + var point = e.GetCurrentPoint(window).Position; + var bounds = RendererHost.EmbeddedWindow.TransformedBounds.Value.Clip; _isCursorInRenderer = point.X >= bounds.X && point.X <= bounds.Width + bounds.X && @@ -220,7 +223,7 @@ namespace Ryujinx.Ava _renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value); } - private void UpdateScalingFilter(object sender, ReactiveEventArgs e) + private void UpdateScalingFilter(object sender, ReactiveEventArgs e) { _renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value); _renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value); @@ -234,7 +237,7 @@ namespace Ryujinx.Ava if (OperatingSystem.IsWindows()) { - SetCursor(DefaultCursorWin); + SetCursor(_defaultCursorWin); } }); } @@ -243,11 +246,11 @@ namespace Ryujinx.Ava { Dispatcher.UIThread.Post(() => { - _viewModel.Cursor = InvisibleCursor; + _viewModel.Cursor = _invisibleCursor; if (OperatingSystem.IsWindows()) { - SetCursor(InvisibleCursorWin); + SetCursor(_invisibleCursorWin); } }); } @@ -271,12 +274,12 @@ namespace Ryujinx.Ava lock (_lockObject) { DateTime currentTime = DateTime.Now; - string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png"; + string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png"; string directory = AppDataManager.Mode switch { AppDataManager.LaunchMode.Portable or AppDataManager.LaunchMode.Custom => Path.Combine(AppDataManager.BaseDirPath, "screenshots"), - _ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx") + _ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx"), }; string path = Path.Combine(directory, filename); @@ -305,9 +308,9 @@ namespace Ryujinx.Ava image.Mutate(x => x.Flip(FlipMode.Vertical)); } - image.SaveAsPng(path, new PngEncoder() + image.SaveAsPng(path, new PngEncoder { - ColorType = PngColorType.Rgb + ColorType = PngColorType.Rgb, }); image.Dispose(); @@ -336,21 +339,21 @@ namespace Ryujinx.Ava _viewModel.IsGameRunning = true; - var activeProcess = Device.Processes.ActiveApplication; + var activeProcess = Device.Processes.ActiveApplication; - string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}"; + string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}"; string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}"; - string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})"; - string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; + string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})"; + string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; Dispatcher.UIThread.InvokeAsync(() => { _viewModel.Title = $"Ryujinx {Program.Version} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}"; }); - _viewModel.SetUIProgressHandlers(Device); + _viewModel.SetUiProgressHandlers(Device); - _rendererHost.SizeChanged += Window_SizeChanged; + RendererHost.SizeChanged += Window_SizeChanged; _isActive = true; @@ -379,7 +382,7 @@ namespace Ryujinx.Ava } } - private void UpdateAntiAliasing(object sender, ReactiveEventArgs e) + private void UpdateAntiAliasing(object sender, ReactiveEventArgs e) { _renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)e.NewValue); } @@ -419,7 +422,7 @@ namespace Ryujinx.Ava } _isStopped = true; - _isActive = false; + _isActive = false; } public void DisposeContext() @@ -448,16 +451,16 @@ namespace Ryujinx.Ava { if (Device.Processes != null) { - _viewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText); + MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText); } ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState; - ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState; - ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState; - ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState; - ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter; - ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel; - ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing; + ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState; + ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState; + ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState; + ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter; + ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel; + ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing; _topLevel.PointerMoved -= TopLevel_PointerEnterOrMoved; _topLevel.PointerEnter -= TopLevel_PointerEnterOrMoved; @@ -477,7 +480,7 @@ namespace Ryujinx.Ava _windowsMultimediaTimerResolution = null; } - if (_rendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow) + if (RendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow) { // Try to bind the OpenGL context before calling the shutdown event. openGlWindow.MakeCurrent(false, false); @@ -508,7 +511,7 @@ namespace Ryujinx.Ava SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion(); - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { if (!SetupValidator.CanStartApplication(ContentManager, ApplicationPath, out UserError userError)) { @@ -526,7 +529,7 @@ namespace Ryujinx.Ava if (result != UserResult.Yes) { - await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow)); + await UserErrorDialog.ShowUserErrorDialog(userError); Device.Dispose(); return false; @@ -535,7 +538,7 @@ namespace Ryujinx.Ava if (!SetupValidator.TryFixStartApplication(ContentManager, ApplicationPath, userError, out _)) { - await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow)); + await UserErrorDialog.ShowUserErrorDialog(userError); Device.Dispose(); return false; @@ -558,7 +561,7 @@ namespace Ryujinx.Ava } else { - await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow)); + await UserErrorDialog.ShowUserErrorDialog(userError); Device.Dispose(); return false; @@ -727,7 +730,7 @@ namespace Ryujinx.Ava { renderer = new VulkanRenderer( Vk.GetApi(), - (_rendererHost.EmbeddedWindow as EmbeddedWindowVulkan).CreateSurface, + (RendererHost.EmbeddedWindow as EmbeddedWindowVulkan).CreateSurface, VulkanHelper.GetRequiredInstanceExtensions, ConfigurationState.Instance.Graphics.PreferredGpu.Value); } @@ -738,18 +741,18 @@ namespace Ryujinx.Ava BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading; - var isGALthreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading); - if (isGALthreaded) + var isGALThreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading); + if (isGALThreaded) { renderer = new ThreadedRenderer(renderer); } - Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALthreaded}"); + Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALThreaded}"); // Initialize Configuration. - var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value ? HLE.MemoryConfiguration.MemoryConfiguration6GiB : HLE.MemoryConfiguration.MemoryConfiguration4GiB; + var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value ? MemoryConfiguration.MemoryConfiguration6GiB : MemoryConfiguration.MemoryConfiguration4GiB; - HLE.HLEConfiguration configuration = new(VirtualFileSystem, + HLEConfiguration configuration = new(VirtualFileSystem, _viewModel.LibHacHorizonManager, ContentManager, _accountManager, @@ -780,12 +783,12 @@ namespace Ryujinx.Ava private static IHardwareDeviceDriver InitializeAudio() { - var availableBackends = new List() + var availableBackends = new List { AudioBackend.SDL2, AudioBackend.SoundIo, AudioBackend.OpenAl, - AudioBackend.Dummy + AudioBackend.Dummy, }; AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value; @@ -806,12 +809,10 @@ namespace Ryujinx.Ava { return new T(); } - else - { - Logger.Warning?.Print(LogClass.Audio, $"{backend} is not supported, falling back to {nextBackend}."); - return null; - } + Logger.Warning?.Print(LogClass.Audio, $"{backend} is not supported, falling back to {nextBackend}."); + + return null; } IHardwareDeviceDriver deviceDriver = null; @@ -819,14 +820,14 @@ namespace Ryujinx.Ava for (int i = 0; i < availableBackends.Count; i++) { AudioBackend currentBackend = availableBackends[i]; - AudioBackend nextBackend = i + 1 < availableBackends.Count ? availableBackends[i + 1] : AudioBackend.Dummy; + AudioBackend nextBackend = i + 1 < availableBackends.Count ? availableBackends[i + 1] : AudioBackend.Dummy; deviceDriver = currentBackend switch { - AudioBackend.SDL2 => InitializeAudioBackend(AudioBackend.SDL2, nextBackend), + AudioBackend.SDL2 => InitializeAudioBackend(AudioBackend.SDL2, nextBackend), AudioBackend.SoundIo => InitializeAudioBackend(AudioBackend.SoundIo, nextBackend), - AudioBackend.OpenAl => InitializeAudioBackend(AudioBackend.OpenAl, nextBackend), - _ => new DummyHardwareDeviceDriver() + AudioBackend.OpenAl => InitializeAudioBackend(AudioBackend.OpenAl, nextBackend), + _ => new DummyHardwareDeviceDriver(), }; if (deviceDriver != null) @@ -843,7 +844,7 @@ namespace Ryujinx.Ava private void Window_SizeChanged(object sender, Size e) { - Width = (int)e.Width; + Width = (int)e.Width; Height = (int)e.Height; SetRendererWindowSize(e); @@ -879,7 +880,7 @@ namespace Ryujinx.Ava _renderer.ScreenCaptured += Renderer_ScreenCaptured; - (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.InitializeBackgroundContext(_renderer); + (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.InitializeBackgroundContext(_renderer); Device.Gpu.Renderer.Initialize(_glLogLevel); @@ -887,8 +888,8 @@ namespace Ryujinx.Ava _renderer?.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value); _renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value); - Width = (int)_rendererHost.Bounds.Width; - Height = (int)_rendererHost.Bounds.Height; + Width = (int)RendererHost.Bounds.Width; + Height = (int)RendererHost.Bounds.Height; _renderer.Window.SetSize((int)(Width * _topLevel.PlatformImpl.RenderScaling), (int)(Height * _topLevel.PlatformImpl.RenderScaling)); @@ -923,7 +924,7 @@ namespace Ryujinx.Ava _viewModel.SwitchToRenderer(false); } - Device.PresentFrame(() => (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.SwapBuffers()); + Device.PresentFrame(() => (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.SwapBuffers()); } if (_ticks >= _ticksPerFrame) @@ -941,7 +942,7 @@ namespace Ryujinx.Ava _gpuDoneEvent.Set(); }); - (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true); + (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true); } public void UpdateStatus() @@ -1175,4 +1176,4 @@ namespace Ryujinx.Ava return state; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Common/ApplicationHelper.cs b/src/Ryujinx.Ava/Common/ApplicationHelper.cs index 882c06949..b8f2366cd 100644 --- a/src/Ryujinx.Ava/Common/ApplicationHelper.cs +++ b/src/Ryujinx.Ava/Common/ApplicationHelper.cs @@ -18,7 +18,6 @@ using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; -using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.Ui.App.Common; using Ryujinx.Ui.Common.Helper; @@ -27,6 +26,7 @@ using System.Buffers; using System.IO; using System.Threading; using System.Threading.Tasks; +using ApplicationId = LibHac.Ncm.ApplicationId; using Path = System.IO.Path; namespace Ryujinx.Ava.Common @@ -57,7 +57,7 @@ namespace Ryujinx.Ava.Common Logger.Info?.Print(LogClass.Application, $"Creating save directory for Title: {titleName} [{titleId:x16}]"); - if (Utilities.IsZeros(controlHolder.ByteSpan)) + if (controlHolder.ByteSpan.IsZeros()) { // If the current application doesn't have a loaded control property, create a dummy one // and set the savedata sizes so a user savedata will be created. @@ -72,7 +72,7 @@ namespace Ryujinx.Ava.Common Uid user = new((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low); - result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new LibHac.Ncm.ApplicationId(titleId), in control, in user); + result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new ApplicationId(titleId), in control, in user); if (result.IsFailure()) { Dispatcher.UIThread.InvokeAsync(async () => @@ -147,11 +147,11 @@ namespace Ryujinx.Ava.Common { OpenFolderDialog folderDialog = new() { - Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], }; - string destination = await folderDialog.ShowAsync(_owner); - var cancellationToken = new CancellationTokenSource(); + string destination = await folderDialog.ShowAsync(_owner); + var cancellationToken = new CancellationTokenSource(); UpdateWaitWindow waitingDialog = new( LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle], @@ -166,7 +166,7 @@ namespace Ryujinx.Ava.Common using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read); - Nca mainNca = null; + Nca mainNca = null; Nca patchNca = null; string extension = Path.GetExtension(titleFilePath).ToLower(); @@ -293,10 +293,11 @@ namespace Ryujinx.Ava.Common await ContentDialogHelper.CreateErrorDialog(ex.Message); }); } - }); - - extractorThread.Name = "GUI.NcaSectionExtractorThread"; - extractorThread.IsBackground = true; + }) + { + Name = "GUI.NcaSectionExtractorThread", + IsBackground = true, + }; extractorThread.Start(); } } @@ -413,4 +414,4 @@ namespace Ryujinx.Ava.Common return Result.Success; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Common/ApplicationSort.cs b/src/Ryujinx.Ava/Common/ApplicationSort.cs index 6ff06a1e2..4b80e3d29 100644 --- a/src/Ryujinx.Ava/Common/ApplicationSort.cs +++ b/src/Ryujinx.Ava/Common/ApplicationSort.cs @@ -10,6 +10,6 @@ namespace Ryujinx.Ava.Common FileType, FileSize, Path, - Favorite + Favorite, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs b/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs index e85bdf341..1d7f0b9ce 100644 --- a/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs +++ b/src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs @@ -11,6 +11,6 @@ ResScaleUp, ResScaleDown, VolumeUp, - VolumeDown + VolumeDown, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Common/Locale/LocaleExtension.cs b/src/Ryujinx.Ava/Common/Locale/LocaleExtension.cs index b82c405de..cd1c1510d 100644 --- a/src/Ryujinx.Ava/Common/Locale/LocaleExtension.cs +++ b/src/Ryujinx.Ava/Common/Locale/LocaleExtension.cs @@ -20,11 +20,11 @@ namespace Ryujinx.Ava.Common.Locale ReflectionBindingExtension binding = new($"[{keyToUse}]") { - Mode = BindingMode.OneWay, - Source = LocaleManager.Instance + Mode = BindingMode.OneWay, + Source = LocaleManager.Instance, }; return binding.ProvideValue(serviceProvider); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs b/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs index 464ab780d..583619fe5 100644 --- a/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs +++ b/src/Ryujinx.Ava/Common/Locale/LocaleManager.cs @@ -13,17 +13,17 @@ namespace Ryujinx.Ava.Common.Locale { private const string DefaultLanguageCode = "en_US"; - private Dictionary _localeStrings; - private Dictionary _localeDefaultStrings; + private readonly Dictionary _localeStrings; + private Dictionary _localeDefaultStrings; private readonly ConcurrentDictionary _dynamicValues; - public static LocaleManager Instance { get; } = new LocaleManager(); + public static LocaleManager Instance { get; } = new(); public LocaleManager() { - _localeStrings = new Dictionary(); + _localeStrings = new Dictionary(); _localeDefaultStrings = new Dictionary(); - _dynamicValues = new ConcurrentDictionary(); + _dynamicValues = new ConcurrentDictionary(); Load(); } @@ -126,11 +126,11 @@ namespace Ryujinx.Ava.Common.Locale } } - private Dictionary LoadJsonLanguage(string languageCode = DefaultLanguageCode) + private static Dictionary LoadJsonLanguage(string languageCode = DefaultLanguageCode) { - var localeStrings = new Dictionary(); - string languageJson = EmbeddedResources.ReadAllText($"Ryujinx.Ava/Assets/Locales/{languageCode}.json"); - var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary); + var localeStrings = new Dictionary(); + string languageJson = EmbeddedResources.ReadAllText($"Ryujinx.Ava/Assets/Locales/{languageCode}.json"); + var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary); foreach (var item in strings) { @@ -143,4 +143,4 @@ namespace Ryujinx.Ava.Common.Locale return localeStrings; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs b/src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs index d40ebbd2b..d07c81340 100644 --- a/src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs +++ b/src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs @@ -12,25 +12,25 @@ namespace Ryujinx.Ava.Input internal class AvaloniaKeyboard : IKeyboard { private readonly List _buttonsUserMapping; - private readonly AvaloniaKeyboardDriver _driver; - private StandardKeyboardInputConfig _configuration; + private readonly AvaloniaKeyboardDriver _driver; + private StandardKeyboardInputConfig _configuration; private readonly object _userMappingLock = new(); - public string Id { get; } + public string Id { get; } public string Name { get; } - public bool IsConnected => true; - public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None; + public bool IsConnected => true; + public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None; private class ButtonMappingEntry { - public readonly Key From; + public readonly Key From; public readonly GamepadButtonInputId To; public ButtonMappingEntry(GamepadButtonInputId to, Key from) { - To = to; + To = to; From = from; } } @@ -40,8 +40,8 @@ namespace Ryujinx.Ava.Input _buttonsUserMapping = new List(); _driver = driver; - Id = id; - Name = name; + Id = id; + Name = name; } public KeyboardStateSnapshot GetKeyboardStateSnapshot() @@ -52,7 +52,7 @@ namespace Ryujinx.Ava.Input public GamepadStateSnapshot GetMappedStateSnapshot() { KeyboardStateSnapshot rawState = GetKeyboardStateSnapshot(); - GamepadStateSnapshot result = default; + GamepadStateSnapshot result = default; lock (_userMappingLock) { @@ -75,10 +75,10 @@ namespace Ryujinx.Ava.Input } } - (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick); + (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick); (short rightStickX, short rightStickY) = GetStickValues(ref rawState, _configuration.RightJoyconStick); - result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY)); + result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY)); result.SetStick(StickInputId.Right, ConvertRawStickValue(rightStickX), ConvertRawStickValue(rightStickY)); } @@ -120,6 +120,7 @@ namespace Ryujinx.Ava.Input _buttonsUserMapping.Clear(); +#pragma warning disable IDE0055 // Disable formatting // Left JoyCon _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton)); _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp)); @@ -143,6 +144,7 @@ namespace Ryujinx.Ava.Input _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr)); _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (Key)_configuration.RightJoycon.ButtonSr)); _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl)); +#pragma warning restore IDE0055 } } @@ -198,4 +200,4 @@ namespace Ryujinx.Ava.Input public void Dispose() { } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs b/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs index edcdb52fd..f12d0214b 100644 --- a/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs +++ b/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs @@ -13,23 +13,23 @@ namespace Ryujinx.Ava.Input internal class AvaloniaKeyboardDriver : IGamepadDriver { private static readonly string[] _keyboardIdentifers = new string[1] { "0" }; - private readonly Control _control; + private readonly Control _control; private readonly HashSet _pressedKeys; public event EventHandler KeyPressed; public event EventHandler KeyRelease; - public event EventHandler TextInput; + public event EventHandler TextInput; - public string DriverName => "AvaloniaKeyboardDriver"; + public string DriverName => "AvaloniaKeyboardDriver"; public ReadOnlySpan GamepadsIds => _keyboardIdentifers; public AvaloniaKeyboardDriver(Control control) { - _control = control; + _control = control; _pressedKeys = new HashSet(); - _control.KeyDown += OnKeyPress; - _control.KeyUp += OnKeyRelease; + _control.KeyDown += OnKeyPress; + _control.KeyUp += OnKeyRelease; _control.TextInput += Control_TextInput; _control.AddHandler(InputElement.TextInputEvent, Control_LastChanceTextInput, RoutingStrategies.Bubble); } @@ -47,13 +47,13 @@ namespace Ryujinx.Ava.Input public event Action OnGamepadConnected { - add { } + add { } remove { } } public event Action OnGamepadDisconnected { - add { } + add { } remove { } } @@ -71,7 +71,7 @@ namespace Ryujinx.Ava.Input { if (disposing) { - _control.KeyUp -= OnKeyPress; + _control.KeyUp -= OnKeyPress; _control.KeyDown -= OnKeyRelease; } } @@ -112,4 +112,4 @@ namespace Ryujinx.Ava.Input Dispose(true); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs b/src/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs index 0cc04d0a9..d30a7566a 100644 --- a/src/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs +++ b/src/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs @@ -143,7 +143,7 @@ namespace Ryujinx.Ava.Input AvaKey.OemBackslash, // NOTE: invalid - AvaKey.None + AvaKey.None, }; private static readonly Dictionary _avaKeyMapping; @@ -182,4 +182,4 @@ namespace Ryujinx.Ava.Input return _avaKeyMapping.GetValueOrDefault(key, Key.Unknown); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Input/AvaloniaMouse.cs b/src/Ryujinx.Ava/Input/AvaloniaMouse.cs index 3a9c91c0d..1aa2d586a 100644 --- a/src/Ryujinx.Ava/Input/AvaloniaMouse.cs +++ b/src/Ryujinx.Ava/Input/AvaloniaMouse.cs @@ -10,12 +10,12 @@ namespace Ryujinx.Ava.Input { private AvaloniaMouseDriver _driver; - public string Id => "0"; + public string Id => "0"; public string Name => "AvaloniaMouse"; - public bool IsConnected => true; - public GamepadFeaturesFlag Features => throw new NotImplementedException(); - public bool[] Buttons => _driver.PressedButtons; + public bool IsConnected => true; + public GamepadFeaturesFlag Features => throw new NotImplementedException(); + public bool[] Buttons => _driver.PressedButtons; public AvaloniaMouse(AvaloniaMouseDriver driver) { @@ -84,4 +84,4 @@ namespace Ryujinx.Ava.Input _driver = null; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs b/src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs index b7e5a4d95..e71bbf64a 100644 --- a/src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs +++ b/src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs @@ -11,16 +11,16 @@ namespace Ryujinx.Ava.Input { internal class AvaloniaMouseDriver : IGamepadDriver { - private Control _widget; - private bool _isDisposed; - private Size _size; + private Control _widget; + private bool _isDisposed; + private Size _size; private readonly TopLevel _window; - public bool[] PressedButtons { get; } + public bool[] PressedButtons { get; } public Vector2 CurrentPosition { get; private set; } - public Vector2 Scroll { get; private set; } + public Vector2 Scroll { get; private set; } - public string DriverName => "AvaloniaMouseDriver"; + public string DriverName => "AvaloniaMouseDriver"; public ReadOnlySpan GamepadsIds => new[] { "0" }; public AvaloniaMouseDriver(TopLevel window, Control parent) @@ -28,14 +28,14 @@ namespace Ryujinx.Ava.Input _widget = parent; _window = window; - _widget.PointerMoved += Parent_PointerMovedEvent; - _widget.PointerPressed += Parent_PointerPressedEvent; - _widget.PointerReleased += Parent_PointerReleasedEvent; + _widget.PointerMoved += Parent_PointerMovedEvent; + _widget.PointerPressed += Parent_PointerPressedEvent; + _widget.PointerReleased += Parent_PointerReleasedEvent; _widget.PointerWheelChanged += Parent_PointerWheelChanged; - - _window.PointerMoved += Parent_PointerMovedEvent; - _window.PointerPressed += Parent_PointerPressedEvent; - _window.PointerReleased += Parent_PointerReleasedEvent; + + _window.PointerMoved += Parent_PointerMovedEvent; + _window.PointerPressed += Parent_PointerPressedEvent; + _window.PointerReleased += Parent_PointerReleasedEvent; _window.PointerWheelChanged += Parent_PointerWheelChanged; PressedButtons = new bool[(int)MouseButton.Count]; @@ -47,13 +47,13 @@ namespace Ryujinx.Ava.Input public event Action OnGamepadConnected { - add { } + add { } remove { } } public event Action OnGamepadDisconnected { - add { } + add { } remove { } } @@ -143,17 +143,17 @@ namespace Ryujinx.Ava.Input _isDisposed = true; - _widget.PointerMoved -= Parent_PointerMovedEvent; - _widget.PointerPressed -= Parent_PointerPressedEvent; - _widget.PointerReleased -= Parent_PointerReleasedEvent; + _widget.PointerMoved -= Parent_PointerMovedEvent; + _widget.PointerPressed -= Parent_PointerPressedEvent; + _widget.PointerReleased -= Parent_PointerReleasedEvent; _widget.PointerWheelChanged -= Parent_PointerWheelChanged; - _window.PointerMoved -= Parent_PointerMovedEvent; - _window.PointerPressed -= Parent_PointerPressedEvent; - _window.PointerReleased -= Parent_PointerReleasedEvent; + _window.PointerMoved -= Parent_PointerMovedEvent; + _window.PointerPressed -= Parent_PointerPressedEvent; + _window.PointerReleased -= Parent_PointerReleasedEvent; _window.PointerWheelChanged -= Parent_PointerWheelChanged; _widget = null; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Modules/Updater/Updater.cs b/src/Ryujinx.Ava/Modules/Updater/Updater.cs index 71d978c67..8216333a7 100644 --- a/src/Ryujinx.Ava/Modules/Updater/Updater.cs +++ b/src/Ryujinx.Ava/Modules/Updater/Updater.cs @@ -31,22 +31,22 @@ namespace Ryujinx.Modules { internal static class Updater { - private const string GitHubApiURL = "https://api.github.com"; - private static readonly GithubReleasesJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private const string GitHubApiUrl = "https://api.github.com"; + private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); - private static readonly string HomeDir = AppDomain.CurrentDomain.BaseDirectory; - private static readonly string UpdateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update"); - private static readonly string UpdatePublishDir = Path.Combine(UpdateDir, "publish"); - private static readonly int ConnectionCount = 4; + private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory; + private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update"); + private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish"); + private static readonly int _connectionCount = 4; private static string _buildVer; private static string _platformExt; private static string _buildUrl; - private static long _buildSize; - private static bool _updateSuccessful; - private static bool _running; + private static long _buildSize; + private static bool _updateSuccessful; + private static bool _running; - private static readonly string[] WindowsDependencyDirs = Array.Empty(); + private static readonly string[] _windowsDependencyDirs = Array.Empty(); public static async Task BeginParse(Window mainWindow, bool showVersionUpToDate) { @@ -99,9 +99,9 @@ namespace Ryujinx.Modules { using HttpClient jsonClient = ConstructHttpClient(); - string buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest"; - string fetchedJson = await jsonClient.GetStringAsync(buildInfoURL); - var fetched = JsonHelper.Deserialize(fetchedJson, SerializerContext.GithubReleasesJsonResponse); + string buildInfoUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest"; + string fetchedJson = await jsonClient.GetStringAsync(buildInfoUrl); + var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse); _buildVer = fetched.Name; foreach (var asset in fetched.Assets) @@ -195,23 +195,21 @@ namespace Ryujinx.Modules } // Fetch build size information to learn chunk sizes. - using (HttpClient buildSizeClient = ConstructHttpClient()) + using HttpClient buildSizeClient = ConstructHttpClient(); + try { - try - { - buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0"); + buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0"); - HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead); + HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead); - _buildSize = message.Content.Headers.ContentRange.Length.Value; - } - catch (Exception ex) - { - Logger.Warning?.Print(LogClass.Application, ex.Message); - Logger.Warning?.Print(LogClass.Application, "Couldn't determine build size for update, using single-threaded updater"); + _buildSize = message.Content.Headers.ContentRange.Length.Value; + } + catch (Exception ex) + { + Logger.Warning?.Print(LogClass.Application, ex.Message); + Logger.Warning?.Print(LogClass.Application, "Couldn't determine build size for update, using single-threaded updater"); - _buildSize = -1; - } + _buildSize = -1; } Dispatcher.UIThread.Post(async () => @@ -248,23 +246,22 @@ namespace Ryujinx.Modules _updateSuccessful = false; // Empty update dir, although it shouldn't ever have anything inside it - if (Directory.Exists(UpdateDir)) + if (Directory.Exists(_updateDir)) { - Directory.Delete(UpdateDir, true); + Directory.Delete(_updateDir, true); } - Directory.CreateDirectory(UpdateDir); + Directory.CreateDirectory(_updateDir); - string updateFile = Path.Combine(UpdateDir, "update.bin"); + string updateFile = Path.Combine(_updateDir, "update.bin"); TaskDialog taskDialog = new() { - Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater], - SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading], - IconSource = new SymbolIconSource { Symbol = Symbol.Download }, - Buttons = { }, + Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater], + SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading], + IconSource = new SymbolIconSource { Symbol = Symbol.Download }, ShowProgressBar = true, - XamlRoot = parent + XamlRoot = parent, }; taskDialog.Opened += (s, e) => @@ -301,7 +298,7 @@ namespace Ryujinx.Modules if (OperatingSystem.IsMacOS()) { string baseBundlePath = Path.GetFullPath(Path.Combine(executableDirectory, "..", "..")); - string newBundlePath = Path.Combine(UpdateDir, "Ryujinx.app"); + string newBundlePath = Path.Combine(_updateDir, "Ryujinx.app"); string updaterScriptPath = Path.Combine(newBundlePath, "Contents", "Resources", "updater.sh"); string currentPid = Environment.ProcessId.ToString(); @@ -328,7 +325,7 @@ namespace Ryujinx.Modules ProcessStartInfo processStart = new(ryuName) { UseShellExecute = true, - WorkingDirectory = executableDirectory + WorkingDirectory = executableDirectory, }; foreach (string argument in CommandLineState.Arguments) @@ -347,22 +344,22 @@ namespace Ryujinx.Modules private static void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile) { // Multi-Threaded Updater - long chunkSize = _buildSize / ConnectionCount; - long remainderChunk = _buildSize % ConnectionCount; + long chunkSize = _buildSize / _connectionCount; + long remainderChunk = _buildSize % _connectionCount; - int completedRequests = 0; - int totalProgressPercentage = 0; - int[] progressPercentage = new int[ConnectionCount]; + int completedRequests = 0; + int totalProgressPercentage = 0; + int[] progressPercentage = new int[_connectionCount]; - List list = new(ConnectionCount); - List webClients = new(ConnectionCount); + List list = new(_connectionCount); + List webClients = new(_connectionCount); - for (int i = 0; i < ConnectionCount; i++) + for (int i = 0; i < _connectionCount; i++) { list.Add(Array.Empty()); } - for (int i = 0; i < ConnectionCount; i++) + for (int i = 0; i < _connectionCount; i++) { #pragma warning disable SYSLIB0014 // TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient. @@ -371,7 +368,7 @@ namespace Ryujinx.Modules webClients.Add(client); - if (i == ConnectionCount - 1) + if (i == _connectionCount - 1) { client.Headers.Add("Range", $"bytes={chunkSize * i}-{(chunkSize * (i + 1) - 1) + remainderChunk}"); } @@ -388,7 +385,7 @@ namespace Ryujinx.Modules Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage); Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage); - taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal); + taskDialog.SetProgressBarState(totalProgressPercentage / _connectionCount, TaskDialogProgressState.Normal); }; client.DownloadDataCompleted += (_, args) => @@ -407,10 +404,10 @@ namespace Ryujinx.Modules list[index] = args.Result; Interlocked.Increment(ref completedRequests); - if (Equals(completedRequests, ConnectionCount)) + if (Equals(completedRequests, _connectionCount)) { byte[] mergedFileBytes = new byte[_buildSize]; - for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++) + for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < _connectionCount; connectionIndex++) { Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length); destinationOffset += list[connectionIndex].Length; @@ -421,10 +418,9 @@ namespace Ryujinx.Modules // On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution. if (OperatingSystem.IsMacOS()) { - using (Process xattrProcess = Process.Start("xattr", new List { "-d", "com.apple.quarantine", updateFile })) - { - xattrProcess.WaitForExit(); - } + using Process xattrProcess = Process.Start("xattr", new List { "-d", "com.apple.quarantine", updateFile }); + + xattrProcess.WaitForExit(); } try @@ -437,8 +433,6 @@ namespace Ryujinx.Modules Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater."); DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile); - - return; } } }; @@ -470,31 +464,29 @@ namespace Ryujinx.Modules // We do not want to timeout while downloading client.Timeout = TimeSpan.FromDays(1); - using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result) - using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result) + using HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result; + using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result; + using Stream updateFileStream = File.Open(updateFile, FileMode.Create); + + long totalBytes = response.Content.Headers.ContentLength.Value; + long byteWritten = 0; + + byte[] buffer = new byte[32 * 1024]; + + while (true) { - using Stream updateFileStream = File.Open(updateFile, FileMode.Create); + int readSize = remoteFileStream.Read(buffer); - long totalBytes = response.Content.Headers.ContentLength.Value; - long byteWritten = 0; - - byte[] buffer = new byte[32 * 1024]; - - while (true) + if (readSize == 0) { - int readSize = remoteFileStream.Read(buffer); - - if (readSize == 0) - { - break; - } - - byteWritten += readSize; - - taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal); - - updateFileStream.Write(buffer, 0, readSize); + break; } + + byteWritten += readSize; + + taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal); + + updateFileStream.Write(buffer, 0, readSize); } InstallUpdate(taskDialog, updateFile); @@ -510,7 +502,7 @@ namespace Ryujinx.Modules { Thread worker = new(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile)) { - Name = "Updater.SingleThreadWorker" + Name = "Updater.SingleThreadWorker", }; worker.Start(); @@ -520,9 +512,9 @@ namespace Ryujinx.Modules [SupportedOSPlatform("macos")] private static void ExtractTarGzipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath) { - using Stream inStream = File.OpenRead(archivePath); + using Stream inStream = File.OpenRead(archivePath); using GZipInputStream gzipStream = new(inStream); - using TarInputStream tarStream = new(gzipStream, Encoding.ASCII); + using TarInputStream tarStream = new(gzipStream, Encoding.ASCII); TarEntry tarEntry; @@ -537,10 +529,8 @@ namespace Ryujinx.Modules Directory.CreateDirectory(Path.GetDirectoryName(outPath)); - using (FileStream outStream = File.OpenWrite(outPath)) - { - tarStream.CopyEntryContents(outStream); - } + using FileStream outStream = File.OpenWrite(outPath); + tarStream.CopyEntryContents(outStream); File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode); File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc)); @@ -559,24 +549,26 @@ namespace Ryujinx.Modules private static void ExtractZipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath) { - using Stream inStream = File.OpenRead(archivePath); - using ZipFile zipFile = new(inStream); + using Stream inStream = File.OpenRead(archivePath); + using ZipFile zipFile = new(inStream); double count = 0; foreach (ZipEntry zipEntry in zipFile) { count++; - if (zipEntry.IsDirectory) continue; + if (zipEntry.IsDirectory) + { + continue; + } string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name); Directory.CreateDirectory(Path.GetDirectoryName(outPath)); - using (Stream zipStream = zipFile.GetInputStream(zipEntry)) - using (FileStream outStream = File.OpenWrite(outPath)) - { - zipStream.CopyTo(outStream); - } + using Stream zipStream = zipFile.GetInputStream(zipEntry); + using FileStream outStream = File.OpenWrite(outPath); + + zipStream.CopyTo(outStream); File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc)); @@ -597,11 +589,11 @@ namespace Ryujinx.Modules { if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) { - ExtractTarGzipFile(taskDialog, updateFile, UpdateDir); + ExtractTarGzipFile(taskDialog, updateFile, _updateDir); } else if (OperatingSystem.IsWindows()) { - ExtractZipFile(taskDialog, updateFile, UpdateDir); + ExtractZipFile(taskDialog, updateFile, _updateDir); } else { @@ -648,10 +640,10 @@ namespace Ryujinx.Modules taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal); }); - MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog); + MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog); }); - Directory.Delete(UpdateDir, true); + Directory.Delete(_updateDir, true); } _updateSuccessful = true; @@ -738,15 +730,15 @@ namespace Ryujinx.Modules // NOTE: This method should always reflect the latest build layout. private static IEnumerable EnumerateFilesToDelete() { - var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir. + var files = Directory.EnumerateFiles(_homeDir); // All files directly in base dir. // Determine and exclude user files only when the updater is running, not when cleaning old files if (_running && !OperatingSystem.IsMacOS()) { // Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list. - var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName); - var newFiles = Directory.EnumerateFiles(UpdatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName); - var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(HomeDir, filename)); + var oldFiles = Directory.EnumerateFiles(_homeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName); + var newFiles = Directory.EnumerateFiles(_updatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName); + var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(_homeDir, filename)); // Remove user files from the paths in files. files = files.Except(userFiles); @@ -754,9 +746,9 @@ namespace Ryujinx.Modules if (OperatingSystem.IsWindows()) { - foreach (string dir in WindowsDependencyDirs) + foreach (string dir in _windowsDependencyDirs) { - string dirPath = Path.Combine(HomeDir, dir); + string dirPath = Path.Combine(_homeDir, dir); if (Directory.Exists(dirPath)) { files = files.Concat(Directory.EnumerateFiles(dirPath, "*", SearchOption.AllDirectories)); @@ -798,10 +790,10 @@ namespace Ryujinx.Modules public static void CleanupUpdate() { - foreach (string file in Directory.GetFiles(HomeDir, "*.ryuold", SearchOption.AllDirectories)) + foreach (string file in Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories)) { File.Delete(file); } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/Program.cs b/src/Ryujinx.Ava/Program.cs index 0629e6062..5241f91f8 100644 --- a/src/Ryujinx.Ava/Program.cs +++ b/src/Ryujinx.Ava/Program.cs @@ -22,16 +22,16 @@ namespace Ryujinx.Ava { internal partial class Program { - public static double WindowScaleFactor { get; set; } + public static double WindowScaleFactor { get; set; } public static double DesktopScaleFactor { get; set; } = 1.0; - public static string Version { get; private set; } - public static string ConfigurationPath { get; private set; } - public static bool PreviewerDetached { get; private set; } + public static string Version { get; private set; } + public static string ConfigurationPath { get; private set; } + public static bool PreviewerDetached { get; private set; } [LibraryImport("user32.dll", SetLastError = true)] public static partial int MessageBoxA(IntPtr hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type); - private const uint MB_ICONWARNING = 0x30; + private const uint MbIconwarning = 0x30; public static void Main(string[] args) { @@ -39,7 +39,7 @@ namespace Ryujinx.Ava if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134)) { - _ = MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MB_ICONWARNING); + _ = MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MbIconwarning); } PreviewerDetached = true; @@ -58,15 +58,15 @@ namespace Ryujinx.Ava .With(new X11PlatformOptions { EnableMultiTouch = true, - EnableIme = true, - UseEGL = false, - UseGpu = true + EnableIme = true, + UseEGL = false, + UseGpu = true, }) .With(new Win32PlatformOptions { - EnableMultitouch = true, - UseWgl = false, - AllowEglInitialization = false, + EnableMultitouch = true, + UseWgl = false, + AllowEglInitialization = false, CompositionBackdropCornerRadius = 8.0f, }) .UseSkia(); @@ -84,7 +84,7 @@ namespace Ryujinx.Ava // Hook unhandled exception and process exit events. AppDomain.CurrentDomain.UnhandledException += (sender, e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating); - AppDomain.CurrentDomain.ProcessExit += (sender, e) => Exit(); + AppDomain.CurrentDomain.ProcessExit += (sender, e) => Exit(); // Setup base data directory. AppDataManager.Initialize(CommandLineState.BaseDirPathArg); @@ -130,7 +130,7 @@ namespace Ryujinx.Ava public static void ReloadConfig() { - string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); + string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json"); // Now load the configuration as the other subsystems are now registered @@ -192,7 +192,7 @@ namespace Ryujinx.Ava "never" => HideCursorMode.Never, "onidle" => HideCursorMode.OnIdle, "always" => HideCursorMode.Always, - _ => ConfigurationState.Instance.HideCursor.Value + _ => ConfigurationState.Instance.HideCursor.Value, }; } } @@ -238,4 +238,4 @@ namespace Ryujinx.Ava Logger.Shutdown(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs b/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs index c87308cfb..d35f44bf5 100644 --- a/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs +++ b/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs @@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Applet LocaleManager.Instance[LocaleKeys.SettingsButtonClose], (int)Symbol.Important, deferEvent, - async (window) => + async window => { if (opened) { @@ -112,7 +112,7 @@ namespace Ryujinx.Ava.UI.Applet { try { - var response = await SwkbdAppletDialog.ShowInputDialog(_parent, LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args); + var response = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args); if (response.Result == UserResult.Ok) { @@ -142,10 +142,7 @@ namespace Ryujinx.Ava.UI.Applet public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value) { device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value); - if (_parent.ViewModel.AppHost != null) - { - _parent.ViewModel.AppHost.Stop(); - } + _parent.ViewModel.AppHost?.Stop(); } public bool DisplayErrorAppletDialog(string title, string message, string[] buttons) @@ -162,7 +159,7 @@ namespace Ryujinx.Ava.UI.Applet { Title = title, WindowStartupLocation = WindowStartupLocation.CenterScreen, - Width = 400 + Width = 400, }; object response = await msgDialog.Run(); @@ -194,4 +191,4 @@ namespace Ryujinx.Ava.UI.Applet return new AvaloniaDynamicTextInputHandler(_parent); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs b/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs index 2dd65e362..2fa4d54f8 100644 --- a/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs +++ b/src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs @@ -3,13 +3,11 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Threading; using Ryujinx.Ava.Input; -using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.HLE.Ui; using System; using System.Threading; - using HidKey = Ryujinx.Common.Configuration.Hid.Key; namespace Ryujinx.Ava.UI.Applet @@ -17,7 +15,7 @@ namespace Ryujinx.Ava.UI.Applet class AvaloniaDynamicTextInputHandler : IDynamicTextInputHandler { private MainWindow _parent; - private OffscreenTextBox _hiddenTextBox; + private readonly OffscreenTextBox _hiddenTextBox; private bool _canProcessInput; private IDisposable _textChangedSubscription; private IDisposable _selectionStartChangedSubscription; @@ -76,7 +74,7 @@ namespace Ryujinx.Ava.UI.Applet return; } - e.RoutedEvent = _hiddenTextBox.GetKeyUpRoutedEvent(); + e.RoutedEvent = OffscreenTextBox.GetKeyUpRoutedEvent(); Dispatcher.UIThread.InvokeAsync(() => { @@ -96,7 +94,7 @@ namespace Ryujinx.Ava.UI.Applet return; } - e.RoutedEvent = _hiddenTextBox.GetKeyUpRoutedEvent(); + e.RoutedEvent = OffscreenTextBox.GetKeyUpRoutedEvent(); Dispatcher.UIThread.InvokeAsync(() => { diff --git a/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs b/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs index 77c7a2d2c..3cf273347 100644 --- a/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs +++ b/src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs @@ -9,7 +9,7 @@ namespace Ryujinx.Ava.UI.Applet { public AvaloniaHostUiTheme(MainWindow parent) { - FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000, 0) ? "Segoe UI Variable" : parent.FontFamily.Name; + FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000) ? "Segoe UI Variable" : parent.FontFamily.Name; DefaultBackgroundColor = BrushToThemeColor(parent.Background); DefaultForegroundColor = BrushToThemeColor(parent.Foreground); DefaultBorderColor = BrushToThemeColor(parent.BorderBrush); @@ -25,7 +25,7 @@ namespace Ryujinx.Ava.UI.Applet public ThemeColor SelectionBackgroundColor { get; } public ThemeColor SelectionForegroundColor { get; } - private ThemeColor BrushToThemeColor(IBrush brush) + private static ThemeColor BrushToThemeColor(IBrush brush) { if (brush is SolidColorBrush solidColor) { @@ -34,10 +34,8 @@ namespace Ryujinx.Ava.UI.Applet (float)solidColor.Color.G / 255, (float)solidColor.Color.B / 255); } - else - { - return new ThemeColor(); - } + + return new ThemeColor(); } } } diff --git a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs index 4134797ba..b77cc4020 100644 --- a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs @@ -1,10 +1,12 @@ -using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Threading; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Windows; using System.Threading.Tasks; +#if DEBUG +using Avalonia; +#endif namespace Ryujinx.Ava.UI.Applet { @@ -77,4 +79,4 @@ namespace Ryujinx.Ava.UI.Applet return _buttonResponse; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs index 81258b448..210fc9a2b 100644 --- a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs +++ b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs @@ -1,13 +1,10 @@ -using Avalonia; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; -using FluentAvalonia.Core; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Windows; using Ryujinx.HLE.HOS.Applets; using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard; using System; @@ -22,7 +19,7 @@ namespace Ryujinx.Ava.UI.Controls private Predicate _checkInput = _ => true; private int _inputMax; private int _inputMin; - private string _placeholder; + private readonly string _placeholder; private ContentDialog _host; @@ -57,13 +54,13 @@ namespace Ryujinx.Ava.UI.Controls public string MainText { get; set; } = ""; public string SecondaryText { get; set; } = ""; - public static async Task<(UserResult Result, string Input)> ShowInputDialog(StyleableWindow window, string title, SoftwareKeyboardUiArgs args) + public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUiArgs args) { - ContentDialog contentDialog = new ContentDialog(); + ContentDialog contentDialog = new(); UserResult result = UserResult.Cancel; - SwkbdAppletDialog content = new SwkbdAppletDialog(args.HeaderText, args.SubtitleText, args.GuideText, args.InitialText); + SwkbdAppletDialog content = new(args.HeaderText, args.SubtitleText, args.GuideText, args.InitialText); string input = string.Empty; @@ -78,15 +75,16 @@ namespace Ryujinx.Ava.UI.Controls contentDialog.CloseButtonText = LocaleManager.Instance[LocaleKeys.InputDialogCancel]; contentDialog.Content = content; - TypedEventHandler handler = (sender, eventArgs) => + void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs) { if (eventArgs.Result == ContentDialogResult.Primary) { result = UserResult.Ok; input = content.Input.Text; } - }; - contentDialog.Closed += handler; + } + + contentDialog.Closed += Handler; await ContentDialogHelper.ShowAsync(contentDialog); @@ -182,4 +180,4 @@ namespace Ryujinx.Ava.UI.Controls } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs index b01c7c5e3..77b4f5207 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs @@ -18,7 +18,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using Path = System.IO.Path; -using UserId = LibHac.Fs.UserId; namespace Ryujinx.Ava.UI.Controls { @@ -53,7 +52,7 @@ namespace Ryujinx.Ava.UI.Controls public void OpenUserSaveDirectory_Click(object sender, RoutedEventArgs args) { - if ((sender as MenuItem)?.DataContext is MainWindowViewModel viewModel) + if (sender is MenuItem { DataContext: MainWindowViewModel viewModel }) { OpenSaveDirectory(viewModel, SaveDataType.Account, userId: new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)); } @@ -334,4 +333,4 @@ namespace Ryujinx.Ava.UI.Controls } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs index c30c75b36..efdc9ab02 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Ava.UI.Controls public event EventHandler ApplicationOpened { - add { AddHandler(ApplicationOpenedEvent, value); } + add { AddHandler(ApplicationOpenedEvent, value); } remove { RemoveHandler(ApplicationOpenedEvent, value); } } diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs index 1a07c4251..1646fc1b1 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Ava.UI.Controls public event EventHandler ApplicationOpened { - add { AddHandler(ApplicationOpenedEvent, value); } + add { AddHandler(ApplicationOpenedEvent, value); } remove { RemoveHandler(ApplicationOpenedEvent, value); } } diff --git a/src/Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs b/src/Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs index 1b857fae4..a32c052bf 100644 --- a/src/Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs @@ -2,7 +2,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Styling; using Avalonia.Threading; -using FluentAvalonia.Core; using FluentAvalonia.UI.Controls; using LibHac; using LibHac.Common; @@ -10,7 +9,6 @@ using LibHac.Fs; using LibHac.Fs.Shim; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.Views.User; using Ryujinx.HLE.FileSystem; @@ -19,6 +17,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using UserId = Ryujinx.HLE.HOS.Services.Account.Acc.UserId; using UserProfile = Ryujinx.Ava.UI.Models.UserProfile; namespace Ryujinx.Ava.UI.Controls @@ -56,7 +55,7 @@ namespace Ryujinx.Ava.UI.Controls InitializeComponent(); } - public void GoBack(object parameter = null) + public void GoBack() { if (ContentFrame.BackStack.Count > 0) { @@ -75,14 +74,14 @@ namespace Ryujinx.Ava.UI.Controls VirtualFileSystem ownerVirtualFileSystem, HorizonClient ownerHorizonClient) { var content = new NavigationDialogHost(ownerAccountManager, ownerContentManager, ownerVirtualFileSystem, ownerHorizonClient); - ContentDialog contentDialog = new ContentDialog + ContentDialog contentDialog = new() { Title = LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle], PrimaryButtonText = "", SecondaryButtonText = "", CloseButtonText = "", Content = content, - Padding = new Thickness(0) + Padding = new Thickness(0), }; contentDialog.Closed += (sender, args) => @@ -125,7 +124,7 @@ namespace Ryujinx.Ava.UI.Controls Span saveDataInfo = stackalloc SaveDataInfo[10]; - HashSet lostAccounts = new(); + HashSet lostAccounts = new(); while (true) { @@ -139,15 +138,15 @@ namespace Ryujinx.Ava.UI.Controls for (int i = 0; i < readCount; i++) { var save = saveDataInfo[i]; - var id = new HLE.HOS.Services.Account.Acc.UserId((long)save.UserId.Id.Low, (long)save.UserId.Id.High); - if (ViewModel.Profiles.Cast().FirstOrDefault( x=> x.UserId == id) == null) + var id = new UserId((long)save.UserId.Id.Low, (long)save.UserId.Id.High); + if (ViewModel.Profiles.Cast().FirstOrDefault(x => x.UserId == id) == null) { lostAccounts.Add(id); } } } - foreach(var account in lostAccounts) + foreach (var account in lostAccounts) { ViewModel.LostProfiles.Add(new UserProfile(new HLE.HOS.Services.Account.Acc.UserProfile(account, "", null), this)); } @@ -166,7 +165,7 @@ namespace Ryujinx.Ava.UI.Controls if (profile == null) { - async void Action() + static async void Action() { await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUserProfileDeletionWarningMessage]); } @@ -215,4 +214,4 @@ namespace Ryujinx.Ava.UI.Controls Navigate(typeof(UserSaveManagerView), (this, AccountManager, HorizonClient, VirtualFileSystem)); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs b/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs index 80a437e33..7ad1ee332 100644 --- a/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs @@ -28,4 +28,4 @@ namespace Ryujinx.Ava.UI.Controls InitializeComponent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs b/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs index ebf5c16ec..cd63a99b0 100644 --- a/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs +++ b/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs @@ -13,4 +13,4 @@ namespace Ryujinx.Ava.UI.Helpers RoutedEvent = routedEvent; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs index 133f8dbc9..42bd8d5a8 100644 --- a/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs @@ -33,4 +33,4 @@ namespace Ryujinx.Ava.UI.Helpers throw new NotSupportedException(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs index 6730b5711..7e8ba7342 100644 --- a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs +++ b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers IsAssigned = isAssigned; } } - + public ToggleButton ToggledButton { get; set; } private bool _isWaitingForInput; diff --git a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs index 045d508c6..7dab57b88 100644 --- a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs +++ b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Layout; using Avalonia.Media; using Avalonia.Threading; using FluentAvalonia.Core; @@ -32,18 +33,17 @@ namespace Ryujinx.Ava.UI.Helpers ContentDialog contentDialog = new() { - Title = title, - PrimaryButtonText = primaryButton, + Title = title, + PrimaryButtonText = primaryButton, SecondaryButtonText = secondaryButton, - CloseButtonText = closeButton, - Content = content + CloseButtonText = closeButton, + Content = content, + PrimaryButtonCommand = MiniCommand.Create(() => + { + result = primaryButtonResult; + }), }; - contentDialog.PrimaryButtonCommand = MiniCommand.Create(() => - { - result = primaryButtonResult; - }); - contentDialog.SecondaryButtonCommand = MiniCommand.Create(() => { result = UserResult.No; @@ -96,7 +96,6 @@ namespace Ryujinx.Ava.UI.Helpers Func doWhileDeferred = null) { bool startedDeferring = false; - UserResult result = UserResult.None; return await ShowTextDialog( title, @@ -123,8 +122,6 @@ namespace Ryujinx.Ava.UI.Helpers var deferral = args.GetDeferral(); - result = primaryButton == LocaleManager.Instance[LocaleKeys.InputDialogYes] ? UserResult.Yes : UserResult.Ok; - sender.PrimaryButtonClick -= DeferClose; _ = Task.Run(() => @@ -150,18 +147,18 @@ namespace Ryujinx.Ava.UI.Helpers { Grid content = new() { - RowDefinitions = new RowDefinitions() { new RowDefinition(), new RowDefinition() }, - ColumnDefinitions = new ColumnDefinitions() { new ColumnDefinition(GridLength.Auto), new ColumnDefinition() }, + RowDefinitions = new RowDefinitions { new(), new() }, + ColumnDefinitions = new ColumnDefinitions { new(GridLength.Auto), new() }, - MinHeight = 80 + MinHeight = 80, }; SymbolIcon icon = new() { - Symbol = (Symbol)symbol, - Margin = new Thickness(10), - FontSize = 40, - VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center + Symbol = (Symbol)symbol, + Margin = new Thickness(10), + FontSize = 40, + VerticalAlignment = VerticalAlignment.Center, }; Grid.SetColumn(icon, 0); @@ -170,18 +167,18 @@ namespace Ryujinx.Ava.UI.Helpers TextBlock primaryLabel = new() { - Text = primaryText, - Margin = new Thickness(5), + Text = primaryText, + Margin = new Thickness(5), TextWrapping = TextWrapping.Wrap, - MaxWidth = 450 + MaxWidth = 450, }; TextBlock secondaryLabel = new() { - Text = secondaryText, - Margin = new Thickness(5), + Text = secondaryText, + Margin = new Thickness(5), TextWrapping = TextWrapping.Wrap, - MaxWidth = 450 + MaxWidth = 450, }; Grid.SetColumn(primaryLabel, 1); @@ -318,14 +315,14 @@ namespace Ryujinx.Ava.UI.Helpers Window parent = GetMainWindow(); - if (parent != null && parent.IsActive && (parent as MainWindow).ViewModel.IsGameRunning) + if (parent is { IsActive: true } and MainWindow window && window.ViewModel.IsGameRunning) { contentDialogOverlayWindow = new() { - Height = parent.Bounds.Height, - Width = parent.Bounds.Width, - Position = parent.PointToScreen(new Point()), - ShowInTaskbar = false + Height = parent.Bounds.Height, + Width = parent.Bounds.Width, + Position = parent.PointToScreen(new Point()), + ShowInTaskbar = false, }; parent.PositionChanged += OverlayOnPositionChanged; @@ -389,7 +386,7 @@ namespace Ryujinx.Ava.UI.Helpers private static Window GetMainWindow() { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al) + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al) { foreach (Window item in al.Windows) { @@ -403,4 +400,4 @@ namespace Ryujinx.Ava.UI.Helpers return null; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs index 3d6c9c018..4e4b971eb 100644 --- a/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs @@ -1,5 +1,6 @@ using Avalonia.Data; using Avalonia.Markup.Xaml; +using Avalonia.Markup.Xaml.MarkupExtensions; using FluentAvalonia.UI.Controls; using System; using System.Collections.Generic; @@ -8,13 +9,13 @@ namespace Ryujinx.Ava.UI.Helpers { public class GlyphValueConverter : MarkupExtension { - private string _key; + private readonly string _key; - private static Dictionary _glyphs = new Dictionary + private static readonly Dictionary _glyphs = new() { - { Glyph.List, char.ConvertFromUtf32((int)Symbol.List).ToString() }, - { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll).ToString() }, - { Glyph.Chip, char.ConvertFromUtf32(59748).ToString() } + { Glyph.List, char.ConvertFromUtf32((int)Symbol.List) }, + { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll) }, + { Glyph.Chip, char.ConvertFromUtf32(59748) }, }; public GlyphValueConverter(string key) @@ -37,13 +38,13 @@ namespace Ryujinx.Ava.UI.Helpers public override object ProvideValue(IServiceProvider serviceProvider) { - Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension binding = new($"[{_key}]") + ReflectionBindingExtension binding = new($"[{_key}]") { Mode = BindingMode.OneWay, - Source = this + Source = this, }; return binding.ProvideValue(serviceProvider); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs b/src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs index f1fad1576..4ae903b49 100644 --- a/src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs +++ b/src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs @@ -49,4 +49,4 @@ namespace Ryujinx.Ava.UI.Helpers } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs index 8d5c2815a..028ed6bf4 100644 --- a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs @@ -43,4 +43,4 @@ namespace Ryujinx.Ava.UI.Helpers return key; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs index 7a29cc198..dc8e3f945 100644 --- a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs @@ -1,15 +1,17 @@ +using Avalonia.Logging; using Avalonia.Utilities; +using Ryujinx.Common.Logging; using System; using System.Text; namespace Ryujinx.Ava.UI.Helpers { - using AvaLogger = Avalonia.Logging.Logger; - using AvaLogLevel = Avalonia.Logging.LogEventLevel; - using RyuLogClass = Ryujinx.Common.Logging.LogClass; - using RyuLogger = Ryujinx.Common.Logging.Logger; + using AvaLogger = Avalonia.Logging.Logger; + using AvaLogLevel = LogEventLevel; + using RyuLogClass = LogClass; + using RyuLogger = Ryujinx.Common.Logging.Logger; - internal class LoggerAdapter : Avalonia.Logging.ILogSink + internal class LoggerAdapter : ILogSink { public static void Register() { @@ -20,13 +22,13 @@ namespace Ryujinx.Ava.UI.Helpers { return level switch { - AvaLogLevel.Verbose => RyuLogger.Debug, - AvaLogLevel.Debug => RyuLogger.Debug, + AvaLogLevel.Verbose => RyuLogger.Debug, + AvaLogLevel.Debug => RyuLogger.Debug, AvaLogLevel.Information => RyuLogger.Debug, - AvaLogLevel.Warning => RyuLogger.Debug, - AvaLogLevel.Error => RyuLogger.Error, - AvaLogLevel.Fatal => RyuLogger.Error, - _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) + AvaLogLevel.Warning => RyuLogger.Debug, + AvaLogLevel.Error => RyuLogger.Error, + AvaLogLevel.Fatal => RyuLogger.Error, + _ => throw new ArgumentOutOfRangeException(nameof(level), level, null), }; } @@ -45,7 +47,7 @@ namespace Ryujinx.Ava.UI.Helpers GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0 })); } - public void Log(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + public void Log(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1) { GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0, propertyValue1 })); } @@ -112,4 +114,4 @@ namespace Ryujinx.Ava.UI.Helpers return result.ToString(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs b/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs index 305182c92..864f53b8a 100644 --- a/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs +++ b/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Ava.UI.Helpers { private readonly Action _callback; private bool _busy; - private Func _asyncCallback; + private readonly Func _asyncCallback; public MiniCommand(Action callback) { @@ -68,4 +68,4 @@ namespace Ryujinx.Ava.UI.Helpers public abstract void Execute(object parameter); public abstract event EventHandler CanExecuteChanged; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs b/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs index f207c5fb0..a11fb5267 100644 --- a/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs +++ b/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs @@ -12,12 +12,12 @@ namespace Ryujinx.Ava.UI.Helpers { public static class NotificationHelper { - private const int MaxNotifications = 4; + private const int MaxNotifications = 4; private const int NotificationDelayInMs = 5000; private static WindowNotificationManager _notificationManager; - private static readonly BlockingCollection _notifications = new(); + private static readonly BlockingCollection _notifications = new(); public static void SetNotificationManager(Window host) { @@ -25,7 +25,7 @@ namespace Ryujinx.Ava.UI.Helpers { Position = NotificationPosition.BottomRight, MaxItems = MaxNotifications, - Margin = new Thickness(0, 0, 15, 40) + Margin = new Thickness(0, 0, 15, 40), }; var maybeAsyncWorkQueue = new Lazy>( @@ -67,4 +67,4 @@ namespace Ryujinx.Ava.UI.Helpers Show(LocaleManager.Instance[LocaleKeys.DialogErrorTitle], $"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}", NotificationType.Error); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/NullableDateTimeConverter.cs b/src/Ryujinx.Ava/UI/Helpers/NullableDateTimeConverter.cs index 1d862de01..e91937612 100644 --- a/src/Ryujinx.Ava/UI/Helpers/NullableDateTimeConverter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/NullableDateTimeConverter.cs @@ -35,4 +35,4 @@ namespace Ryujinx.Ava.UI.Helpers return _instance; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs b/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs index 785e785cd..670d3b361 100644 --- a/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs +++ b/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs @@ -6,12 +6,12 @@ namespace Ryujinx.Ava.UI.Helpers { public class OffscreenTextBox : TextBox { - public RoutedEvent GetKeyDownRoutedEvent() + public static RoutedEvent GetKeyDownRoutedEvent() { return KeyDownEvent; } - public RoutedEvent GetKeyUpRoutedEvent() + public static RoutedEvent GetKeyUpRoutedEvent() { return KeyUpEvent; } @@ -28,13 +28,13 @@ namespace Ryujinx.Ava.UI.Helpers public void SendText(string text) { - OnTextInput(new TextInputEventArgs() + OnTextInput(new TextInputEventArgs { Text = text, Device = KeyboardDevice.Instance, Source = this, - RoutedEvent = TextInputEvent + RoutedEvent = TextInputEvent, }); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs b/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs index 4ed629ff1..afd2958c6 100644 --- a/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs +++ b/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs @@ -1,5 +1,4 @@ using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Windows; using Ryujinx.Ui.Common; using Ryujinx.Ui.Common.Helper; using System.Threading.Tasks; @@ -24,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers UserError.FirmwareParsingFailed => LocaleManager.Instance[LocaleKeys.UserErrorFirmwareParsingFailed], UserError.ApplicationNotFound => LocaleManager.Instance[LocaleKeys.UserErrorApplicationNotFound], UserError.Unknown => LocaleManager.Instance[LocaleKeys.UserErrorUnknown], - _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefined] + _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefined], }; } @@ -37,7 +36,7 @@ namespace Ryujinx.Ava.UI.Helpers UserError.FirmwareParsingFailed => LocaleManager.Instance[LocaleKeys.UserErrorFirmwareParsingFailedDescription], UserError.ApplicationNotFound => LocaleManager.Instance[LocaleKeys.UserErrorApplicationNotFoundDescription], UserError.Unknown => LocaleManager.Instance[LocaleKeys.UserErrorUnknownDescription], - _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefinedDescription] + _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefinedDescription], }; } @@ -48,7 +47,7 @@ namespace Ryujinx.Ava.UI.Helpers UserError.NoKeys or UserError.NoFirmware or UserError.FirmwareParsingFailed => true, - _ => false + _ => false, }; } @@ -63,11 +62,11 @@ namespace Ryujinx.Ava.UI.Helpers { UserError.NoKeys => SetupGuideUrl + "#initial-setup---placement-of-prodkeys", UserError.NoFirmware => SetupGuideUrl + "#initial-setup-continued---installation-of-firmware", - _ => SetupGuideUrl + _ => SetupGuideUrl, }; } - public static async Task ShowUserErrorDialog(UserError error, StyleableWindow owner) + public static async Task ShowUserErrorDialog(UserError error) { string errorCode = GetErrorCode(error); @@ -88,4 +87,4 @@ namespace Ryujinx.Ava.UI.Helpers } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/UserResult.cs b/src/Ryujinx.Ava/UI/Helpers/UserResult.cs index 57802804f..2fcd35ae4 100644 --- a/src/Ryujinx.Ava/UI/Helpers/UserResult.cs +++ b/src/Ryujinx.Ava/UI/Helpers/UserResult.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Helpers Cancel, None, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs b/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs index 03d3a49f3..ca55d0399 100644 --- a/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs +++ b/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -10,46 +11,47 @@ namespace Ryujinx.Ava.UI.Helpers [Flags] public enum ClassStyles : uint { - CS_CLASSDC = 0x40, - CS_OWNDC = 0x20, + CsClassdc = 0x40, + CsOwndc = 0x20, } [Flags] public enum WindowStyles : uint { - WS_CHILD = 0x40000000 + WsChild = 0x40000000, } public enum Cursors : uint { - IDC_ARROW = 32512 + IdcArrow = 32512, } + [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] public enum WindowsMessages : uint { - MOUSEMOVE = 0x0200, - LBUTTONDOWN = 0x0201, - LBUTTONUP = 0x0202, - LBUTTONDBLCLK = 0x0203, - RBUTTONDOWN = 0x0204, - RBUTTONUP = 0x0205, - RBUTTONDBLCLK = 0x0206, - MBUTTONDOWN = 0x0207, - MBUTTONUP = 0x0208, - MBUTTONDBLCLK = 0x0209, - MOUSEWHEEL = 0x020A, - XBUTTONDOWN = 0x020B, - XBUTTONUP = 0x020C, - XBUTTONDBLCLK = 0x020D, - MOUSEHWHEEL = 0x020E, - MOUSELAST = 0x020E + Mousemove = 0x0200, + Lbuttondown = 0x0201, + Lbuttonup = 0x0202, + Lbuttondblclk = 0x0203, + Rbuttondown = 0x0204, + Rbuttonup = 0x0205, + Rbuttondblclk = 0x0206, + Mbuttondown = 0x0207, + Mbuttonup = 0x0208, + Mbuttondblclk = 0x0209, + Mousewheel = 0x020A, + Xbuttondown = 0x020B, + Xbuttonup = 0x020C, + Xbuttondblclk = 0x020D, + Mousehwheel = 0x020E, + Mouselast = 0x020E, } [UnmanagedFunctionPointer(CallingConvention.Winapi)] internal delegate IntPtr WindowProc(IntPtr hWnd, WindowsMessages msg, IntPtr wParam, IntPtr lParam); [StructLayout(LayoutKind.Sequential)] - public struct WNDCLASSEX + public struct WndClassEx { public int cbSize; public ClassStyles style; @@ -64,9 +66,9 @@ namespace Ryujinx.Ava.UI.Helpers public IntPtr lpszClassName; public IntPtr hIconSm; - public WNDCLASSEX() + public WndClassEx() { - cbSize = Marshal.SizeOf(); + cbSize = Marshal.SizeOf(); } } @@ -77,17 +79,17 @@ namespace Ryujinx.Ava.UI.Helpers public static IntPtr CreateArrowCursor() { - return LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IDC_ARROW); + return LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IdcArrow); } [LibraryImport("user32.dll")] public static partial IntPtr SetCursor(IntPtr handle); [LibraryImport("user32.dll")] - public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte[] pvANDPlane, byte[] pvXORPlane); + public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte[] pvAndPlane, byte[] pvXorPlane); [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")] - public static partial ushort RegisterClassEx(ref WNDCLASSEX param); + public static partial ushort RegisterClassEx(ref WndClassEx param); [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "UnregisterClassW")] public static partial short UnregisterClass([MarshalAs(UnmanagedType.LPWStr)] string lpClassName, IntPtr instance); diff --git a/src/Ryujinx.Ava/UI/Models/CheatModel.cs b/src/Ryujinx.Ava/UI/Models/CheatModel.cs index a7507add9..4434c09f4 100644 --- a/src/Ryujinx.Ava/UI/Models/CheatModel.cs +++ b/src/Ryujinx.Ava/UI/Models/CheatModel.cs @@ -11,8 +11,8 @@ namespace Ryujinx.Ava.UI.Models public CheatModel(string name, string buildId, bool isEnabled) { - Name = name; - BuildId = buildId; + Name = name; + BuildId = buildId; IsEnabled = isEnabled; } @@ -35,6 +35,6 @@ namespace Ryujinx.Ava.UI.Models public string Name { get; } - public string CleanName => Name.Substring(1, Name.Length - 8); + public string CleanName => Name[1..^7]; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/CheatsList.cs b/src/Ryujinx.Ava/UI/Models/CheatsList.cs index e674f4eb7..1cb0480c7 100644 --- a/src/Ryujinx.Ava/UI/Models/CheatsList.cs +++ b/src/Ryujinx.Ava/UI/Models/CheatsList.cs @@ -10,13 +10,13 @@ namespace Ryujinx.Ava.UI.Models public CheatsList(string buildId, string path) { BuildId = buildId; - Path = path; + Path = path; CollectionChanged += CheatsList_CollectionChanged; } public string BuildId { get; } - public string Path { get; } + public string Path { get; } public bool IsEnabled { @@ -48,4 +48,4 @@ namespace Ryujinx.Ava.UI.Models OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled))); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/DeviceType.cs b/src/Ryujinx.Ava/UI/Models/DeviceType.cs index fa2e620cc..bb4fc3b30 100644 --- a/src/Ryujinx.Ava/UI/Models/DeviceType.cs +++ b/src/Ryujinx.Ava/UI/Models/DeviceType.cs @@ -4,6 +4,6 @@ namespace Ryujinx.Ava.UI.Models { None, Keyboard, - Controller + Controller, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/DownloadableContentModel.cs b/src/Ryujinx.Ava/UI/Models/DownloadableContentModel.cs index b2ad0d31d..fedb3527b 100644 --- a/src/Ryujinx.Ava/UI/Models/DownloadableContentModel.cs +++ b/src/Ryujinx.Ava/UI/Models/DownloadableContentModel.cs @@ -18,18 +18,18 @@ namespace Ryujinx.Ava.UI.Models } } - public string TitleId { get; } + public string TitleId { get; } public string ContainerPath { get; } - public string FullPath { get; } + public string FullPath { get; } public string FileName => Path.GetFileName(ContainerPath); public DownloadableContentModel(string titleId, string containerPath, string fullPath, bool enabled) { - TitleId = titleId; + TitleId = titleId; ContainerPath = containerPath; - FullPath = fullPath; - Enabled = enabled; + FullPath = fullPath; + Enabled = enabled; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs b/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs index 3627ada9a..8a4346556 100644 --- a/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs +++ b/src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs @@ -29,4 +29,4 @@ namespace Ryujinx.Ava.UI.Models.Generic return (IsAscending ? 1 : -1) * DateTime.Compare(bValue.Value, aValue.Value); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs b/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs index 2acd716ba..f1352c6d8 100644 --- a/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs +++ b/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs @@ -7,16 +7,16 @@ using System; namespace Ryujinx.Ava.UI.Models { - internal class InputConfiguration : BaseModel + internal class InputConfiguration : BaseModel { private float _deadzoneRight; private float _triggerThreshold; private float _deadzoneLeft; private double _gyroDeadzone; private int _sensitivity; - private bool enableMotion; - private float weakRumble; - private float strongRumble; + private bool _enableMotion; + private float _weakRumble; + private float _strongRumble; private float _rangeLeft; private float _rangeRight; @@ -37,17 +37,17 @@ namespace Ryujinx.Ava.UI.Models /// public PlayerIndex PlayerIndex { get; set; } - public Stick LeftJoystick { get; set; } + public TStick LeftJoystick { get; set; } public bool LeftInvertStickX { get; set; } public bool LeftInvertStickY { get; set; } public bool RightRotate90 { get; set; } - public Key LeftControllerStickButton { get; set; } + public TKey LeftControllerStickButton { get; set; } - public Stick RightJoystick { get; set; } + public TStick RightJoystick { get; set; } public bool RightInvertStickX { get; set; } public bool RightInvertStickY { get; set; } public bool LeftRotate90 { get; set; } - public Key RightControllerStickButton { get; set; } + public TKey RightControllerStickButton { get; set; } public float DeadzoneLeft { @@ -106,38 +106,37 @@ namespace Ryujinx.Ava.UI.Models public MotionInputBackendType MotionBackend { get; set; } - public Key ButtonMinus { get; set; } - public Key ButtonL { get; set; } - public Key ButtonZl { get; set; } - public Key LeftButtonSl { get; set; } - public Key LeftButtonSr { get; set; } - public Key DpadUp { get; set; } - public Key DpadDown { get; set; } - public Key DpadLeft { get; set; } - public Key DpadRight { get; set; } + public TKey ButtonMinus { get; set; } + public TKey ButtonL { get; set; } + public TKey ButtonZl { get; set; } + public TKey LeftButtonSl { get; set; } + public TKey LeftButtonSr { get; set; } + public TKey DpadUp { get; set; } + public TKey DpadDown { get; set; } + public TKey DpadLeft { get; set; } + public TKey DpadRight { get; set; } - public Key ButtonPlus { get; set; } - public Key ButtonR { get; set; } - public Key ButtonZr { get; set; } - public Key RightButtonSl { get; set; } - public Key RightButtonSr { get; set; } - public Key ButtonX { get; set; } - public Key ButtonB { get; set; } - public Key ButtonY { get; set; } - public Key ButtonA { get; set; } + public TKey ButtonPlus { get; set; } + public TKey ButtonR { get; set; } + public TKey ButtonZr { get; set; } + public TKey RightButtonSl { get; set; } + public TKey RightButtonSr { get; set; } + public TKey ButtonX { get; set; } + public TKey ButtonB { get; set; } + public TKey ButtonY { get; set; } + public TKey ButtonA { get; set; } + public TKey LeftStickUp { get; set; } + public TKey LeftStickDown { get; set; } + public TKey LeftStickLeft { get; set; } + public TKey LeftStickRight { get; set; } + public TKey LeftKeyboardStickButton { get; set; } - public Key LeftStickUp { get; set; } - public Key LeftStickDown { get; set; } - public Key LeftStickLeft { get; set; } - public Key LeftStickRight { get; set; } - public Key LeftKeyboardStickButton { get; set; } - - public Key RightStickUp { get; set; } - public Key RightStickDown { get; set; } - public Key RightStickLeft { get; set; } - public Key RightStickRight { get; set; } - public Key RightKeyboardStickButton { get; set; } + public TKey RightStickUp { get; set; } + public TKey RightStickDown { get; set; } + public TKey RightStickLeft { get; set; } + public TKey RightStickRight { get; set; } + public TKey RightKeyboardStickButton { get; set; } public int Sensitivity { @@ -163,9 +162,9 @@ namespace Ryujinx.Ava.UI.Models public bool EnableMotion { - get => enableMotion; set + get => _enableMotion; set { - enableMotion = value; + _enableMotion = value; OnPropertyChanged(); } @@ -181,18 +180,18 @@ namespace Ryujinx.Ava.UI.Models public bool EnableRumble { get; set; } public float WeakRumble { - get => weakRumble; set + get => _weakRumble; set { - weakRumble = value; + _weakRumble = value; OnPropertyChanged(); } } public float StrongRumble { - get => strongRumble; set + get => _strongRumble; set { - strongRumble = value; + _strongRumble = value; OnPropertyChanged(); } @@ -209,71 +208,71 @@ namespace Ryujinx.Ava.UI.Models if (config is StandardKeyboardInputConfig keyboardConfig) { - LeftStickUp = (Key)(object)keyboardConfig.LeftJoyconStick.StickUp; - LeftStickDown = (Key)(object)keyboardConfig.LeftJoyconStick.StickDown; - LeftStickLeft = (Key)(object)keyboardConfig.LeftJoyconStick.StickLeft; - LeftStickRight = (Key)(object)keyboardConfig.LeftJoyconStick.StickRight; - LeftKeyboardStickButton = (Key)(object)keyboardConfig.LeftJoyconStick.StickButton; + LeftStickUp = (TKey)(object)keyboardConfig.LeftJoyconStick.StickUp; + LeftStickDown = (TKey)(object)keyboardConfig.LeftJoyconStick.StickDown; + LeftStickLeft = (TKey)(object)keyboardConfig.LeftJoyconStick.StickLeft; + LeftStickRight = (TKey)(object)keyboardConfig.LeftJoyconStick.StickRight; + LeftKeyboardStickButton = (TKey)(object)keyboardConfig.LeftJoyconStick.StickButton; - RightStickUp = (Key)(object)keyboardConfig.RightJoyconStick.StickUp; - RightStickDown = (Key)(object)keyboardConfig.RightJoyconStick.StickDown; - RightStickLeft = (Key)(object)keyboardConfig.RightJoyconStick.StickLeft; - RightStickRight = (Key)(object)keyboardConfig.RightJoyconStick.StickRight; - RightKeyboardStickButton = (Key)(object)keyboardConfig.RightJoyconStick.StickButton; + RightStickUp = (TKey)(object)keyboardConfig.RightJoyconStick.StickUp; + RightStickDown = (TKey)(object)keyboardConfig.RightJoyconStick.StickDown; + RightStickLeft = (TKey)(object)keyboardConfig.RightJoyconStick.StickLeft; + RightStickRight = (TKey)(object)keyboardConfig.RightJoyconStick.StickRight; + RightKeyboardStickButton = (TKey)(object)keyboardConfig.RightJoyconStick.StickButton; - ButtonA = (Key)(object)keyboardConfig.RightJoycon.ButtonA; - ButtonB = (Key)(object)keyboardConfig.RightJoycon.ButtonB; - ButtonX = (Key)(object)keyboardConfig.RightJoycon.ButtonX; - ButtonY = (Key)(object)keyboardConfig.RightJoycon.ButtonY; - ButtonR = (Key)(object)keyboardConfig.RightJoycon.ButtonR; - RightButtonSl = (Key)(object)keyboardConfig.RightJoycon.ButtonSl; - RightButtonSr = (Key)(object)keyboardConfig.RightJoycon.ButtonSr; - ButtonZr = (Key)(object)keyboardConfig.RightJoycon.ButtonZr; - ButtonPlus = (Key)(object)keyboardConfig.RightJoycon.ButtonPlus; + ButtonA = (TKey)(object)keyboardConfig.RightJoycon.ButtonA; + ButtonB = (TKey)(object)keyboardConfig.RightJoycon.ButtonB; + ButtonX = (TKey)(object)keyboardConfig.RightJoycon.ButtonX; + ButtonY = (TKey)(object)keyboardConfig.RightJoycon.ButtonY; + ButtonR = (TKey)(object)keyboardConfig.RightJoycon.ButtonR; + RightButtonSl = (TKey)(object)keyboardConfig.RightJoycon.ButtonSl; + RightButtonSr = (TKey)(object)keyboardConfig.RightJoycon.ButtonSr; + ButtonZr = (TKey)(object)keyboardConfig.RightJoycon.ButtonZr; + ButtonPlus = (TKey)(object)keyboardConfig.RightJoycon.ButtonPlus; - DpadUp = (Key)(object)keyboardConfig.LeftJoycon.DpadUp; - DpadDown = (Key)(object)keyboardConfig.LeftJoycon.DpadDown; - DpadLeft = (Key)(object)keyboardConfig.LeftJoycon.DpadLeft; - DpadRight = (Key)(object)keyboardConfig.LeftJoycon.DpadRight; - ButtonMinus = (Key)(object)keyboardConfig.LeftJoycon.ButtonMinus; - LeftButtonSl = (Key)(object)keyboardConfig.LeftJoycon.ButtonSl; - LeftButtonSr = (Key)(object)keyboardConfig.LeftJoycon.ButtonSr; - ButtonZl = (Key)(object)keyboardConfig.LeftJoycon.ButtonZl; - ButtonL = (Key)(object)keyboardConfig.LeftJoycon.ButtonL; + DpadUp = (TKey)(object)keyboardConfig.LeftJoycon.DpadUp; + DpadDown = (TKey)(object)keyboardConfig.LeftJoycon.DpadDown; + DpadLeft = (TKey)(object)keyboardConfig.LeftJoycon.DpadLeft; + DpadRight = (TKey)(object)keyboardConfig.LeftJoycon.DpadRight; + ButtonMinus = (TKey)(object)keyboardConfig.LeftJoycon.ButtonMinus; + LeftButtonSl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSl; + LeftButtonSr = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSr; + ButtonZl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonZl; + ButtonL = (TKey)(object)keyboardConfig.LeftJoycon.ButtonL; } else if (config is StandardControllerInputConfig controllerConfig) { - LeftJoystick = (Stick)(object)controllerConfig.LeftJoyconStick.Joystick; + LeftJoystick = (TStick)(object)controllerConfig.LeftJoyconStick.Joystick; LeftInvertStickX = controllerConfig.LeftJoyconStick.InvertStickX; LeftInvertStickY = controllerConfig.LeftJoyconStick.InvertStickY; LeftRotate90 = controllerConfig.LeftJoyconStick.Rotate90CW; - LeftControllerStickButton = (Key)(object)controllerConfig.LeftJoyconStick.StickButton; + LeftControllerStickButton = (TKey)(object)controllerConfig.LeftJoyconStick.StickButton; - RightJoystick = (Stick)(object)controllerConfig.RightJoyconStick.Joystick; + RightJoystick = (TStick)(object)controllerConfig.RightJoyconStick.Joystick; RightInvertStickX = controllerConfig.RightJoyconStick.InvertStickX; RightInvertStickY = controllerConfig.RightJoyconStick.InvertStickY; RightRotate90 = controllerConfig.RightJoyconStick.Rotate90CW; - RightControllerStickButton = (Key)(object)controllerConfig.RightJoyconStick.StickButton; + RightControllerStickButton = (TKey)(object)controllerConfig.RightJoyconStick.StickButton; - ButtonA = (Key)(object)controllerConfig.RightJoycon.ButtonA; - ButtonB = (Key)(object)controllerConfig.RightJoycon.ButtonB; - ButtonX = (Key)(object)controllerConfig.RightJoycon.ButtonX; - ButtonY = (Key)(object)controllerConfig.RightJoycon.ButtonY; - ButtonR = (Key)(object)controllerConfig.RightJoycon.ButtonR; - RightButtonSl = (Key)(object)controllerConfig.RightJoycon.ButtonSl; - RightButtonSr = (Key)(object)controllerConfig.RightJoycon.ButtonSr; - ButtonZr = (Key)(object)controllerConfig.RightJoycon.ButtonZr; - ButtonPlus = (Key)(object)controllerConfig.RightJoycon.ButtonPlus; + ButtonA = (TKey)(object)controllerConfig.RightJoycon.ButtonA; + ButtonB = (TKey)(object)controllerConfig.RightJoycon.ButtonB; + ButtonX = (TKey)(object)controllerConfig.RightJoycon.ButtonX; + ButtonY = (TKey)(object)controllerConfig.RightJoycon.ButtonY; + ButtonR = (TKey)(object)controllerConfig.RightJoycon.ButtonR; + RightButtonSl = (TKey)(object)controllerConfig.RightJoycon.ButtonSl; + RightButtonSr = (TKey)(object)controllerConfig.RightJoycon.ButtonSr; + ButtonZr = (TKey)(object)controllerConfig.RightJoycon.ButtonZr; + ButtonPlus = (TKey)(object)controllerConfig.RightJoycon.ButtonPlus; - DpadUp = (Key)(object)controllerConfig.LeftJoycon.DpadUp; - DpadDown = (Key)(object)controllerConfig.LeftJoycon.DpadDown; - DpadLeft = (Key)(object)controllerConfig.LeftJoycon.DpadLeft; - DpadRight = (Key)(object)controllerConfig.LeftJoycon.DpadRight; - ButtonMinus = (Key)(object)controllerConfig.LeftJoycon.ButtonMinus; - LeftButtonSl = (Key)(object)controllerConfig.LeftJoycon.ButtonSl; - LeftButtonSr = (Key)(object)controllerConfig.LeftJoycon.ButtonSr; - ButtonZl = (Key)(object)controllerConfig.LeftJoycon.ButtonZl; - ButtonL = (Key)(object)controllerConfig.LeftJoycon.ButtonL; + DpadUp = (TKey)(object)controllerConfig.LeftJoycon.DpadUp; + DpadDown = (TKey)(object)controllerConfig.LeftJoycon.DpadDown; + DpadLeft = (TKey)(object)controllerConfig.LeftJoycon.DpadLeft; + DpadRight = (TKey)(object)controllerConfig.LeftJoycon.DpadRight; + ButtonMinus = (TKey)(object)controllerConfig.LeftJoycon.ButtonMinus; + LeftButtonSl = (TKey)(object)controllerConfig.LeftJoycon.ButtonSl; + LeftButtonSr = (TKey)(object)controllerConfig.LeftJoycon.ButtonSr; + ButtonZl = (TKey)(object)controllerConfig.LeftJoycon.ButtonZl; + ButtonL = (TKey)(object)controllerConfig.LeftJoycon.ButtonL; DeadzoneLeft = controllerConfig.DeadzoneLeft; DeadzoneRight = controllerConfig.DeadzoneRight; @@ -317,65 +316,66 @@ namespace Ryujinx.Ava.UI.Models { if (Backend == InputBackendType.WindowKeyboard) { - return new StandardKeyboardInputConfig() + return new StandardKeyboardInputConfig { Id = Id, Backend = Backend, PlayerIndex = PlayerIndex, ControllerType = ControllerType, - LeftJoycon = new LeftJoyconCommonConfig() + LeftJoycon = new LeftJoyconCommonConfig { - DpadUp = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadUp, - DpadDown = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadDown, - DpadLeft = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadLeft, - DpadRight = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadRight, - ButtonL = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonL, - ButtonZl = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonZl, - ButtonSl = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftButtonSl, - ButtonSr = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftButtonSr, - ButtonMinus = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonMinus + DpadUp = (Key)(object)DpadUp, + DpadDown = (Key)(object)DpadDown, + DpadLeft = (Key)(object)DpadLeft, + DpadRight = (Key)(object)DpadRight, + ButtonL = (Key)(object)ButtonL, + ButtonZl = (Key)(object)ButtonZl, + ButtonSl = (Key)(object)LeftButtonSl, + ButtonSr = (Key)(object)LeftButtonSr, + ButtonMinus = (Key)(object)ButtonMinus, }, - RightJoycon = new RightJoyconCommonConfig() + RightJoycon = new RightJoyconCommonConfig { - ButtonA = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonA, - ButtonB = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonB, - ButtonX = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonX, - ButtonY = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonY, - ButtonPlus = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonPlus, - ButtonSl = (Ryujinx.Common.Configuration.Hid.Key)(object)RightButtonSl, - ButtonSr = (Ryujinx.Common.Configuration.Hid.Key)(object)RightButtonSr, - ButtonR = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonR, - ButtonZr = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonZr + ButtonA = (Key)(object)ButtonA, + ButtonB = (Key)(object)ButtonB, + ButtonX = (Key)(object)ButtonX, + ButtonY = (Key)(object)ButtonY, + ButtonPlus = (Key)(object)ButtonPlus, + ButtonSl = (Key)(object)RightButtonSl, + ButtonSr = (Key)(object)RightButtonSr, + ButtonR = (Key)(object)ButtonR, + ButtonZr = (Key)(object)ButtonZr, }, - LeftJoyconStick = new JoyconConfigKeyboardStick() + LeftJoyconStick = new JoyconConfigKeyboardStick { - StickUp = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickUp, - StickDown = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickDown, - StickRight = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickRight, - StickLeft = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickLeft, - StickButton = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftKeyboardStickButton + StickUp = (Key)(object)LeftStickUp, + StickDown = (Key)(object)LeftStickDown, + StickRight = (Key)(object)LeftStickRight, + StickLeft = (Key)(object)LeftStickLeft, + StickButton = (Key)(object)LeftKeyboardStickButton, }, - RightJoyconStick = new JoyconConfigKeyboardStick() + RightJoyconStick = new JoyconConfigKeyboardStick { - StickUp = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickUp, - StickDown = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickDown, - StickLeft = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickLeft, - StickRight = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickRight, - StickButton = (Ryujinx.Common.Configuration.Hid.Key)(object)RightKeyboardStickButton + StickUp = (Key)(object)RightStickUp, + StickDown = (Key)(object)RightStickDown, + StickLeft = (Key)(object)RightStickLeft, + StickRight = (Key)(object)RightStickRight, + StickButton = (Key)(object)RightKeyboardStickButton, }, - Version = InputConfig.CurrentVersion + Version = InputConfig.CurrentVersion, }; } - else if (Backend == InputBackendType.GamepadSDL2) + + if (Backend == InputBackendType.GamepadSDL2) { - var config = new StandardControllerInputConfig() + var config = new StandardControllerInputConfig { Id = Id, Backend = Backend, PlayerIndex = PlayerIndex, ControllerType = ControllerType, - LeftJoycon = new LeftJoyconCommonConfig() + LeftJoycon = new LeftJoyconCommonConfig { DpadUp = (GamepadInputId)(object)DpadUp, DpadDown = (GamepadInputId)(object)DpadDown, @@ -387,7 +387,7 @@ namespace Ryujinx.Ava.UI.Models ButtonSr = (GamepadInputId)(object)LeftButtonSr, ButtonMinus = (GamepadInputId)(object)ButtonMinus, }, - RightJoycon = new RightJoyconCommonConfig() + RightJoycon = new RightJoyconCommonConfig { ButtonA = (GamepadInputId)(object)ButtonA, ButtonB = (GamepadInputId)(object)ButtonB, @@ -399,7 +399,7 @@ namespace Ryujinx.Ava.UI.Models ButtonR = (GamepadInputId)(object)ButtonR, ButtonZr = (GamepadInputId)(object)ButtonZr, }, - LeftJoyconStick = new JoyconConfigControllerStick() + LeftJoyconStick = new JoyconConfigControllerStick { Joystick = (StickInputId)(object)LeftJoystick, InvertStickX = LeftInvertStickX, @@ -407,7 +407,7 @@ namespace Ryujinx.Ava.UI.Models Rotate90CW = LeftRotate90, StickButton = (GamepadInputId)(object)LeftControllerStickButton, }, - RightJoyconStick = new JoyconConfigControllerStick() + RightJoyconStick = new JoyconConfigControllerStick { Joystick = (StickInputId)(object)RightJoystick, InvertStickX = RightInvertStickX, @@ -415,11 +415,11 @@ namespace Ryujinx.Ava.UI.Models Rotate90CW = RightRotate90, StickButton = (GamepadInputId)(object)RightControllerStickButton, }, - Rumble = new RumbleConfigController() + Rumble = new RumbleConfigController { EnableRumble = EnableRumble, WeakRumble = WeakRumble, - StrongRumble = StrongRumble + StrongRumble = StrongRumble, }, Version = InputConfig.CurrentVersion, DeadzoneLeft = DeadzoneLeft, @@ -428,19 +428,19 @@ namespace Ryujinx.Ava.UI.Models RangeRight = RangeRight, TriggerThreshold = TriggerThreshold, Motion = EnableCemuHookMotion - ? new CemuHookMotionConfigController() - { - DsuServerHost = DsuServerHost, - DsuServerPort = DsuServerPort, - Slot = Slot, - AltSlot = AltSlot, - MirrorInput = MirrorInput, - MotionBackend = MotionInputBackendType.CemuHook - } - : new StandardMotionConfigController() - { - MotionBackend = MotionInputBackendType.GamepadDriver - } + ? new CemuHookMotionConfigController + { + DsuServerHost = DsuServerHost, + DsuServerPort = DsuServerPort, + Slot = Slot, + AltSlot = AltSlot, + MirrorInput = MirrorInput, + MotionBackend = MotionInputBackendType.CemuHook, + } + : new StandardMotionConfigController + { + MotionBackend = MotionInputBackendType.GamepadDriver, + }, }; config.Motion.Sensitivity = Sensitivity; @@ -453,4 +453,4 @@ namespace Ryujinx.Ava.UI.Models return null; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/ProfileImageModel.cs b/src/Ryujinx.Ava/UI/Models/ProfileImageModel.cs index 8aa194005..99365dfc7 100644 --- a/src/Ryujinx.Ava/UI/Models/ProfileImageModel.cs +++ b/src/Ryujinx.Ava/UI/Models/ProfileImageModel.cs @@ -29,4 +29,4 @@ namespace Ryujinx.Ava.UI.Models } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/SaveModel.cs b/src/Ryujinx.Ava/UI/Models/SaveModel.cs index cc9b67681..2f220162f 100644 --- a/src/Ryujinx.Ava/UI/Models/SaveModel.cs +++ b/src/Ryujinx.Ava/UI/Models/SaveModel.cs @@ -2,12 +2,12 @@ using LibHac.Fs; using LibHac.Ncm; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.Windows; -using Ryujinx.HLE.FileSystem; using Ryujinx.Ui.App.Common; using System; using System.IO; using System.Linq; using System.Threading.Tasks; +using Path = System.IO.Path; namespace Ryujinx.Ava.UI.Models { @@ -58,7 +58,7 @@ namespace Ryujinx.Ava.UI.Models return "0 KiB"; } - public SaveModel(SaveDataInfo info, VirtualFileSystem virtualFileSystem) + public SaveModel(SaveDataInfo info) { SaveId = info.SaveDataId; TitleId = info.ProgramId; @@ -81,10 +81,11 @@ namespace Ryujinx.Ava.UI.Models Task.Run(() => { - var saveRoot = System.IO.Path.Combine(virtualFileSystem.GetNandPath(), $"user/save/{info.SaveDataId:x16}"); + var saveRoot = Path.Combine(MainWindow.MainWindowViewModel.VirtualFileSystem.GetNandPath(), $"user/save/{info.SaveDataId:x16}"); - long total_size = GetDirectorySize(saveRoot); - long GetDirectorySize(string path) + long totalSize = GetDirectorySize(saveRoot); + + static long GetDirectorySize(string path) { long size = 0; if (Directory.Exists(path)) @@ -105,7 +106,7 @@ namespace Ryujinx.Ava.UI.Models return size; } - Size = total_size; + Size = totalSize; }); } diff --git a/src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs b/src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs index ea2b90385..cc29442d0 100644 --- a/src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs +++ b/src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs @@ -25,4 +25,4 @@ namespace Ryujinx.Ava.UI.Models GpuName = gpuName; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/TempProfile.cs b/src/Ryujinx.Ava/UI/Models/TempProfile.cs index 05e16632d..659092e6d 100644 --- a/src/Ryujinx.Ava/UI/Models/TempProfile.cs +++ b/src/Ryujinx.Ava/UI/Models/TempProfile.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Models private string _name = String.Empty; private UserId _userId; - public uint MaxProfileNameLength => 0x20; + public static uint MaxProfileNameLength => 0x20; public byte[] Image { @@ -58,4 +58,4 @@ namespace Ryujinx.Ava.UI.Models } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/TimeZone.cs b/src/Ryujinx.Ava/UI/Models/TimeZone.cs index cb6cc2fdc..950fbce43 100644 --- a/src/Ryujinx.Ava/UI/Models/TimeZone.cs +++ b/src/Ryujinx.Ava/UI/Models/TimeZone.cs @@ -13,4 +13,4 @@ namespace Ryujinx.Ava.UI.Models public string Location { get; set; } public string Abbreviation { get; set; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs b/src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs index 80476a433..3b44e8ee6 100644 --- a/src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs +++ b/src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs @@ -16,4 +16,4 @@ namespace Ryujinx.Ava.UI.Models Path = path; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Models/UserProfile.cs b/src/Ryujinx.Ava/UI/Models/UserProfile.cs index e7cd53007..e1698b4df 100644 --- a/src/Ryujinx.Ava/UI/Models/UserProfile.cs +++ b/src/Ryujinx.Ava/UI/Models/UserProfile.cs @@ -1,3 +1,4 @@ +using Avalonia; using Avalonia.Media; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.ViewModels; @@ -87,7 +88,7 @@ namespace Ryujinx.Ava.UI.Models private void UpdateBackground() { - Avalonia.Application.Current.Styles.TryGetResource("ControlFillColorSecondary", out object color); + Application.Current.Styles.TryGetResource("ControlFillColorSecondary", out object color); if (color is not null) { @@ -100,4 +101,4 @@ namespace Ryujinx.Ava.UI.Models _owner.Navigate(typeof(UserEditorView), (_owner, userProfile, true)); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs index c5dd9332c..e324b484d 100644 --- a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs +++ b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs @@ -21,20 +21,20 @@ namespace Ryujinx.Ava.UI.Renderer public class EmbeddedWindow : NativeControlHost { private WindowProc _wndProcDelegate; - private string _className; + private string _className; protected GLXWindow X11Window { get; set; } protected IntPtr WindowHandle { get; set; } - protected IntPtr X11Display { get; set; } - protected IntPtr NsView { get; set; } - protected IntPtr MetalLayer { get; set; } + protected IntPtr X11Display { get; set; } + protected IntPtr NsView { get; set; } + protected IntPtr MetalLayer { get; set; } public delegate void UpdateBoundsCallbackDelegate(Rect rect); private UpdateBoundsCallbackDelegate _updateBoundsCallback; public event EventHandler WindowCreated; - public event EventHandler SizeChanged; + public event EventHandler SizeChanged; public EmbeddedWindow() { @@ -50,9 +50,9 @@ namespace Ryujinx.Ava.UI.Renderer protected virtual void OnWindowDestroying() { WindowHandle = IntPtr.Zero; - X11Display = IntPtr.Zero; - NsView = IntPtr.Zero; - MetalLayer = IntPtr.Zero; + X11Display = IntPtr.Zero; + NsView = IntPtr.Zero; + MetalLayer = IntPtr.Zero; } private void OnNativeEmbeddedWindowCreated(object sender, EventArgs e) @@ -77,11 +77,13 @@ namespace Ryujinx.Ava.UI.Renderer { return CreateLinux(control); } - else if (OperatingSystem.IsWindows()) + + if (OperatingSystem.IsWindows()) { return CreateWin32(control); } - else if (OperatingSystem.IsMacOS()) + + if (OperatingSystem.IsMacOS()) { return CreateMacOS(); } @@ -127,7 +129,7 @@ namespace Ryujinx.Ava.UI.Renderer } WindowHandle = X11Window.WindowHandle.RawHandle; - X11Display = X11Window.DisplayHandle.RawHandle; + X11Display = X11Window.DisplayHandle.RawHandle; return new PlatformHandle(WindowHandle, "X11"); } @@ -141,23 +143,23 @@ namespace Ryujinx.Ava.UI.Renderer { if (VisualRoot != null) { - if (msg == WindowsMessages.LBUTTONDOWN || - msg == WindowsMessages.RBUTTONDOWN || - msg == WindowsMessages.LBUTTONUP || - msg == WindowsMessages.RBUTTONUP || - msg == WindowsMessages.MOUSEMOVE) + if (msg == WindowsMessages.Lbuttondown || + msg == WindowsMessages.Rbuttondown || + msg == WindowsMessages.Lbuttonup || + msg == WindowsMessages.Rbuttonup || + msg == WindowsMessages.Mousemove) { - Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value; - Pointer pointer = new(0, PointerType.Mouse, true); + Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value; + Pointer pointer = new(0, PointerType.Mouse, true); switch (msg) { - case WindowsMessages.LBUTTONDOWN: - case WindowsMessages.RBUTTONDOWN: + case WindowsMessages.Lbuttondown: + case WindowsMessages.Rbuttondown: { - bool isLeft = msg == WindowsMessages.LBUTTONDOWN; - RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton; - PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed); + bool isLeft = msg == WindowsMessages.Lbuttondown; + RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton; + PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed); var evnt = new PointerPressedEventArgs( this, @@ -172,12 +174,12 @@ namespace Ryujinx.Ava.UI.Renderer break; } - case WindowsMessages.LBUTTONUP: - case WindowsMessages.RBUTTONUP: + case WindowsMessages.Lbuttonup: + case WindowsMessages.Rbuttonup: { - bool isLeft = msg == WindowsMessages.LBUTTONUP; - RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton; - PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased); + bool isLeft = msg == WindowsMessages.Lbuttonup; + RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton; + PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased); var evnt = new PointerReleasedEventArgs( this, @@ -193,7 +195,7 @@ namespace Ryujinx.Ava.UI.Renderer break; } - case WindowsMessages.MOUSEMOVE: + case WindowsMessages.Mousemove: { var evnt = new PointerEventArgs( PointerMovedEvent, @@ -216,19 +218,19 @@ namespace Ryujinx.Ava.UI.Renderer return DefWindowProc(hWnd, msg, wParam, lParam); }; - WNDCLASSEX wndClassEx = new() + WndClassEx wndClassEx = new() { - cbSize = Marshal.SizeOf(), - hInstance = GetModuleHandle(null), - lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate), - style = ClassStyles.CS_OWNDC, + cbSize = Marshal.SizeOf(), + hInstance = GetModuleHandle(null), + lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate), + style = ClassStyles.CsOwndc, lpszClassName = Marshal.StringToHGlobalUni(_className), - hCursor = CreateArrowCursor() + hCursor = CreateArrowCursor(), }; RegisterClassEx(ref wndClassEx); - WindowHandle = CreateWindowEx(0, _className, "NativeWindow", WindowStyles.WS_CHILD, 0, 0, 640, 480, control.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + WindowHandle = CreateWindowEx(0, _className, "NativeWindow", WindowStyles.WsChild, 0, 0, 640, 480, control.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); Marshal.FreeHGlobal(wndClassEx.lpszClassName); @@ -280,9 +282,11 @@ namespace Ryujinx.Ava.UI.Renderer } [SupportedOSPlatform("macos")] +#pragma warning disable CA1822 // Mark member as static void DestroyMacOS() { // TODO } +#pragma warning restore CA1822 } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs index d427ab88c..769a1c91a 100644 --- a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs +++ b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs @@ -91,4 +91,4 @@ namespace Ryujinx.Ava.UI.Renderer MakeCurrent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowVulkan.cs b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowVulkan.cs index 0b3eb9e30..fafbec207 100644 --- a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowVulkan.cs +++ b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowVulkan.cs @@ -34,9 +34,9 @@ namespace Ryujinx.Ava.UI.Renderer return new SurfaceKHR((ulong?)VulkanHelper.CreateWindowSurface(instance.Handle, nativeWindowBase)); } - public SurfaceKHR CreateSurface(Instance instance, Vk api) + public SurfaceKHR CreateSurface(Instance instance, Vk _) { return CreateSurface(instance); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Renderer/OpenTKBindingsContext.cs b/src/Ryujinx.Ava/UI/Renderer/OpenTKBindingsContext.cs index a2ec02b25..85e8585fc 100644 --- a/src/Ryujinx.Ava/UI/Renderer/OpenTKBindingsContext.cs +++ b/src/Ryujinx.Ava/UI/Renderer/OpenTKBindingsContext.cs @@ -17,4 +17,4 @@ namespace Ryujinx.Ava.UI.Renderer return _getProcAddress(procName); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs b/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs index ee10282db..b74265a31 100644 --- a/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs +++ b/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Renderer public readonly EmbeddedWindow EmbeddedWindow; public event EventHandler WindowCreated; - public event Action SizeChanged; + public event Action SizeChanged; public RendererHost() { @@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Renderer private void Initialize() { EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated; - EmbeddedWindow.SizeChanged += CurrentWindow_SizeChanged; + EmbeddedWindow.SizeChanged += CurrentWindow_SizeChanged; Content = EmbeddedWindow; } @@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Renderer if (EmbeddedWindow != null) { EmbeddedWindow.WindowCreated -= CurrentWindow_WindowCreated; - EmbeddedWindow.SizeChanged -= CurrentWindow_SizeChanged; + EmbeddedWindow.SizeChanged -= CurrentWindow_SizeChanged; } GC.SuppressFinalize(this); @@ -65,4 +65,4 @@ namespace Ryujinx.Ava.UI.Renderer WindowCreated?.Invoke(this, EventArgs.Empty); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Renderer/SPBOpenGLContext.cs b/src/Ryujinx.Ava/UI/Renderer/SPBOpenGLContext.cs index e090f14c7..a2c7aa279 100644 --- a/src/Ryujinx.Ava/UI/Renderer/SPBOpenGLContext.cs +++ b/src/Ryujinx.Ava/UI/Renderer/SPBOpenGLContext.cs @@ -10,12 +10,12 @@ namespace Ryujinx.Ava.UI.Renderer class SPBOpenGLContext : IOpenGLContext { private readonly OpenGLContextBase _context; - private readonly NativeWindowBase _window; + private readonly NativeWindowBase _window; private SPBOpenGLContext(OpenGLContextBase context, NativeWindowBase window) { _context = context; - _window = window; + _window = window; } public void Dispose() @@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Renderer public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext) { OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext); - NativeWindowBase window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100); + NativeWindowBase window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100); context.Initialize(window); context.MakeCurrent(window); diff --git a/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs index 479411cba..fddcd71a7 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs @@ -1,5 +1,6 @@ using Avalonia; using Avalonia.Media.Imaging; +using Avalonia.Platform; using Avalonia.Threading; using Ryujinx.Ava.Common.Locale; using Ryujinx.Common.Utilities; @@ -87,7 +88,7 @@ namespace Ryujinx.Ava.UI.ViewModels { Version = Program.Version; - var assets = AvaloniaLocator.Current.GetService(); + var assets = AvaloniaLocator.Current.GetService(); if (ConfigurationState.Instance.Ui.BaseStyle.Value == "Light") { @@ -130,4 +131,4 @@ namespace Ryujinx.Ava.UI.ViewModels } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs index ecd425ef2..3138dd146 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs @@ -18,7 +18,6 @@ using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; -using AmiiboJsonSerializerContext = Ryujinx.Ui.Common.Models.Amiibo.AmiiboJsonSerializerContext; namespace Ryujinx.Ava.UI.ViewModels { @@ -44,7 +43,7 @@ namespace Ryujinx.Ava.UI.ViewModels private bool _useRandomUuid; private string _usage; - private static readonly AmiiboJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); public AmiiboWindowViewModel(StyleableWindow owner, string lastScannedAmiiboId, string titleId) { @@ -52,7 +51,7 @@ namespace Ryujinx.Ava.UI.ViewModels _httpClient = new HttpClient { - Timeout = TimeSpan.FromSeconds(30) + Timeout = TimeSpan.FromSeconds(30), }; LastScannedAmiiboId = lastScannedAmiiboId; @@ -185,6 +184,7 @@ namespace Ryujinx.Ava.UI.ViewModels public void Dispose() { + GC.SuppressFinalize(this); _httpClient.Dispose(); } @@ -196,7 +196,7 @@ namespace Ryujinx.Ava.UI.ViewModels { amiiboJsonString = await File.ReadAllTextAsync(_amiiboJsonPath); - if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, SerializerContext.AmiiboJson).LastUpdated)) + if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).LastUpdated)) { amiiboJsonString = await DownloadAmiiboJson(); } @@ -215,7 +215,7 @@ namespace Ryujinx.Ava.UI.ViewModels } } - _amiiboList = JsonHelper.Deserialize(amiiboJsonString, SerializerContext.AmiiboJson).Amiibo; + _amiiboList = JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).Amiibo; _amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList(); ParseAmiiboData(); @@ -426,18 +426,17 @@ namespace Ryujinx.Ava.UI.ViewModels if (response.IsSuccessStatusCode) { byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync(); - using (MemoryStream memoryStream = new(amiiboPreviewBytes)) - { - Bitmap bitmap = new(memoryStream); + using MemoryStream memoryStream = new(amiiboPreviewBytes); - double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width, + Bitmap bitmap = new(memoryStream); + + double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width, AmiiboImageSize / bitmap.Size.Height); - int resizeHeight = (int)(bitmap.Size.Height * ratio); - int resizeWidth = (int)(bitmap.Size.Width * ratio); + int resizeHeight = (int)(bitmap.Size.Height * ratio); + int resizeWidth = (int)(bitmap.Size.Width * ratio); - AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight)); - } + AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight)); } else { @@ -447,15 +446,14 @@ namespace Ryujinx.Ava.UI.ViewModels private void ResetAmiiboPreview() { - using (MemoryStream memoryStream = new(_amiiboLogoBytes)) - { - Bitmap bitmap = new(memoryStream); + using MemoryStream memoryStream = new(_amiiboLogoBytes); - AmiiboImage = bitmap; - } + Bitmap bitmap = new(memoryStream); + + AmiiboImage = bitmap; } - private async void ShowInfoDialog() + private static async void ShowInfoDialog() { await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle], LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage], @@ -464,4 +462,4 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.RyujinxInfo]); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/AvatarProfileViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AvatarProfileViewModel.cs deleted file mode 100644 index b2b310149..000000000 --- a/src/Ryujinx.Ava/UI/ViewModels/AvatarProfileViewModel.cs +++ /dev/null @@ -1,363 +0,0 @@ -using Avalonia.Media; -using DynamicData; -using LibHac.Common; -using LibHac.Fs; -using LibHac.Fs.Fsa; -using LibHac.FsSystem; -using LibHac.Ncm; -using LibHac.Tools.Fs; -using LibHac.Tools.FsSystem; -using LibHac.Tools.FsSystem.NcaUtils; -using Ryujinx.Ava.UI.Models; -using Ryujinx.HLE.FileSystem; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System; -using System.Buffers.Binary; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Color = Avalonia.Media.Color; - -namespace Ryujinx.Ava.UI.ViewModels -{ - internal class AvatarProfileViewModel : BaseModel, IDisposable - { - private const int MaxImageTasks = 4; - - private static readonly Dictionary _avatarStore = new(); - private static bool _isPreloading; - private static Action _loadCompleteAction; - - private ObservableCollection _images; - private Color _backgroundColor = Colors.White; - - private int _selectedIndex; - private int _imagesLoaded; - private bool _isActive; - private byte[] _selectedImage; - private bool _isIndeterminate = true; - - public bool IsActive - { - get => _isActive; - set => _isActive = value; - } - - public AvatarProfileViewModel() - { - _images = new ObservableCollection(); - } - - public AvatarProfileViewModel(Action loadCompleteAction) - { - _images = new ObservableCollection(); - - if (_isPreloading) - { - _loadCompleteAction = loadCompleteAction; - } - else - { - ReloadImages(); - } - } - - public Color BackgroundColor - { - get => _backgroundColor; - set - { - _backgroundColor = value; - - IsActive = false; - - ReloadImages(); - } - } - - public ObservableCollection Images - { - get => _images; - set - { - _images = value; - OnPropertyChanged(); - } - } - - public bool IsIndeterminate - { - get => _isIndeterminate; - set - { - _isIndeterminate = value; - - OnPropertyChanged(); - } - } - - public int ImageCount => _avatarStore.Count; - - public int ImagesLoaded - { - get => _imagesLoaded; - set - { - _imagesLoaded = value; - OnPropertyChanged(); - } - } - - public int SelectedIndex - { - get => _selectedIndex; - set - { - _selectedIndex = value; - - if (_selectedIndex == -1) - { - SelectedImage = null; - } - else - { - SelectedImage = _images[_selectedIndex].Data; - } - - OnPropertyChanged(); - } - } - - public byte[] SelectedImage - { - get => _selectedImage; - private set => _selectedImage = value; - } - - public void ReloadImages() - { - if (_isPreloading) - { - IsIndeterminate = false; - return; - } - Task.Run(() => - { - IsActive = true; - - Images.Clear(); - int selectedIndex = _selectedIndex; - int index = 0; - - ImagesLoaded = 0; - IsIndeterminate = false; - - var keys = _avatarStore.Keys.ToList(); - - var newImages = new List(); - var tasks = new List(); - - for (int i = 0; i < MaxImageTasks; i++) - { - var start = i; - tasks.Add(Task.Run(() => ImageTask(start))); - } - - Task.WaitAll(tasks.ToArray()); - - Images.AddRange(newImages); - - void ImageTask(int start) - { - for (int i = start; i < keys.Count; i += MaxImageTasks) - { - if (!IsActive) - { - return; - } - - var key = keys[i]; - var image = _avatarStore[keys[i]]; - - var data = ProcessImage(image); - newImages.Add(new ProfileImageModel(key, data)); - if (index++ == selectedIndex) - { - SelectedImage = data; - } - - Interlocked.Increment(ref _imagesLoaded); - OnPropertyChanged(nameof(ImagesLoaded)); - } - } - }); - } - - private byte[] ProcessImage(byte[] data) - { - using (MemoryStream streamJpg = new()) - { - Image avatarImage = Image.Load(data, new PngDecoder()); - - avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(BackgroundColor.R, - BackgroundColor.G, - BackgroundColor.B, - BackgroundColor.A))); - avatarImage.SaveAsJpeg(streamJpg); - - return streamJpg.ToArray(); - } - } - - public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem) - { - try - { - if (_avatarStore.Count > 0) - { - return; - } - - _isPreloading = true; - - string contentPath = - contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem, - NcaContentType.Data); - string avatarPath = virtualFileSystem.SwitchPathToSystemPath(contentPath); - - if (!string.IsNullOrWhiteSpace(avatarPath)) - { - using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open)) - { - Nca nca = new(virtualFileSystem.KeySet, ncaFileStream); - IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); - - foreach (DirectoryEntryEx item in romfs.EnumerateEntries()) - { - // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy. - if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && - item.FullPath.Contains("szs")) - { - using var file = new UniqueRef(); - - romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read) - .ThrowIfFailure(); - - using (MemoryStream stream = new()) - using (MemoryStream streamPng = new()) - { - file.Get.AsStream().CopyTo(stream); - - stream.Position = 0; - - Image avatarImage = Image.LoadPixelData(DecompressYaz0(stream), 256, 256); - - avatarImage.SaveAsPng(streamPng); - - _avatarStore.Add(item.FullPath, streamPng.ToArray()); - } - } - } - } - } - } - finally - { - _isPreloading = false; - _loadCompleteAction?.Invoke(); - } - } - - private static byte[] DecompressYaz0(Stream stream) - { - using (BinaryReader reader = new(stream)) - { - reader.ReadInt32(); // Magic - - uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32()); - - reader.ReadInt64(); // Padding - - byte[] input = new byte[stream.Length - stream.Position]; - stream.Read(input, 0, input.Length); - - uint inputOffset = 0; - - byte[] output = new byte[decodedLength]; - uint outputOffset = 0; - - ushort mask = 0; - byte header = 0; - - while (outputOffset < decodedLength) - { - if ((mask >>= 1) == 0) - { - header = input[inputOffset++]; - mask = 0x80; - } - - if ((header & mask) != 0) - { - if (outputOffset == output.Length) - { - break; - } - - output[outputOffset++] = input[inputOffset++]; - } - else - { - byte byte1 = input[inputOffset++]; - byte byte2 = input[inputOffset++]; - - uint dist = (uint)((byte1 & 0xF) << 8) | byte2; - uint position = outputOffset - (dist + 1); - - uint length = (uint)byte1 >> 4; - if (length == 0) - { - length = (uint)input[inputOffset++] + 0x12; - } - else - { - length += 2; - } - - uint gap = outputOffset - position; - uint nonOverlappingLength = length; - - if (nonOverlappingLength > gap) - { - nonOverlappingLength = gap; - } - - Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength); - outputOffset += nonOverlappingLength; - position += nonOverlappingLength; - length -= nonOverlappingLength; - - while (length-- > 0) - { - output[outputOffset++] = output[position++]; - } - } - } - - return output; - } - } - - public void Dispose() - { - _loadCompleteAction = null; - IsActive = false; - } - } -} \ No newline at end of file diff --git a/src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs b/src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs index 5a3717fd3..0ff72dbc4 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs @@ -12,4 +12,4 @@ namespace Ryujinx.Ava.UI.ViewModels PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs index fda58504e..c0c625321 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs @@ -1,3 +1,4 @@ +using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; @@ -44,15 +45,14 @@ namespace Ryujinx.Ava.UI.ViewModels private PlayerIndex _playerId; private int _controller; - private int _controllerNumber = 0; + private int _controllerNumber; private string _controllerImage; private int _device; private object _configuration; private string _profileName; private bool _isLoaded; - private readonly UserControl _owner; - private static readonly InputConfigJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); public IGamepadDriver AvaloniaKeyboardDriver { get; } public IGamepad SelectedGamepad { get; private set; } @@ -176,11 +176,11 @@ namespace Ryujinx.Ava.UI.ViewModels { get { - SvgImage image = new SvgImage(); + SvgImage image = new(); if (!string.IsNullOrWhiteSpace(_controllerImage)) { - SvgSource source = new SvgSource(); + SvgSource source = new(); source.Load(EmbeddedResources.GetStream(_controllerImage)); @@ -234,22 +234,18 @@ namespace Ryujinx.Ava.UI.ViewModels public ControllerInputViewModel(UserControl owner) : this() { - _owner = owner; - if (Program.PreviewerDetached) { _mainWindow = - (MainWindow)((IClassicDesktopStyleApplicationLifetime)Avalonia.Application.Current + (MainWindow)((IClassicDesktopStyleApplicationLifetime)Application.Current .ApplicationLifetime).MainWindow; AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner); _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; - if (_mainWindow.ViewModel.AppHost != null) - { - _mainWindow.ViewModel.AppHost.NpadManager.BlockInputUpdates(); - } + + _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates(); _isLoaded = false; @@ -351,7 +347,8 @@ namespace Ryujinx.Ava.UI.ViewModels { return; } - else if (type == DeviceType.Keyboard) + + if (type == DeviceType.Keyboard) { if (_mainWindow.InputManager.KeyboardDriver is AvaloniaKeyboardDriver) { @@ -448,7 +445,7 @@ namespace Ryujinx.Ava.UI.ViewModels const string Hyphen = "-"; const int Offset = 1; - return str.Substring(str.IndexOf(Hyphen) + Offset); + return str[(str.IndexOf(Hyphen) + Offset)..]; } public void LoadDevices() @@ -562,7 +559,7 @@ namespace Ryujinx.Ava.UI.ViewModels ButtonL = Key.E, ButtonZl = Key.Q, ButtonSl = Key.Unbound, - ButtonSr = Key.Unbound + ButtonSr = Key.Unbound, }, LeftJoyconStick = new JoyconConfigKeyboardStick @@ -571,7 +568,7 @@ namespace Ryujinx.Ava.UI.ViewModels StickDown = Key.S, StickLeft = Key.A, StickRight = Key.D, - StickButton = Key.F + StickButton = Key.F, }, RightJoycon = new RightJoyconCommonConfig { @@ -583,7 +580,7 @@ namespace Ryujinx.Ava.UI.ViewModels ButtonR = Key.U, ButtonZr = Key.O, ButtonSl = Key.Unbound, - ButtonSr = Key.Unbound + ButtonSr = Key.Unbound, }, RightJoyconStick = new JoyconConfigKeyboardStick { @@ -591,8 +588,8 @@ namespace Ryujinx.Ava.UI.ViewModels StickDown = Key.K, StickLeft = Key.J, StickRight = Key.L, - StickButton = Key.H - } + StickButton = Key.H, + }, }; } else if (activeDevice.Type == DeviceType.Controller) @@ -622,14 +619,14 @@ namespace Ryujinx.Ava.UI.ViewModels ButtonL = ConfigGamepadInputId.LeftShoulder, ButtonZl = ConfigGamepadInputId.LeftTrigger, ButtonSl = ConfigGamepadInputId.Unbound, - ButtonSr = ConfigGamepadInputId.Unbound + ButtonSr = ConfigGamepadInputId.Unbound, }, LeftJoyconStick = new JoyconConfigControllerStick { Joystick = ConfigStickInputId.Left, StickButton = ConfigGamepadInputId.LeftStick, InvertStickX = false, - InvertStickY = false + InvertStickY = false, }, RightJoycon = new RightJoyconCommonConfig { @@ -641,28 +638,28 @@ namespace Ryujinx.Ava.UI.ViewModels ButtonR = ConfigGamepadInputId.RightShoulder, ButtonZr = ConfigGamepadInputId.RightTrigger, ButtonSl = ConfigGamepadInputId.Unbound, - ButtonSr = ConfigGamepadInputId.Unbound + ButtonSr = ConfigGamepadInputId.Unbound, }, RightJoyconStick = new JoyconConfigControllerStick { Joystick = ConfigStickInputId.Right, StickButton = ConfigGamepadInputId.RightStick, InvertStickX = false, - InvertStickY = false + InvertStickY = false, }, Motion = new StandardMotionConfigController { MotionBackend = MotionInputBackendType.GamepadDriver, EnableMotion = true, Sensitivity = 100, - GyroDeadzone = 1 + GyroDeadzone = 1, }, Rumble = new RumbleConfigController { StrongRumble = 1f, WeakRumble = 1f, - EnableRumble = false - } + EnableRumble = false, + }, }; } else @@ -709,7 +706,7 @@ namespace Ryujinx.Ava.UI.ViewModels try { - config = JsonHelper.DeserializeFromFile(path, SerializerContext.InputConfig); + config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig); } catch (JsonException) { } catch (InvalidOperationException) @@ -754,37 +751,35 @@ namespace Ryujinx.Ava.UI.ViewModels return; } + + bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1; + + if (validFileName) + { + string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json"); + + InputConfig config = null; + + if (IsKeyboard) + { + config = (Configuration as InputConfiguration).GetConfig(); + } + else if (IsController) + { + config = (Configuration as InputConfiguration).GetConfig(); + } + + config.ControllerType = Controllers[_controller].Type; + + string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); + + await File.WriteAllTextAsync(path, jsonString); + + LoadProfiles(); + } else { - bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1; - - if (validFileName) - { - string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json"); - - InputConfig config = null; - - if (IsKeyboard) - { - config = (Configuration as InputConfiguration).GetConfig(); - } - else if (IsController) - { - config = (Configuration as InputConfiguration).GetConfig(); - } - - config.ControllerType = Controllers[_controller].Type; - - string jsonString = JsonHelper.Serialize(config, SerializerContext.InputConfig); - - await File.WriteAllTextAsync(path, jsonString); - - LoadProfiles(); - } - else - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]); - } + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]); } } @@ -887,6 +882,8 @@ namespace Ryujinx.Ava.UI.ViewModels public void Dispose() { + GC.SuppressFinalize(this); + _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected; _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected; @@ -897,4 +894,4 @@ namespace Ryujinx.Ava.UI.ViewModels AvaloniaKeyboardDriver.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs index 1d7da9a40..f2f569472 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using Application = Avalonia.Application; using Path = System.IO.Path; namespace Ryujinx.Ava.UI.ViewModels @@ -29,18 +30,17 @@ namespace Ryujinx.Ava.UI.ViewModels public class DownloadableContentManagerViewModel : BaseModel { private readonly List _downloadableContentContainerList; - private readonly string _downloadableContentJsonPath; + private readonly string _downloadableContentJsonPath; - private VirtualFileSystem _virtualFileSystem; + private readonly VirtualFileSystem _virtualFileSystem; private AvaloniaList _downloadableContents = new(); private AvaloniaList _views = new(); private AvaloniaList _selectedDownloadableContents = new(); private string _search; - private ulong _titleId; - private string _titleName; + private readonly ulong _titleId; - private static readonly DownloadableContentJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); public AvaloniaList DownloadableContents { @@ -90,18 +90,17 @@ namespace Ryujinx.Ava.UI.ViewModels get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count); } - public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) + public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId) { _virtualFileSystem = virtualFileSystem; - _titleId = titleId; - _titleName = titleName; + _titleId = titleId; _downloadableContentJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "dlc.json"); try { - _downloadableContentContainerList = JsonHelper.DeserializeFromFile(_downloadableContentJsonPath, SerializerContext.ListDownloadableContentContainer); + _downloadableContentContainerList = JsonHelper.DeserializeFromFile(_downloadableContentJsonPath, _serializerContext.ListDownloadableContentContainer); } catch { @@ -132,7 +131,7 @@ namespace Ryujinx.Ava.UI.ViewModels Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), downloadableContentContainer.ContainerPath); if (nca != null) - { + { var content = new DownloadableContentModel(nca.Header.TitleId.ToString("X16"), downloadableContentContainer.ContainerPath, downloadableContentNca.FullPath, @@ -196,19 +195,19 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OpenFileDialog dialog = new OpenFileDialog() + OpenFileDialog dialog = new() { - Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], - AllowMultiple = true + Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], + AllowMultiple = true, }; dialog.Filters.Add(new FileDialogFilter { - Name = "NSP", - Extensions = { "nsp" } + Name = "NSP", + Extensions = { "nsp" }, }); - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { string[] files = await dialog.ShowAsync(desktop.MainWindow); @@ -231,8 +230,8 @@ namespace Ryujinx.Ava.UI.ViewModels using FileStream containerFile = File.OpenRead(path); - PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage()); - bool containsDownloadableContent = false; + PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage()); + bool containsDownloadableContent = false; _virtualFileSystem.ImportTickets(partitionFileSystem); @@ -313,16 +312,16 @@ namespace Ryujinx.Ava.UI.ViewModels container = new DownloadableContentContainer { - ContainerPath = downloadableContent.ContainerPath, - DownloadableContentNcaList = new List() + ContainerPath = downloadableContent.ContainerPath, + DownloadableContentNcaList = new List(), }; } container.DownloadableContentNcaList.Add(new DownloadableContentNca { - Enabled = downloadableContent.Enabled, - TitleId = Convert.ToUInt64(downloadableContent.TitleId, 16), - FullPath = downloadableContent.FullPath + Enabled = downloadableContent.Enabled, + TitleId = Convert.ToUInt64(downloadableContent.TitleId, 16), + FullPath = downloadableContent.FullPath, }); } @@ -331,8 +330,8 @@ namespace Ryujinx.Ava.UI.ViewModels _downloadableContentContainerList.Add(container); } - JsonHelper.SerializeToFile(_downloadableContentJsonPath, _downloadableContentContainerList, SerializerContext.ListDownloadableContentContainer); + JsonHelper.SerializeToFile(_downloadableContentJsonPath, _downloadableContentContainerList, _serializerContext.ListDownloadableContentContainer); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index 0976e2fae..e8d68f769 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -1,3 +1,4 @@ +using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; @@ -12,6 +13,7 @@ using Ryujinx.Ava.Input; 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.Common; @@ -23,6 +25,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.Ui; +using Ryujinx.Modules; using Ryujinx.Ui.App.Common; using Ryujinx.Ui.Common; using Ryujinx.Ui.Common.Configuration; @@ -34,7 +37,10 @@ using System.Collections.ObjectModel; using System.IO; using System.Threading; using System.Threading.Tasks; -using Path = System.IO.Path; +using Image = SixLabors.ImageSharp.Image; +using InputManager = Ryujinx.Input.HLE.InputManager; +using Key = Ryujinx.Input.Key; +using MissingKeyException = LibHac.Common.Keys.MissingKeyException; using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState; namespace Ryujinx.Ava.UI.ViewModels @@ -89,7 +95,7 @@ namespace Ryujinx.Ava.UI.ViewModels private Cursor _cursor; private string _title; private string _currentEmulatedGamePath; - private AutoResetEvent _rendererWaitEvent; + private readonly AutoResetEvent _rendererWaitEvent; private WindowState _windowState; private double _windowWidth; private double _windowHeight; @@ -128,7 +134,7 @@ namespace Ryujinx.Ava.UI.ViewModels ApplicationLibrary applicationLibrary, VirtualFileSystem virtualFileSystem, AccountManager accountManager, - Ryujinx.Input.HLE.InputManager inputManager, + InputManager inputManager, UserChannelPersistence userChannelPersistence, LibHacHorizonManager libHacHorizonManager, IHostUiHandler uiHandler, @@ -152,7 +158,7 @@ namespace Ryujinx.Ava.UI.ViewModels TopLevel = topLevel; } -#region Properties + #region Properties public string SearchText { @@ -177,7 +183,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool CanUpdate { - get => _canUpdate && EnableNonGameRunningControls && Modules.Updater.CanUpdate(false); + get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(false); set { _canUpdate = value; @@ -343,11 +349,11 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public bool OpenUserSaveDirectoryEnabled => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0; + public bool OpenUserSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0; - public bool OpenDeviceSaveDirectoryEnabled => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0; + public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0; - public bool OpenBcatSaveDirectoryEnabled => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; + public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; public string LoadHeading { @@ -888,7 +894,7 @@ namespace Ryujinx.Ava.UI.ViewModels public ApplicationLibrary ApplicationLibrary { get; private set; } public VirtualFileSystem VirtualFileSystem { get; private set; } public AccountManager AccountManager { get; private set; } - public Ryujinx.Input.HLE.InputManager InputManager { get; private set; } + public InputManager InputManager { get; private set; } public UserChannelPersistence UserChannelPersistence { get; private set; } public Action ShowLoading { get; private set; } public Action SwitchToGameControl { get; private set; } @@ -911,15 +917,16 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsGridLarge => ConfigurationState.Instance.Ui.GridSize == 3; public bool IsGridHuge => ConfigurationState.Instance.Ui.GridSize == 4; -#endregion + #endregion -#region PrivateMethods + #region PrivateMethods private IComparer GetComparer() { return SortMode switch { - ApplicationSort.LastPlayed => new Models.Generic.LastPlayedSortComparer(IsAscending), +#pragma warning disable IDE0055 // Disable formatting + ApplicationSort.LastPlayed => new LastPlayedSortComparer(IsAscending), ApplicationSort.FileSize => IsAscending ? SortExpressionComparer.Ascending(app => app.FileSizeBytes) : SortExpressionComparer.Descending(app => app.FileSizeBytes), ApplicationSort.TotalTimePlayed => IsAscending ? SortExpressionComparer.Ascending(app => app.TimePlayedNum) @@ -935,6 +942,7 @@ namespace Ryujinx.Ava.UI.ViewModels ApplicationSort.Path => IsAscending ? SortExpressionComparer.Ascending(app => app.Path) : SortExpressionComparer.Descending(app => app.Path), _ => null, +#pragma warning restore IDE0055 }; } @@ -1023,7 +1031,7 @@ namespace Ryujinx.Ava.UI.ViewModels // Purge Applet Cache. - DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache")); + DirectoryInfo miiEditorCacheFolder = new(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache")); if (miiEditorCacheFolder.Exists) { @@ -1044,18 +1052,21 @@ namespace Ryujinx.Ava.UI.ViewModels { RefreshFirmwareStatus(); } - }) { Name = "GUI.FirmwareInstallerThread" }; + }) + { + Name = "GUI.FirmwareInstallerThread", + }; thread.Start(); } } - catch (LibHac.Common.Keys.MissingKeyException ex) + catch (MissingKeyException ex) { - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { Logger.Error?.Print(LogClass.Application, ex.ToString()); - async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, (desktop.MainWindow as MainWindow)); + static async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys); Dispatcher.UIThread.Post(Action); } @@ -1120,7 +1131,7 @@ namespace Ryujinx.Ava.UI.ViewModels private void PrepareLoadScreen() { using MemoryStream stream = new(SelectedIcon); - using var gameIconBmp = SixLabors.ImageSharp.Image.Load(stream); + using var gameIconBmp = Image.Load(stream); var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel(); @@ -1175,7 +1186,7 @@ namespace Ryujinx.Ava.UI.ViewModels { Dispatcher.UIThread.InvokeAsync(() => { - Avalonia.Application.Current.Styles.TryGetResource(args.VSyncEnabled + Application.Current.Styles.TryGetResource(args.VSyncEnabled ? "VsyncEnabled" : "VsyncDisabled", out object color); @@ -1204,11 +1215,11 @@ namespace Ryujinx.Ava.UI.ViewModels _rendererWaitEvent.Set(); } -#endregion + #endregion -#region PublicMethods + #region PublicMethods - public void SetUIProgressHandlers(Switch emulationContext) + public void SetUiProgressHandlers(Switch emulationContext) { if (emulationContext.Processes.ActiveApplication.DiskCacheLoadState != null) { @@ -1222,17 +1233,17 @@ namespace Ryujinx.Ava.UI.ViewModels public void LoadConfigurableHotKeys() { - if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey)) + if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey)) { ShowUiKey = new KeyGesture(showUiKey); } - if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey)) + if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey)) { ScreenshotKey = new KeyGesture(screenshotKey); } - if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey)) + if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey)) { PauseKey = new KeyGesture(pauseKey); } @@ -1260,12 +1271,12 @@ namespace Ryujinx.Ava.UI.ViewModels public async void InstallFirmwareFromFile() { - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { OpenFileDialog dialog = new() { AllowMultiple = false }; dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance[LocaleKeys.FileDialogAllTypes], Extensions = { "xci", "zip" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "ZIP", Extensions = { "zip" } }); + dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } }); + dialog.Filters.Add(new FileDialogFilter { Name = "ZIP", Extensions = { "zip" } }); string[] file = await dialog.ShowAsync(desktop.MainWindow); @@ -1278,7 +1289,7 @@ namespace Ryujinx.Ava.UI.ViewModels public async void InstallFirmwareFromFolder() { - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { OpenFolderDialog dialog = new(); @@ -1327,7 +1338,7 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public void ChangeLanguage(object languageCode) + public static void ChangeLanguage(object languageCode) { LocaleManager.Instance.LoadLanguage((string)languageCode); @@ -1342,6 +1353,7 @@ namespace Ryujinx.Ava.UI.ViewModels { _ = fileType switch { +#pragma warning disable IDE0055 // Disable formatting "NSP" => ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSP, "PFS0" => ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.PFS0, "XCI" => ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.XCI, @@ -1349,6 +1361,7 @@ namespace Ryujinx.Ava.UI.ViewModels "NRO" => ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NRO, "NSO" => ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSO, _ => throw new ArgumentOutOfRangeException(fileType), +#pragma warning restore IDE0055 }; ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); @@ -1371,9 +1384,9 @@ namespace Ryujinx.Ava.UI.ViewModels { Applications.Clear(); - StatusBarVisible = true; + StatusBarVisible = true; StatusBarProgressMaximum = 0; - StatusBarProgressValue = 0; + StatusBarProgressValue = 0; LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); }); @@ -1383,11 +1396,11 @@ namespace Ryujinx.Ava.UI.ViewModels public async void OpenFile() { - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { OpenFileDialog dialog = new() { - Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle] + Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], }; dialog.Filters.Add(new FileDialogFilter @@ -1400,16 +1413,18 @@ namespace Ryujinx.Ava.UI.ViewModels "xci", "nca", "nro", - "nso" - } + "nso", + }, }); +#pragma warning disable IDE0055 // Disable formatting dialog.Filters.Add(new FileDialogFilter { Name = "NSP", Extensions = { "nsp" } }); dialog.Filters.Add(new FileDialogFilter { Name = "PFS0", Extensions = { "pfs0" } }); dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } }); dialog.Filters.Add(new FileDialogFilter { Name = "NCA", Extensions = { "nca" } }); dialog.Filters.Add(new FileDialogFilter { Name = "NRO", Extensions = { "nro" } }); dialog.Filters.Add(new FileDialogFilter { Name = "NSO", Extensions = { "nso" } }); +#pragma warning restore IDE0055 string[] files = await dialog.ShowAsync(desktop.MainWindow); @@ -1422,11 +1437,11 @@ namespace Ryujinx.Ava.UI.ViewModels public async void OpenFolder() { - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { OpenFolderDialog dialog = new() { - Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle] + Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], }; string folder = await dialog.ShowAsync(desktop.MainWindow); @@ -1458,10 +1473,7 @@ namespace Ryujinx.Ava.UI.ViewModels Logger.RestartTime(); - if (SelectedIcon == null) - { - SelectedIcon = ApplicationLibrary.GetApplicationIcon(path); - } + SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(path); PrepareLoadScreen(); @@ -1495,7 +1507,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (string.IsNullOrWhiteSpace(titleName)) { LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Processes.ActiveApplication.Name); - TitleName = AppHost.Device.Processes.ActiveApplication.Name; + TitleName = AppHost.Device.Processes.ActiveApplication.Name; } SwitchToRenderer(startFullscreen); @@ -1521,7 +1533,7 @@ namespace Ryujinx.Ava.UI.ViewModels }); } - public void UpdateGameMetadata(string titleId) + public static void UpdateGameMetadata(string titleId) { ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => { @@ -1675,6 +1687,6 @@ namespace Ryujinx.Ava.UI.ViewModels } } -#endregion + #endregion } } diff --git a/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs index d57ccc6bb..0b12a51f6 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs @@ -90,4 +90,4 @@ namespace Ryujinx.Ava.UI.ViewModels } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs index 2d53968f7..49de19937 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs @@ -24,4 +24,4 @@ namespace Ryujinx.Ava.UI.ViewModels } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs index 0a2ffae3b..a9eb9c618 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs @@ -18,7 +18,6 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Time.TimeZone; using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration.System; -using Silk.NET.Vulkan; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -248,7 +247,7 @@ namespace Ryujinx.Ava.UI.ViewModels public AvaloniaList NetworkInterfaceList { - get => new AvaloniaList(_networkInterfaces.Keys); + get => new(_networkInterfaces.Keys); } public KeyboardHotkeys KeyboardHotkeys @@ -561,7 +560,7 @@ namespace Ryujinx.Ava.UI.ViewModels _directoryChanged = false; } - public void RevertIfNotSaved() + private static void RevertIfNotSaved() { Program.ReloadConfig(); } @@ -583,4 +582,4 @@ namespace Ryujinx.Ava.UI.ViewModels CloseWindow?.Invoke(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs index 1f4e3c624..740d888bb 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs @@ -1,3 +1,4 @@ +using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; @@ -16,7 +17,6 @@ using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; using Ryujinx.HLE.FileSystem; -using Ryujinx.HLE.HOS; using Ryujinx.Ui.App.Common; using System; using System.Collections.Generic; @@ -29,17 +29,16 @@ namespace Ryujinx.Ava.UI.ViewModels { public class TitleUpdateViewModel : BaseModel { - public TitleUpdateMetadata _titleUpdateWindowData; - public readonly string _titleUpdateJsonPath; - private VirtualFileSystem _virtualFileSystem { get; } - private ulong _titleId { get; } - private string _titleName { get; } + public TitleUpdateMetadata TitleUpdateWindowData; + public readonly string TitleUpdateJsonPath; + private VirtualFileSystem VirtualFileSystem { get; } + private ulong TitleId { get; } private AvaloniaList _titleUpdates = new(); private AvaloniaList _views = new(); private object _selectedUpdate; - private static readonly TitleUpdateMetadataJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); public AvaloniaList TitleUpdates { @@ -71,27 +70,26 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public TitleUpdateViewModel(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) + public TitleUpdateViewModel(VirtualFileSystem virtualFileSystem, ulong titleId) { - _virtualFileSystem = virtualFileSystem; + VirtualFileSystem = virtualFileSystem; - _titleId = titleId; - _titleName = titleName; + TitleId = titleId; - _titleUpdateJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "updates.json"); + TitleUpdateJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "updates.json"); try { - _titleUpdateWindowData = JsonHelper.DeserializeFromFile(_titleUpdateJsonPath, SerializerContext.TitleUpdateMetadata); + TitleUpdateWindowData = JsonHelper.DeserializeFromFile(TitleUpdateJsonPath, _serializerContext.TitleUpdateMetadata); } catch { - Logger.Warning?.Print(LogClass.Application, $"Failed to deserialize title update data for {_titleId} at {_titleUpdateJsonPath}"); + Logger.Warning?.Print(LogClass.Application, $"Failed to deserialize title update data for {TitleId} at {TitleUpdateJsonPath}"); - _titleUpdateWindowData = new TitleUpdateMetadata + TitleUpdateWindowData = new TitleUpdateMetadata { Selected = "", - Paths = new List() + Paths = new List(), }; Save(); @@ -102,12 +100,12 @@ namespace Ryujinx.Ava.UI.ViewModels private void LoadUpdates() { - foreach (string path in _titleUpdateWindowData.Paths) + foreach (string path in TitleUpdateWindowData.Paths) { AddUpdate(path); } - TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == _titleUpdateWindowData.Selected, null); + TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == TitleUpdateWindowData.Selected, null); SelectedUpdate = selected; @@ -126,7 +124,8 @@ namespace Ryujinx.Ava.UI.ViewModels { return -1; } - else if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString())) + + if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString())) { return 1; } @@ -163,7 +162,7 @@ namespace Ryujinx.Ava.UI.ViewModels try { - (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(_virtualFileSystem, new PartitionFileSystem(file.AsStorage()), _titleId.ToString("x16"), 0); + (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(VirtualFileSystem, new PartitionFileSystem(file.AsStorage()), TitleId.ToString("x16"), 0); if (controlNca != null && patchNca != null) { @@ -205,17 +204,17 @@ namespace Ryujinx.Ava.UI.ViewModels { OpenFileDialog dialog = new() { - Title = LocaleManager.Instance[LocaleKeys.SelectUpdateDialogTitle], - AllowMultiple = true + Title = LocaleManager.Instance[LocaleKeys.SelectUpdateDialogTitle], + AllowMultiple = true, }; dialog.Filters.Add(new FileDialogFilter { - Name = "NSP", - Extensions = { "nsp" } + Name = "NSP", + Extensions = { "nsp" }, }); - if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { string[] files = await dialog.ShowAsync(desktop.MainWindow); @@ -233,20 +232,20 @@ namespace Ryujinx.Ava.UI.ViewModels public void Save() { - _titleUpdateWindowData.Paths.Clear(); - _titleUpdateWindowData.Selected = ""; + TitleUpdateWindowData.Paths.Clear(); + TitleUpdateWindowData.Selected = ""; foreach (TitleUpdateModel update in TitleUpdates) { - _titleUpdateWindowData.Paths.Add(update.Path); + TitleUpdateWindowData.Paths.Add(update.Path); if (update == SelectedUpdate) { - _titleUpdateWindowData.Selected = update.Path; + TitleUpdateWindowData.Selected = update.Path; } } - JsonHelper.SerializeToFile(_titleUpdateJsonPath, _titleUpdateWindowData, SerializerContext.TitleUpdateMetadata); + JsonHelper.SerializeToFile(TitleUpdateJsonPath, TitleUpdateWindowData, _serializerContext.TitleUpdateMetadata); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs index 558cad5a7..cb8da9ede 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs @@ -28,7 +28,6 @@ namespace Ryujinx.Ava.UI.ViewModels private Color _backgroundColor = Colors.White; private int _selectedIndex; - private byte[] _selectedImage; public UserFirmwareAvatarSelectorViewModel() { @@ -78,11 +77,7 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public byte[] SelectedImage - { - get => _selectedImage; - private set => _selectedImage = value; - } + public byte[] SelectedImage { get; private set; } private void LoadImagesFromStore() { @@ -114,34 +109,32 @@ namespace Ryujinx.Ava.UI.ViewModels if (!string.IsNullOrWhiteSpace(avatarPath)) { - using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open)) + using IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open); + + Nca nca = new(virtualFileSystem.KeySet, ncaFileStream); + IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); + + foreach (DirectoryEntryEx item in romfs.EnumerateEntries()) { - Nca nca = new(virtualFileSystem.KeySet, ncaFileStream); - IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); - - foreach (DirectoryEntryEx item in romfs.EnumerateEntries()) + // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy. + if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs")) { - // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy. - if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs")) - { - using var file = new UniqueRef(); + using var file = new UniqueRef(); - romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure(); + romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure(); - using (MemoryStream stream = new()) - using (MemoryStream streamPng = new()) - { - file.Get.AsStream().CopyTo(stream); + using MemoryStream stream = new(); + using MemoryStream streamPng = new(); - stream.Position = 0; + file.Get.AsStream().CopyTo(stream); - Image avatarImage = Image.LoadPixelData(DecompressYaz0(stream), 256, 256); + stream.Position = 0; - avatarImage.SaveAsPng(streamPng); + Image avatarImage = Image.LoadPixelData(DecompressYaz0(stream), 256, 256); - _avatarStore.Add(item.FullPath, streamPng.ToArray()); - } - } + avatarImage.SaveAsPng(streamPng); + + _avatarStore.Add(item.FullPath, streamPng.ToArray()); } } } @@ -149,82 +142,81 @@ namespace Ryujinx.Ava.UI.ViewModels private static byte[] DecompressYaz0(Stream stream) { - using (BinaryReader reader = new(stream)) + using BinaryReader reader = new(stream); + + reader.ReadInt32(); // Magic + + uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32()); + + reader.ReadInt64(); // Padding + + byte[] input = new byte[stream.Length - stream.Position]; + stream.Read(input, 0, input.Length); + + uint inputOffset = 0; + + byte[] output = new byte[decodedLength]; + uint outputOffset = 0; + + ushort mask = 0; + byte header = 0; + + while (outputOffset < decodedLength) { - reader.ReadInt32(); // Magic - - uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32()); - - reader.ReadInt64(); // Padding - - byte[] input = new byte[stream.Length - stream.Position]; - stream.Read(input, 0, input.Length); - - uint inputOffset = 0; - - byte[] output = new byte[decodedLength]; - uint outputOffset = 0; - - ushort mask = 0; - byte header = 0; - - while (outputOffset < decodedLength) + if ((mask >>= 1) == 0) { - if ((mask >>= 1) == 0) + header = input[inputOffset++]; + mask = 0x80; + } + + if ((header & mask) != 0) + { + if (outputOffset == output.Length) { - header = input[inputOffset++]; - mask = 0x80; + break; } - if ((header & mask) != 0) - { - if (outputOffset == output.Length) - { - break; - } + output[outputOffset++] = input[inputOffset++]; + } + else + { + byte byte1 = input[inputOffset++]; + byte byte2 = input[inputOffset++]; - output[outputOffset++] = input[inputOffset++]; + uint dist = (uint)((byte1 & 0xF) << 8) | byte2; + uint position = outputOffset - (dist + 1); + + uint length = (uint)byte1 >> 4; + if (length == 0) + { + length = (uint)input[inputOffset++] + 0x12; } else { - byte byte1 = input[inputOffset++]; - byte byte2 = input[inputOffset++]; + length += 2; + } - uint dist = (uint)((byte1 & 0xF) << 8) | byte2; - uint position = outputOffset - (dist + 1); + uint gap = outputOffset - position; + uint nonOverlappingLength = length; - uint length = (uint)byte1 >> 4; - if (length == 0) - { - length = (uint)input[inputOffset++] + 0x12; - } - else - { - length += 2; - } + if (nonOverlappingLength > gap) + { + nonOverlappingLength = gap; + } - uint gap = outputOffset - position; - uint nonOverlappingLength = length; + Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength); + outputOffset += nonOverlappingLength; + position += nonOverlappingLength; + length -= nonOverlappingLength; - if (nonOverlappingLength > gap) - { - nonOverlappingLength = gap; - } - - Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength); - outputOffset += nonOverlappingLength; - position += nonOverlappingLength; - length -= nonOverlappingLength; - - while (length-- > 0) - { - output[outputOffset++] = output[position++]; - } + while (length-- > 0) + { + output[outputOffset++] = output[position++]; } } - - return output; } + + return output; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/UserProfileImageSelectorViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/UserProfileImageSelectorViewModel.cs index 7261631c1..8e7d41a55 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/UserProfileImageSelectorViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/UserProfileImageSelectorViewModel.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool FirmwareFound { get => _firmwareFound; - + set { _firmwareFound = value; @@ -15,4 +15,4 @@ namespace Ryujinx.Ava.UI.ViewModels } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs index 8f997efc1..70274847f 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs @@ -1,7 +1,7 @@ using Microsoft.IdentityModel.Tokens; +using Ryujinx.Ava.UI.Models; using System; using System.Collections.ObjectModel; -using UserProfile = Ryujinx.Ava.UI.Models.UserProfile; namespace Ryujinx.Ava.UI.ViewModels { @@ -20,6 +20,9 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsEmpty { get; set; } - public void Dispose() { } + public void Dispose() + { + GC.SuppressFinalize(this); + } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs index 097634a80..0a13f24a8 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.ViewModels private string _search; private ObservableCollection _saves = new(); private ObservableCollection _views = new(); - private AccountManager _accountManager; + private readonly AccountManager _accountManager; public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId); @@ -102,19 +102,16 @@ namespace Ryujinx.Ava.UI.ViewModels private IComparer GetComparer() { - switch (SortIndex) + return SortIndex switch { - case 0: - return OrderIndex == 0 - ? SortExpressionComparer.Ascending(save => save.Title) - : SortExpressionComparer.Descending(save => save.Title); - case 1: - return OrderIndex == 0 - ? SortExpressionComparer.Ascending(save => save.Size) - : SortExpressionComparer.Descending(save => save.Size); - default: - return null; - } + 0 => OrderIndex == 0 + ? SortExpressionComparer.Ascending(save => save.Title) + : SortExpressionComparer.Descending(save => save.Title), + 1 => OrderIndex == 0 + ? SortExpressionComparer.Ascending(save => save.Size) + : SortExpressionComparer.Descending(save => save.Size), + _ => null, + }; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs index 8fe7b9412..19009f5f2 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs @@ -29,7 +29,7 @@ namespace Ryujinx.Ava.UI.Views.Input foreach (ILogical visual in SettingButtons.GetLogicalDescendants()) { - if (visual is ToggleButton button && !(visual is CheckBox)) + if (visual is ToggleButton button && visual is not CheckBox) { button.Checked += Button_Checked; button.Unchecked += Button_Unchecked; @@ -177,4 +177,4 @@ namespace Ryujinx.Ava.UI.Views.Input ViewModel.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs index 88bbcd932..1b340752b 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs @@ -10,7 +10,7 @@ namespace Ryujinx.Ava.UI.Views.Input { public partial class MotionInputView : UserControl { - private MotionInputViewModel _viewModel; + private readonly MotionInputViewModel _viewModel; public MotionInputView() { @@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Input MirrorInput = config.MirrorInput, Sensitivity = config.Sensitivity, GyroDeadzone = config.GyroDeadzone, - EnableCemuHookMotion = config.EnableCemuHookMotion + EnableCemuHookMotion = config.EnableCemuHookMotion, }; InitializeComponent(); @@ -47,7 +47,7 @@ namespace Ryujinx.Ava.UI.Views.Input PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave], SecondaryButtonText = "", CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose], - Content = content + Content = content, }; contentDialog.PrimaryButtonClick += (sender, args) => { @@ -65,4 +65,4 @@ namespace Ryujinx.Ava.UI.Views.Input await contentDialog.ShowAsync(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs index dfe05b08b..9307f872c 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs @@ -10,7 +10,7 @@ namespace Ryujinx.Ava.UI.Views.Input { public partial class RumbleInputView : UserControl { - private RumbleInputViewModel _viewModel; + private readonly RumbleInputViewModel _viewModel; public RumbleInputView() { @@ -24,11 +24,11 @@ namespace Ryujinx.Ava.UI.Views.Input _viewModel = new RumbleInputViewModel { StrongRumble = config.StrongRumble, - WeakRumble = config.WeakRumble + WeakRumble = config.WeakRumble, }; InitializeComponent(); - + DataContext = _viewModel; } @@ -55,4 +55,4 @@ namespace Ryujinx.Ava.UI.Views.Input await contentDialog.ShowAsync(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs index f94b80d45..ae52f0719 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs @@ -38,26 +38,26 @@ namespace Ryujinx.Ava.UI.Views.Main { List checkBoxes = new(); - foreach (var item in Enum.GetValues(typeof (FileTypes))) + foreach (var item in Enum.GetValues(typeof(FileTypes))) { - string fileName = Enum.GetName(typeof (FileTypes), item); - checkBoxes.Add(new CheckBox() + string fileName = Enum.GetName(typeof(FileTypes), item); + checkBoxes.Add(new CheckBox { Content = $".{fileName}", IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.Ui.ShownFileTypes), - Command = MiniCommand.Create(() => ViewModel.ToggleFileType(fileName)) + Command = MiniCommand.Create(() => ViewModel.ToggleFileType(fileName)), }); } return checkBoxes.ToArray(); } - private MenuItem[] GenerateLanguageMenuItems() + private static MenuItem[] GenerateLanguageMenuItems() { List menuItems = new(); string localePath = "Ryujinx.Ava/Assets/Locales"; - string localeExt = ".json"; + string localeExt = ".json"; string[] localesPath = EmbeddedResources.GetAllAvailableResources(localePath, localeExt); @@ -67,7 +67,7 @@ namespace Ryujinx.Ava.UI.Views.Main { string languageCode = Path.GetFileNameWithoutExtension(locale).Split('.').Last(); string languageJson = EmbeddedResources.ReadAllText($"{localePath}/{languageCode}{localeExt}"); - var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary); + var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary); if (!strings.TryGetValue("Language", out string languageName)) { @@ -76,11 +76,11 @@ namespace Ryujinx.Ava.UI.Views.Main MenuItem menuItem = new() { - Header = languageName, + Header = languageName, Command = MiniCommand.Create(() => { - ViewModel.ChangeLanguage(languageCode); - }) + MainWindowViewModel.ChangeLanguage(languageCode); + }), }; menuItems.Add(menuItem); @@ -236,4 +236,4 @@ namespace Ryujinx.Ava.UI.Views.Main Window.Close(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs index 473de0ee2..0640869c1 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs @@ -49,4 +49,4 @@ namespace Ryujinx.Ava.UI.Views.Main ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs index fd7578939..9163222f4 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Ava.UI.Views.Main public partial class MainViewControls : UserControl { public MainWindowViewModel ViewModel; - + public MainViewControls() { InitializeComponent(); @@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Views.Main ViewModel.Sort(Enum.Parse(button.Tag.ToString())); } } - + public void Order_Checked(object sender, RoutedEventArgs args) { if (sender is RadioButton button) @@ -45,10 +45,10 @@ namespace Ryujinx.Ava.UI.Views.Main ViewModel.Sort(button.Tag.ToString() != "Descending"); } } - + private void SearchBox_OnKeyUp(object sender, KeyEventArgs e) { ViewModel.SearchText = SearchBox.Text; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs index 026c7fdf8..f9f93ba3c 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings InitializeComponent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs index 5c5b60793..47a640e08 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings InitializeComponent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs index 8fe08552e..56b966523 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings InitializeComponent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs index 702f73e87..4bbd0133a 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -12,12 +12,12 @@ namespace Ryujinx.Ava.UI.Views.Settings public partial class SettingsHotkeysView : UserControl { private ButtonKeyAssigner _currentAssigner; - private IGamepadDriver AvaloniaKeyboardDriver; - + private readonly IGamepadDriver _avaloniaKeyboardDriver; + public SettingsHotkeysView() { InitializeComponent(); - AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this); + _avaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this); } private void MouseClick(object sender, PointerPressedEventArgs e) @@ -28,7 +28,7 @@ namespace Ryujinx.Ava.UI.Views.Settings PointerPressed -= MouseClick; } - + private void Button_Checked(object sender, RoutedEventArgs e) { if (sender is ToggleButton button) @@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.Views.Settings PointerPressed += MouseClick; - var keyboard = (IKeyboard)AvaloniaKeyboardDriver.GetGamepad(AvaloniaKeyboardDriver.GamepadsIds[0]); + var keyboard = (IKeyboard)_avaloniaKeyboardDriver.GetGamepad(_avaloniaKeyboardDriver.GamepadsIds[0]); IButtonAssigner assigner = new KeyboardKeyAssigner(keyboard); _currentAssigner.GetInputAndAssign(assigner); @@ -78,4 +78,4 @@ namespace Ryujinx.Ava.UI.Views.Settings _currentAssigner = null; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs index 0c2105ec4..8a0cb8ab9 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs @@ -14,4 +14,4 @@ namespace Ryujinx.Ava.UI.Views.Settings ControllerSettings.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs index 2ec476ac6..f18f73390 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings InitializeComponent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs index d7407b9d5..bf728f410 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings InitializeComponent(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs index d2ea59deb..4acf2f44c 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.Views.Settings public SettingsSystemView() { InitializeComponent(); - + FuncMultiValueConverter converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()).Trim()); MultiBinding tzMultiBinding = new() { Converter = converter }; @@ -49,4 +49,4 @@ namespace Ryujinx.Ava.UI.Views.Settings } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml index acc5e2b70..c92d56728 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml @@ -1,5 +1,5 @@  0x20; + public static uint MaxProfileNameLength => 0x20; public bool IsDeletable => _profile.UserId != AccountManager.DefaultUserId; public UserEditorView() @@ -39,17 +39,17 @@ namespace Ryujinx.Ava.UI.Views.User switch (arg.NavigationMode) { case NavigationMode.New: - var args = ((NavigationDialogHost parent, UserProfile profile, bool isNewUser))arg.Parameter; - _isNewUser = args.isNewUser; - _profile = args.profile; + var (parent, profile, isNewUser) = ((NavigationDialogHost parent, UserProfile profile, bool isNewUser))arg.Parameter; + _isNewUser = isNewUser; + _profile = profile; TempProfile = new TempProfile(_profile); - _parent = args.parent; + _parent = parent; break; } ((ContentDialog)_parent.Parent).Title = $"{LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle]} - " + - $"{ (_isNewUser ? LocaleManager.Instance[LocaleKeys.UserEditorTitleCreate] : LocaleManager.Instance[LocaleKeys.UserEditorTitle])}"; + $"{(_isNewUser ? LocaleManager.Instance[LocaleKeys.UserEditorTitleCreate] : LocaleManager.Instance[LocaleKeys.UserEditorTitle])}"; DataContext = TempProfile; @@ -162,4 +162,4 @@ namespace Ryujinx.Ava.UI.Views.User } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs index 7c9191ab2..b6376866d 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs @@ -11,6 +11,7 @@ using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using System.IO; +using Image = SixLabors.ImageSharp.Image; namespace Ryujinx.Ava.UI.Views.User { @@ -70,7 +71,7 @@ namespace Ryujinx.Ava.UI.Views.User if (ViewModel.SelectedImage != null) { MemoryStream streamJpg = new(); - SixLabors.ImageSharp.Image avatarImage = SixLabors.ImageSharp.Image.Load(ViewModel.SelectedImage, new PngDecoder()); + Image avatarImage = Image.Load(ViewModel.SelectedImage, new PngDecoder()); avatarImage.Mutate(x => x.BackgroundColor(new Rgba32( ViewModel.BackgroundColor.R, @@ -85,4 +86,4 @@ namespace Ryujinx.Ava.UI.Views.User } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 18f76f805..26b77dcdc 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -67,7 +67,7 @@ namespace Ryujinx.Ava.UI.Views.User dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance[LocaleKeys.AllSupportedFormats], - Extensions = { "jpg", "jpeg", "png", "bmp" } + Extensions = { "jpg", "jpeg", "png", "bmp" }, }); dialog.Filters.Add(new FileDialogFilter { Name = "JPEG", Extensions = { "jpg", "jpeg" } }); dialog.Filters.Add(new FileDialogFilter { Name = "PNG", Extensions = { "png" } }); @@ -108,17 +108,15 @@ namespace Ryujinx.Ava.UI.Views.User private static byte[] ProcessProfileImage(byte[] buffer) { - using (Image image = Image.Load(buffer)) - { - image.Mutate(x => x.Resize(256, 256)); + using Image image = Image.Load(buffer); - using (MemoryStream streamJpg = new()) - { - image.SaveAsJpeg(streamJpg); + image.Mutate(x => x.Resize(256, 256)); - return streamJpg.ToArray(); - } - } + using MemoryStream streamJpg = new(); + + image.SaveAsJpeg(streamJpg); + + return streamJpg.ToArray(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs index 0c53e53d7..31934349d 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs @@ -48,4 +48,4 @@ namespace Ryujinx.Ava.UI.Views.User _parent?.RecoverLostAccounts(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs index 08fef27d0..00a229fae 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs @@ -18,6 +18,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc; using System; using System.Collections.ObjectModel; using System.Threading.Tasks; +using Button = Avalonia.Controls.Button; using UserId = LibHac.Fs.UserId; namespace Ryujinx.Ava.UI.Views.User @@ -47,12 +48,12 @@ namespace Ryujinx.Ava.UI.Views.User switch (arg.NavigationMode) { case NavigationMode.New: - var args = ((NavigationDialogHost parent, AccountManager accountManager, HorizonClient client, VirtualFileSystem virtualFileSystem))arg.Parameter; - _accountManager = args.accountManager; - _horizonClient = args.client; - _virtualFileSystem = args.virtualFileSystem; + var (parent, accountManager, client, virtualFileSystem) = ((NavigationDialogHost parent, AccountManager accountManager, HorizonClient client, VirtualFileSystem virtualFileSystem))arg.Parameter; + _accountManager = accountManager; + _horizonClient = client; + _virtualFileSystem = virtualFileSystem; - _parent = args.parent; + _parent = parent; break; } @@ -94,7 +95,7 @@ namespace Ryujinx.Ava.UI.Views.User var save = saveDataInfo[i]; if (save.ProgramId.Value != 0) { - var saveModel = new SaveModel(save, _virtualFileSystem); + var saveModel = new SaveModel(save); saves.Add(saveModel); } } @@ -114,7 +115,7 @@ namespace Ryujinx.Ava.UI.Views.User private void OpenLocation(object sender, RoutedEventArgs e) { - if (sender is Avalonia.Controls.Button button) + if (sender is Button button) { if (button.DataContext is SaveModel saveModel) { @@ -125,7 +126,7 @@ namespace Ryujinx.Ava.UI.Views.User private async void Delete(object sender, RoutedEventArgs e) { - if (sender is Avalonia.Controls.Button button) + if (sender is Button button) { if (button.DataContext is SaveModel saveModel) { @@ -144,4 +145,4 @@ namespace Ryujinx.Ava.UI.Views.User } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs index aa89fea9e..fa3383aa9 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs @@ -5,8 +5,9 @@ using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Navigation; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; +using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; -using UserProfile = Ryujinx.Ava.UI.Models.UserProfile; +using Button = Avalonia.Controls.Button; namespace Ryujinx.Ava.UI.Views.User { @@ -101,7 +102,7 @@ namespace Ryujinx.Ava.UI.Views.User private void EditUser(object sender, RoutedEventArgs e) { - if (sender is Avalonia.Controls.Button button) + if (sender is Button button) { if (button.DataContext is UserProfile userProfile) { @@ -125,4 +126,4 @@ namespace Ryujinx.Ava.UI.Views.User ((ContentDialog)_parent.Parent).Hide(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs index 36a28605f..ca1c40350 100644 --- a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs @@ -1,6 +1,7 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.Layout; using Avalonia.Styling; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; @@ -25,17 +26,17 @@ namespace Ryujinx.Ava.UI.Windows { ContentDialog contentDialog = new() { - PrimaryButtonText = "", + PrimaryButtonText = "", SecondaryButtonText = "", - CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose], - Content = new AboutWindow() + CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose], + Content = new AboutWindow(), }; Style closeButton = new(x => x.Name("CloseButton")); closeButton.Setters.Add(new Setter(WidthProperty, 80d)); Style closeButtonParent = new(x => x.Name("CommandSpace")); - closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty, Avalonia.Layout.HorizontalAlignment.Right)); + closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty, HorizontalAlignment.Right)); contentDialog.Styles.Add(closeButton); contentDialog.Styles.Add(closeButtonParent); @@ -59,4 +60,4 @@ namespace Ryujinx.Ava.UI.Windows } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs index 206d0a7ea..57106638a 100644 --- a/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs @@ -9,9 +9,10 @@ namespace Ryujinx.Ava.UI.Windows { public AmiiboWindow(bool showAll, string lastScannedAmiiboId, string titleId) { - ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId); - - ViewModel.ShowAllAmiibo = showAll; + ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId) + { + ShowAllAmiibo = showAll, + }; DataContext = ViewModel; @@ -56,4 +57,4 @@ namespace Ryujinx.Ava.UI.Windows Close(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs index f5bba7d2d..df6b123bd 100644 --- a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs @@ -1,11 +1,12 @@ -using Avalonia; -using Avalonia.Collections; +using Avalonia.Collections; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Models; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using Ryujinx.Ui.App.Common; +using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; @@ -36,16 +37,16 @@ namespace Ryujinx.Ava.UI.Windows Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper()); BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath); - + InitializeComponent(); string modsBasePath = ModLoader.GetModsBasePath(); string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId); - ulong titleIdValue = ulong.Parse(titleId, System.Globalization.NumberStyles.HexNumber); + ulong titleIdValue = ulong.Parse(titleId, NumberStyles.HexNumber); _enabledCheatsPath = Path.Combine(titleModsPath, "cheats", "enabled.txt"); - string[] enabled = { }; + string[] enabled = Array.Empty(); if (File.Exists(_enabledCheatsPath)) { @@ -60,7 +61,6 @@ namespace Ryujinx.Ava.UI.Windows string currentCheatFile = string.Empty; string buildId = string.Empty; - string parentPath = string.Empty; CheatsList currentGroup = null; @@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Windows if (cheat.Path.FullName != currentCheatFile) { currentCheatFile = cheat.Path.FullName; - parentPath = currentCheatFile.Replace(titleModsPath, ""); + string parentPath = currentCheatFile.Replace(titleModsPath, ""); buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper(); currentGroup = new CheatsList(buildId, parentPath); @@ -89,7 +89,7 @@ namespace Ryujinx.Ava.UI.Windows } DataContext = this; - + Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle]; } @@ -100,7 +100,7 @@ namespace Ryujinx.Ava.UI.Windows return; } - List enabledCheats = new List(); + List enabledCheats = new(); foreach (var cheats in LoadedCheats) { @@ -120,4 +120,4 @@ namespace Ryujinx.Ava.UI.Windows Close(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs index 3f77124d9..a33ee518b 100644 --- a/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs @@ -1,7 +1,8 @@ -using Avalonia; using Avalonia.Controls; -using Avalonia.Markup.Xaml; using Avalonia.Media; +#if DEBUG +using Avalonia; +#endif namespace Ryujinx.Ava.UI.Windows { @@ -22,4 +23,4 @@ namespace Ryujinx.Ava.UI.Windows CanResize = false; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml b/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml index fe446fb3e..f4ba4f9c9 100644 --- a/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml @@ -89,8 +89,8 @@ - - + + x.OfType().Name("DialogSpace").Child().OfType()); @@ -112,4 +112,4 @@ namespace Ryujinx.Ava.UI.Windows } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/IconColorPicker.cs b/src/Ryujinx.Ava/UI/Windows/IconColorPicker.cs index a4c6287f3..4c75a5ff9 100644 --- a/src/Ryujinx.Ava/UI/Windows/IconColorPicker.cs +++ b/src/Ryujinx.Ava/UI/Windows/IconColorPicker.cs @@ -68,8 +68,10 @@ namespace Ryujinx.Ava.UI.Windows int w8 = w << 8; int h8 = image.Height << 8; +#pragma warning disable IDE0059 // Unnecessary assignment int xStep = w8 / ColorsPerLine; int yStep = h8 / ColorsPerLine; +#pragma warning restore IDE0059 int i = 0; int maxHitCount = 0; diff --git a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs index 66988c4b3..d79bdc56a 100644 --- a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs @@ -155,7 +155,7 @@ namespace Ryujinx.Ava.UI.Windows Dispatcher.UIThread.Post(() => { - ViewModel.StatusBarProgressValue = e.NumAppsLoaded; + ViewModel.StatusBarProgressValue = e.NumAppsLoaded; ViewModel.StatusBarProgressMaximum = e.NumAppsFound; if (e.NumAppsFound == 0) @@ -323,7 +323,7 @@ namespace Ryujinx.Ava.UI.Windows ShowKeyErrorOnLoad = false; Dispatcher.UIThread.Post(async () => await - UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, this)); + UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys)); } if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount) @@ -373,24 +373,26 @@ namespace Ryujinx.Ava.UI.Windows private void SetWindowSizePosition() { - PixelPoint SavedPoint = new PixelPoint(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX, + PixelPoint savedPoint = new(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX, ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY); ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor; ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor; ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value is true ? WindowState.Maximized : WindowState.Normal; - - if (CheckScreenBounds(SavedPoint)) - { - Position = SavedPoint; - } - else WindowStartupLocation = WindowStartupLocation.CenterScreen; + if (CheckScreenBounds(savedPoint)) + { + Position = savedPoint; + } + else + { + WindowStartupLocation = WindowStartupLocation.CenterScreen; + } } private bool CheckScreenBounds(PixelPoint configPoint) - { + { for (int i = 0; i < Screens.ScreenCount; i++) { if (Screens.All[i].Bounds.Contains(configPoint)) @@ -399,7 +401,7 @@ namespace Ryujinx.Ava.UI.Windows } } - Logger.Warning?.Print(LogClass.Application, $"Failed to find valid start-up coordinates. Defaulting to primary monitor center."); + Logger.Warning?.Print(LogClass.Application, "Failed to find valid start-up coordinates. Defaulting to primary monitor center."); return false; } @@ -425,10 +427,7 @@ namespace Ryujinx.Ava.UI.Windows private void SetMainContent(Control content = null) { - if (content == null) - { - content = GameLibrary; - } + content ??= GameLibrary; if (MainContent.Content != content) { @@ -438,21 +437,25 @@ namespace Ryujinx.Ava.UI.Windows public static void UpdateGraphicsConfig() { +#pragma warning disable IDE0055 // Disable formatting GraphicsConfig.ResScale = ConfigurationState.Instance.Graphics.ResScale == -1 ? ConfigurationState.Instance.Graphics.ResScaleCustom : ConfigurationState.Instance.Graphics.ResScale; GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache; GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression; GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE; +#pragma warning restore IDE0055 } public void LoadHotKeys() { +#pragma warning disable IDE0055 // Disable formatting HotKeyManager.SetHotKey(FullscreenHotKey, new KeyGesture(Key.Enter, KeyModifiers.Alt)); HotKeyManager.SetHotKey(FullscreenHotKey2, new KeyGesture(Key.F11)); HotKeyManager.SetHotKey(FullscreenHotKeyMacOS, new KeyGesture(Key.F, KeyModifiers.Control | KeyModifiers.Meta)); HotKeyManager.SetHotKey(DockToggleHotKey, new KeyGesture(Key.F9)); HotKeyManager.SetHotKey(ExitHotKey, new KeyGesture(Key.Escape)); +#pragma warning restore IDE0055 } private void VolumeStatus_CheckedChanged(object sender, SplitButtonClickEventArgs e) @@ -536,8 +539,8 @@ namespace Ryujinx.Ava.UI.Windows ViewModel.Applications.Clear(); StatusBarView.LoadProgressBar.IsVisible = true; - ViewModel.StatusBarProgressMaximum = 0; - ViewModel.StatusBarProgressValue = 0; + ViewModel.StatusBarProgressMaximum = 0; + ViewModel.StatusBarProgressValue = 0; LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); }); @@ -559,4 +562,4 @@ namespace Ryujinx.Ava.UI.Windows _isLoading = false; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml index a44cbfe7d..4b248db79 100644 --- a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml @@ -34,7 +34,7 @@ IsVisible="False" KeyboardNavigation.IsTabStop="False"/> - + @@ -125,4 +125,4 @@ Command="{ReflectionBinding ApplyButton}" /> - \ No newline at end of file + diff --git a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs index bdf7e94d8..518c2d328 100644 --- a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Ava.UI.Windows { Title = $"Ryujinx {Program.Version} - {LocaleManager.Instance[LocaleKeys.Settings]}"; - ViewModel = new SettingsViewModel(virtualFileSystem, contentManager); + ViewModel = new SettingsViewModel(virtualFileSystem, contentManager); DataContext = ViewModel; ViewModel.CloseWindow += Close; @@ -28,7 +28,7 @@ namespace Ryujinx.Ava.UI.Windows public SettingsWindow() { - ViewModel = new SettingsViewModel(); + ViewModel = new SettingsViewModel(); DataContext = ViewModel; InitializeComponent(); @@ -100,4 +100,4 @@ namespace Ryujinx.Ava.UI.Windows base.OnClosing(e); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs index a157f1547..ca23a5ba3 100644 --- a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs +++ b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs @@ -2,6 +2,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Media.Imaging; using Avalonia.Platform; +using Ryujinx.Ui.Common.Configuration; using System; using System.IO; using System.Reflection; @@ -17,7 +18,7 @@ namespace Ryujinx.Ava.UI.Windows WindowStartupLocation = WindowStartupLocation.CenterOwner; TransparencyLevelHint = WindowTransparencyLevel.None; - using Stream stream = Assembly.GetAssembly(typeof(Ryujinx.Ui.Common.Configuration.ConfigurationState)).GetManifestResourceStream("Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png"); + using Stream stream = Assembly.GetAssembly(typeof(ConfigurationState)).GetManifestResourceStream("Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png"); Icon = new WindowIcon(stream); stream.Position = 0; @@ -36,4 +37,4 @@ namespace Ryujinx.Ava.UI.Windows ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome | ExtendClientAreaChromeHints.OSXThickTitleBar; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs index 153ce95d2..f4fcad319 100644 --- a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs @@ -24,9 +24,9 @@ namespace Ryujinx.Ava.UI.Windows InitializeComponent(); } - public TitleUpdateWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) + public TitleUpdateWindow(VirtualFileSystem virtualFileSystem, ulong titleId) { - DataContext = ViewModel = new TitleUpdateViewModel(virtualFileSystem, titleId, titleName); + DataContext = ViewModel = new TitleUpdateViewModel(virtualFileSystem, titleId); InitializeComponent(); } @@ -35,11 +35,11 @@ namespace Ryujinx.Ava.UI.Windows { ContentDialog contentDialog = new() { - PrimaryButtonText = "", + PrimaryButtonText = "", SecondaryButtonText = "", - CloseButtonText = "", - Content = new TitleUpdateWindow(virtualFileSystem, titleId, titleName), - Title = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.GameUpdateWindowHeading, titleName, titleId.ToString("X16")) + CloseButtonText = "", + Content = new TitleUpdateWindow(virtualFileSystem, titleId), + Title = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.GameUpdateWindowHeading, titleName, titleId.ToString("X16")), }; Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType()); @@ -93,4 +93,4 @@ namespace Ryujinx.Ava.UI.Windows ViewModel.SortUpdates(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index e21c28145..83604b420 100644 --- a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -21,7 +21,6 @@ using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; using Path = System.IO.Path; -using RightsId = LibHac.Fs.RightsId; namespace Ryujinx.HLE.FileSystem {