diff --git a/src/Ryujinx.Ava/Assets/Locales/en_US.json b/src/Ryujinx.Ava/Assets/Locales/en_US.json index 72b5e8e3c..75327185a 100644 --- a/src/Ryujinx.Ava/Assets/Locales/en_US.json +++ b/src/Ryujinx.Ava/Assets/Locales/en_US.json @@ -591,11 +591,10 @@ "SelectDlcDialogTitle": "Select DLC files", "SelectUpdateDialogTitle": "Select update files", "UserProfileWindowTitle": "User Profiles Manager", - "CheatWindowTitle": "Cheats Manager", "DlcWindowTitle": "Manage Downloadable Content for {0} ({1})", "UpdateWindowTitle": "Title Update Manager", - "CheatWindowHeading": "Cheats Available for {0} [{1}]", - "BuildId": "BuildId:", + "CheatWindowHeading": "Manage Cheats for {0} ({1})", + "BuildId": "Build ID:", "DlcWindowHeading": "{0} Downloadable Content(s)", "UserProfilesEditProfile": "Edit Selected", "Cancel": "Cancel", diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs index 0f0071065..248e154af 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs @@ -118,11 +118,11 @@ public async void OpenCheatManager_Click(object sender, RoutedEventArgs args) if (viewModel?.SelectedApplication != null) { - await new CheatWindow( + await CheatWindow.Show( viewModel.VirtualFileSystem, - viewModel.SelectedApplication.TitleId, + ulong.Parse(viewModel.SelectedApplication.TitleId, NumberStyles.HexNumber), viewModel.SelectedApplication.TitleName, - viewModel.SelectedApplication.Path).ShowDialog(viewModel.TopLevel as Window); + viewModel.SelectedApplication.Path); } } diff --git a/src/Ryujinx.Ava/UI/ViewModels/CheatWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/CheatWindowViewModel.cs new file mode 100644 index 000000000..d7de58bb2 --- /dev/null +++ b/src/Ryujinx.Ava/UI/ViewModels/CheatWindowViewModel.cs @@ -0,0 +1,92 @@ +using Avalonia; +using Avalonia.Collections; +using Avalonia.Controls.ApplicationLifetimes; +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.IO; +using System.Linq; + +namespace Ryujinx.Ava.UI.ViewModels +{ + public class CheatWindowViewModel : BaseModel + { + private readonly string _enabledCheatsPath; + public AvaloniaList LoadedCheats { get; } = new(); + public string BuildId { get; } + + public CheatWindowViewModel(VirtualFileSystem virtualFileSystem, ulong titleId, string titlePath) + { + BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath); + + string modsBasePath = ModLoader.GetModsBasePath(); + string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId.ToString("x16")); + + _enabledCheatsPath = Path.Combine(titleModsPath, "cheats", "enabled.txt"); + + string[] enabled = Array.Empty(); + + if (File.Exists(_enabledCheatsPath)) + { + enabled = File.ReadAllLines(_enabledCheatsPath); + } + + var mods = new ModLoader.ModCache(); + + ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleId); + + string currentCheatFile = string.Empty; + string buildId = string.Empty; + + CheatNode currentGroup = null; + + foreach (var cheat in mods.Cheats) + { + if (cheat.Path.FullName != currentCheatFile) + { + currentCheatFile = cheat.Path.FullName; + string parentPath = currentCheatFile.Replace(titleModsPath, ""); + + buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper(); + currentGroup = new CheatNode("", buildId, parentPath, true); + + LoadedCheats.Add(currentGroup); + } + + var model = new CheatNode(cheat.Name, buildId, "", false, enabled.Contains($"{buildId}-{cheat.Name}")); + currentGroup?.SubNodes.Add(model); + } + } + + public async void CopyToClipboard() + { + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + await desktop.MainWindow.Clipboard.SetTextAsync(BuildId); + } + } + + public void Save() + { + List enabledCheats = new(); + + foreach (var cheats in LoadedCheats) + { + foreach (var cheat in cheats.SubNodes) + { + if (cheat.IsEnabled) + { + enabledCheats.Add(cheat.BuildIdKey); + } + } + } + + Directory.CreateDirectory(Path.GetDirectoryName(_enabledCheatsPath)); + + File.WriteAllLines(_enabledCheatsPath, enabledCheats); + } + } +} diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs index 9c0e683a0..439c6fcc6 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs @@ -15,6 +15,7 @@ using Ryujinx.Ui.Common.Helper; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; @@ -170,11 +171,11 @@ public async void OpenCheatManagerForCurrentApp(object sender, RoutedEventArgs e string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString(); - await new CheatWindow( + await CheatWindow.Show( Window.VirtualFileSystem, - ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText, + ulong.Parse(ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText, NumberStyles.HexNumber), name, - Window.ViewModel.SelectedApplication.Path).ShowDialog(Window); + Window.ViewModel.SelectedApplication.Path); ViewModel.AppHost.Device.EnableCheats(); } diff --git a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml index 57d5f7eff..21c7c8013 100644 --- a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml @@ -1,81 +1,66 @@ - - - - - + - - - - - - - - - + + + + + + + + + + + + + + + BorderBrush="{DynamicResource AppListHoverBackgroundColor}" + BorderThickness="1" + CornerRadius="5" + Padding="2.5"> @@ -98,29 +83,47 @@ - - + + + + + - - + + - + diff --git a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs index c2de67ab2..0cb7b8b22 100644 --- a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs @@ -1,123 +1,61 @@ -using Avalonia.Collections; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Styling; +using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Models; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Ava.UI.ViewModels; 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; +using System.Threading.Tasks; namespace Ryujinx.Ava.UI.Windows { - public partial class CheatWindow : StyleableWindow + public partial class CheatWindow : UserControl { - private readonly string _enabledCheatsPath; - public bool NoCheatsFound { get; } - - public AvaloniaList LoadedCheats { get; } - - public string Heading { get; } - public string BuildId { get; } + public CheatWindowViewModel ViewModel; public CheatWindow() { DataContext = this; InitializeComponent(); - - Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle]; } - public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath) + public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) { - LoadedCheats = new AvaloniaList(); - - Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper()); - BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath); + DataContext = ViewModel = new CheatWindowViewModel(virtualFileSystem, titleId, titlePath); InitializeComponent(); - - string modsBasePath = ModLoader.GetModsBasePath(); - string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId); - ulong titleIdValue = ulong.Parse(titleId, NumberStyles.HexNumber); - - _enabledCheatsPath = Path.Combine(titleModsPath, "cheats", "enabled.txt"); - - string[] enabled = Array.Empty(); - - if (File.Exists(_enabledCheatsPath)) - { - enabled = File.ReadAllLines(_enabledCheatsPath); - } - - int cheatAdded = 0; - - var mods = new ModLoader.ModCache(); - - ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleIdValue); - - string currentCheatFile = string.Empty; - string buildId = string.Empty; - - CheatNode currentGroup = null; - - foreach (var cheat in mods.Cheats) - { - if (cheat.Path.FullName != currentCheatFile) - { - currentCheatFile = cheat.Path.FullName; - string parentPath = currentCheatFile.Replace(titleModsPath, ""); - - buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper(); - currentGroup = new CheatNode("", buildId, parentPath, true); - - LoadedCheats.Add(currentGroup); - } - - var model = new CheatNode(cheat.Name, buildId, "", false, enabled.Contains($"{buildId}-{cheat.Name}")); - currentGroup?.SubNodes.Add(model); - - cheatAdded++; - } - - if (cheatAdded == 0) - { - NoCheatsFound = true; - } - - DataContext = this; - - Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle]; } - public void Save() + public static async Task Show(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) { - if (NoCheatsFound) + ContentDialog contentDialog = new() { - return; - } + PrimaryButtonText = "", + SecondaryButtonText = "", + CloseButtonText = "", + Content = new CheatWindow(virtualFileSystem, titleId, titleName, titlePath), + Title = string.Format(LocaleManager.Instance[LocaleKeys.CheatWindowHeading], titleName, titleId.ToString("X16")), + }; - List enabledCheats = new(); + Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType()); + bottomBorder.Setters.Add(new Setter(IsVisibleProperty, false)); - foreach (var cheats in LoadedCheats) - { - foreach (var cheat in cheats.SubNodes) - { - if (cheat.IsEnabled) - { - enabledCheats.Add(cheat.BuildIdKey); - } - } - } + contentDialog.Styles.Add(bottomBorder); - Directory.CreateDirectory(Path.GetDirectoryName(_enabledCheatsPath)); + await ContentDialogHelper.ShowAsync(contentDialog); + } - File.WriteAllLines(_enabledCheatsPath, enabledCheats); + private void SaveAndClose(object sender, RoutedEventArgs e) + { + ViewModel.Save(); + ((ContentDialog)Parent).Hide(); + } - Close(); + private void Close(object sender, RoutedEventArgs e) + { + ((ContentDialog)Parent).Hide(); } } }