mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-09 14:55:45 +00:00
@@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private Bitmap _gitLabLogo;
|
||||
[ObservableProperty] private Bitmap _discordLogo;
|
||||
[ObservableProperty] private string _version;
|
||||
|
||||
|
||||
public string Developers => "GreemDev, LotP";
|
||||
|
||||
public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz");
|
||||
@@ -37,9 +37,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private void UpdateLogoTheme(string theme)
|
||||
{
|
||||
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
|
||||
|
||||
|
||||
string themeName = isDarkTheme ? "Dark" : "Light";
|
||||
|
||||
|
||||
DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName));
|
||||
GitLabLogo = LoadBitmap(LogoPathFormat.Format("GitLab", themeName));
|
||||
}
|
||||
@@ -49,10 +49,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public void Dispose()
|
||||
{
|
||||
RyujinxApp.ThemeChanged -= Ryujinx_ThemeChanged;
|
||||
|
||||
|
||||
GitLabLogo.Dispose();
|
||||
DiscordLogo.Dispose();
|
||||
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Gommon;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.PlayReport;
|
||||
@@ -20,8 +20,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer);
|
||||
public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension);
|
||||
public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString);
|
||||
|
||||
public string FormattedLdnInfo =>
|
||||
|
||||
public string FormattedLdnInfo =>
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" +
|
||||
$"\n" +
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Gommon;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Systems;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System;
|
||||
@@ -19,15 +19,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid)))
|
||||
: _currentEntries;
|
||||
|
||||
public CompatibilityViewModel() {}
|
||||
|
||||
public CompatibilityViewModel() { }
|
||||
|
||||
private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __)
|
||||
=> _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
|
||||
|
||||
public CompatibilityViewModel(ApplicationLibrary appLibrary)
|
||||
{
|
||||
_appLibrary = appLibrary;
|
||||
|
||||
|
||||
AppCountUpdated(null, null);
|
||||
|
||||
_appLibrary.ApplicationCountUpdated += AppCountUpdated;
|
||||
@@ -38,7 +38,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
GC.SuppressFinalize(this);
|
||||
_appLibrary.ApplicationCountUpdated -= AppCountUpdated;
|
||||
}
|
||||
|
||||
|
||||
private bool _onlyShowOwnedGames = true;
|
||||
|
||||
public bool OnlyShowOwnedGames
|
||||
@@ -69,9 +69,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void SetEntries(IEnumerable<CompatibilityEntry> entries)
|
||||
{
|
||||
#pragma warning disable MVVMTK0034
|
||||
_currentEntries = entries.ToList();
|
||||
#pragma warning restore MVVMTK0034
|
||||
OnPropertyChanged(nameof(CurrentEntries));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using System.Linq;
|
||||
@@ -8,10 +8,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public partial class DlcSelectViewModel : BaseModel
|
||||
{
|
||||
[ObservableProperty] private DownloadableContentModel[] _dlcs;
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
[ObservableProperty] private DownloadableContentModel? _selectedDlc;
|
||||
#nullable disable
|
||||
|
||||
#nullable disable
|
||||
|
||||
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
|
||||
{
|
||||
_dlcs = appLibrary.FindDlcsFor(titleId)
|
||||
|
||||
@@ -6,8 +6,8 @@ using DynamicData;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
// NOTE(jpr): this works around a bug where calling _views.Clear also clears SelectedDownloadableContents for
|
||||
// some reason. so we save the items here and add them back after
|
||||
DownloadableContentModel[] items = SelectedDownloadableContents.ToArray();
|
||||
|
||||
|
||||
Views.Clear();
|
||||
Views.AddRange(view);
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
if (arg is DownloadableContentModel content)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(_search) || content.FileName.ToLower().Contains(_search.ToLower()) || content.TitleIdStr.ToLower().Contains(_search.ToLower());
|
||||
return string.IsNullOrWhiteSpace(_search) || content.FileName.Contains(_search, System.StringComparison.OrdinalIgnoreCase) || content.TitleIdStr.Contains(_search, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -253,12 +253,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await ContentDialogHelper.ShowTextDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Checkmark);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool _isLeft;
|
||||
public bool IsLeft
|
||||
{
|
||||
@@ -59,11 +59,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
}
|
||||
|
||||
public bool HasSides => IsLeft ^ IsRight;
|
||||
|
||||
|
||||
[ObservableProperty] private SvgImage _image;
|
||||
|
||||
|
||||
public InputViewModel ParentModel { get; }
|
||||
|
||||
|
||||
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config, StickVisualizer visualizer)
|
||||
{
|
||||
ParentModel = model;
|
||||
@@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
else
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
@@ -91,17 +91,17 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
}
|
||||
|
||||
public async void ShowMotionConfig()
|
||||
{
|
||||
{
|
||||
await MotionInputView.Show(this);
|
||||
ParentModel.IsModified = true;
|
||||
}
|
||||
|
||||
public async void ShowRumbleConfig()
|
||||
{
|
||||
{
|
||||
await RumbleInputView.Show(this);
|
||||
ParentModel.IsModified = true;
|
||||
}
|
||||
|
||||
|
||||
public async void ShowLedConfig()
|
||||
{
|
||||
await LedInputView.Show(this);
|
||||
|
||||
@@ -6,11 +6,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
@@ -67,12 +67,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
private set
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
|
||||
_selectedGamepad = value;
|
||||
|
||||
if (ConfigViewModel is ControllerInputViewModel { Config.UseRainbowLed: true })
|
||||
Rainbow.Updated += (ref Color color) => _selectedGamepad.SetLed((uint)color.ToArgb());
|
||||
|
||||
|
||||
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
public bool IsModified
|
||||
{
|
||||
get => _isModified;
|
||||
set
|
||||
set
|
||||
{
|
||||
_isModified = value;
|
||||
OnPropertyChanged();
|
||||
@@ -149,11 +149,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
set
|
||||
{
|
||||
if (IsModified)
|
||||
{
|
||||
{
|
||||
_playerIdChoose = value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IsModified = false;
|
||||
_playerId = value;
|
||||
_isChangeTrackingActive = false;
|
||||
@@ -163,6 +163,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
_playerId = PlayerIndex.Player1;
|
||||
|
||||
}
|
||||
|
||||
_isLoaded = false;
|
||||
LoadConfiguration();
|
||||
LoadDevice();
|
||||
@@ -216,11 +217,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
IsLeft = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
LoadInputDriver();
|
||||
LoadProfiles();
|
||||
}
|
||||
|
||||
|
||||
OnPropertyChanged();
|
||||
NotifyChanges();
|
||||
}
|
||||
@@ -287,7 +288,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public InputConfig Config { get; set; }
|
||||
|
||||
public InputViewModel(UserControl owner) : this()
|
||||
@@ -348,7 +348,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void FindPairedDeviceInConfigFile()
|
||||
@@ -356,7 +355,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
// This function allows you to output a message about the device configuration found in the file
|
||||
// NOTE: if the configuration is found, we display the message "Waiting for controller connection",
|
||||
// but only if the id gamepad belongs to the selected player
|
||||
|
||||
|
||||
NotificationIsVisible = Config != null && Devices.FirstOrDefault(d => d.Id == Config.Id).Id != Config.Id && Config.PlayerIndex == PlayerId;
|
||||
if (NotificationIsVisible)
|
||||
{
|
||||
@@ -369,10 +368,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
NotificationText = $"{LocaleManager.Instance[LocaleKeys.ControllerSettingsWaitingConnectDevice].Format(Config.Name, Config.Id)}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void MarkAsChanged()
|
||||
{
|
||||
//If tracking is active, then allow changing the modifier
|
||||
@@ -383,7 +380,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void UnlinkDevice()
|
||||
{
|
||||
// "Disabled" mode is available after unbinding the device
|
||||
@@ -392,7 +388,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
IsModified = true;
|
||||
}
|
||||
|
||||
|
||||
public void LoadDevice()
|
||||
{
|
||||
if (Config == null || Config.Backend == InputBackendType.Invalid)
|
||||
@@ -479,10 +474,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
LoadDevices();
|
||||
|
||||
IsModified = true;
|
||||
RevertChanges();
|
||||
RevertChanges();
|
||||
|
||||
_isChangeTrackingActive = true;// Enable configuration change tracking
|
||||
|
||||
|
||||
}
|
||||
|
||||
private string GetCurrentGamepadId()
|
||||
@@ -557,6 +552,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
return $"{GetShortGamepadName(gamepad.Name)} ({controllerNumber})";
|
||||
}
|
||||
|
||||
string GetUniqueGamepadName(IGamepad gamepad, ref int controllerNumber)
|
||||
{
|
||||
string name = GetGamepadName(gamepad, controllerNumber);
|
||||
@@ -565,6 +561,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
controllerNumber++;
|
||||
name = GetGamepadName(gamepad, controllerNumber);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -790,7 +787,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
}
|
||||
|
||||
public void LoadProfileButton()
|
||||
{
|
||||
{
|
||||
LoadProfile();
|
||||
IsModified = true;
|
||||
}
|
||||
@@ -824,6 +821,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
ProfilesList.RemoveAt(index);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -860,58 +858,57 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
public async void SaveProfile()
|
||||
{
|
||||
|
||||
if (Device == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfigViewModel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
|
||||
if (Device == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (validFileName)
|
||||
{
|
||||
string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
|
||||
if (ConfigViewModel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InputConfig config = null;
|
||||
if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
|
||||
|
||||
if (IsKeyboard)
|
||||
{
|
||||
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
|
||||
}
|
||||
else if (IsController)
|
||||
{
|
||||
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
|
||||
|
||||
config.ControllerType = Controllers[_controller].Type;
|
||||
if (validFileName)
|
||||
{
|
||||
string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
|
||||
|
||||
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
|
||||
InputConfig config = null;
|
||||
|
||||
await File.WriteAllTextAsync(path, jsonString);
|
||||
if (IsKeyboard)
|
||||
{
|
||||
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
|
||||
}
|
||||
else if (IsController)
|
||||
{
|
||||
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
|
||||
}
|
||||
|
||||
LoadProfiles();
|
||||
config.ControllerType = Controllers[_controller].Type;
|
||||
|
||||
ProfileChoose = ProfileName; // Show new profile
|
||||
}
|
||||
else
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
|
||||
}
|
||||
}
|
||||
|
||||
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
|
||||
|
||||
await File.WriteAllTextAsync(path, jsonString);
|
||||
|
||||
LoadProfiles();
|
||||
|
||||
ProfileChoose = ProfileName; // Show new profile
|
||||
}
|
||||
else
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async void RemoveProfile()
|
||||
@@ -947,7 +944,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
LoadConfiguration(); // configuration preload is required if the paired gamepad was disconnected but was changed to another gamepad
|
||||
Device = Devices.ToList().FindIndex(d => d.Id == RevertDeviceId);
|
||||
|
||||
|
||||
LoadDevice();
|
||||
LoadConfiguration();
|
||||
|
||||
@@ -957,7 +954,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
public void Save()
|
||||
{
|
||||
|
||||
|
||||
if (!IsModified)
|
||||
{
|
||||
return; //If the input settings were not touched, then do nothing
|
||||
@@ -967,7 +964,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
RevertDeviceId = Devices[Device].Id; // Remember selected device after saving
|
||||
|
||||
List <InputConfig> newConfig = [];
|
||||
List<InputConfig> newConfig = [];
|
||||
|
||||
newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Humanizer;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
@@ -11,22 +11,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
public partial class LedInputViewModel : BaseModel
|
||||
{
|
||||
public required InputViewModel ParentModel { get; init; }
|
||||
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
{
|
||||
if (!EnableLedChanging) return;
|
||||
if (!EnableLedChanging)
|
||||
return;
|
||||
|
||||
if (TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(LedColor.ToUInt32());
|
||||
});
|
||||
|
||||
|
||||
[ObservableProperty] private bool _enableLedChanging;
|
||||
[ObservableProperty] private Color _ledColor;
|
||||
|
||||
public string RainbowSpeedText => RainbowSpeed.ToString(CultureInfo.CurrentCulture).Truncate(4, string.Empty);
|
||||
|
||||
|
||||
public float RainbowSpeed
|
||||
{
|
||||
get => ConfigurationState.Instance.Hid.RainbowSpeed;
|
||||
@@ -37,11 +38,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
OnPropertyChanged(nameof(RainbowSpeedText));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
|
||||
private bool _turnOffLed;
|
||||
|
||||
|
||||
public bool TurnOffLed
|
||||
{
|
||||
get => _turnOffLed;
|
||||
@@ -52,9 +53,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool _useRainbowLed;
|
||||
|
||||
|
||||
public bool UseRainbowLed
|
||||
{
|
||||
get => _useRainbowLed;
|
||||
|
||||
@@ -20,15 +20,15 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.Systems;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Models.Generic;
|
||||
using Ryujinx.Ava.UI.Renderer;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.UI.Views.Dialog;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
@@ -86,9 +86,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private Brush _progressBarForegroundColor;
|
||||
[ObservableProperty] private Brush _progressBarBackgroundColor;
|
||||
[ObservableProperty] private Brush _vSyncModeColor;
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
[ObservableProperty] private byte[]? _selectedIcon;
|
||||
#nullable disable
|
||||
#nullable disable
|
||||
[ObservableProperty] private int _statusBarProgressMaximum;
|
||||
[ObservableProperty] private int _statusBarProgressValue;
|
||||
[ObservableProperty] private string _statusBarProgressStatusText;
|
||||
@@ -118,7 +118,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (Updater.CanUpdate(true))
|
||||
await Updater.BeginUpdateAsync(true);
|
||||
});
|
||||
|
||||
|
||||
private bool _showTotalTimePlayed;
|
||||
private bool _showLoadProgress;
|
||||
private bool _isGameRunning;
|
||||
@@ -140,7 +140,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private int _customVSyncIntervalPercentageProxy;
|
||||
private ApplicationData _listSelectedApplication;
|
||||
private ApplicationData _gridSelectedApplication;
|
||||
|
||||
|
||||
// Key is Title ID
|
||||
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
|
||||
|
||||
@@ -157,9 +157,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
.Sort(GetComparer())
|
||||
.OnItemAdded(_ => OnPropertyChanged(nameof(AppsObservableList)))
|
||||
.OnItemRemoved(_ => OnPropertyChanged(nameof(AppsObservableList)))
|
||||
#pragma warning disable MVVMTK0034 // Event to update is fired below
|
||||
.Bind(out _appsObservableList);
|
||||
#pragma warning restore MVVMTK0034
|
||||
|
||||
_rendererWaitEvent = new AutoResetEvent(false);
|
||||
|
||||
@@ -205,7 +203,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
#if DEBUG
|
||||
topLevel.AttachDevTools(new KeyGesture(Avalonia.Input.Key.F12, KeyModifiers.Control));
|
||||
#endif
|
||||
|
||||
|
||||
Window.ApplicationLibrary.TotalTimePlayedRecalculated += TotalTimePlayed_Recalculated;
|
||||
}
|
||||
|
||||
@@ -327,7 +325,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ApplicationData ListSelectedApplication
|
||||
{
|
||||
get => _listSelectedApplication;
|
||||
@@ -335,13 +333,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
_listSelectedApplication = value;
|
||||
|
||||
#pragma warning disable MVVMTK0034
|
||||
if (_listSelectedApplication != null && _listAppContextMenu == null)
|
||||
if (_listSelectedApplication != null && ListAppContextMenu == null)
|
||||
|
||||
ListAppContextMenu = new ApplicationContextMenu();
|
||||
else if (_listSelectedApplication == null && _listAppContextMenu != null)
|
||||
else if (_listSelectedApplication == null && ListAppContextMenu != null)
|
||||
ListAppContextMenu = null!;
|
||||
#pragma warning restore MVVMTK0034
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
@@ -354,13 +350,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
_gridSelectedApplication = value;
|
||||
|
||||
#pragma warning disable MVVMTK0034
|
||||
if (_gridSelectedApplication != null && _gridAppContextMenu == null)
|
||||
if (_gridSelectedApplication != null && GridAppContextMenu == null)
|
||||
GridAppContextMenu = new ApplicationContextMenu();
|
||||
else if (_gridSelectedApplication == null && _gridAppContextMenu != null)
|
||||
else if (_gridSelectedApplication == null && GridAppContextMenu != null)
|
||||
GridAppContextMenu = null!;
|
||||
#pragma warning restore MVVMTK0034
|
||||
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
@@ -380,7 +374,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
ListSelectedApplication = value;
|
||||
GridSelectedApplication = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||
@@ -395,7 +389,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
|
||||
|
||||
public bool ShowCustomVSyncIntervalPicker
|
||||
public bool ShowCustomVSyncIntervalPicker
|
||||
=> _isGameRunning && AppHost.Device.VSyncMode == VSyncMode.Custom;
|
||||
|
||||
public void UpdateVSyncIntervalPicker()
|
||||
@@ -416,6 +410,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
AppHost.Device.CustomVSyncInterval = newInterval;
|
||||
AppHost.Device.UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
OnPropertyChanged((nameof(CustomVSyncInterval)));
|
||||
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
|
||||
}
|
||||
@@ -447,6 +442,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
AppHost.Device.CustomVSyncInterval = value;
|
||||
AppHost.Device.UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
|
||||
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
|
||||
OnPropertyChanged();
|
||||
@@ -579,7 +575,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool ShowNames
|
||||
{
|
||||
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
|
||||
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
|
||||
set
|
||||
{
|
||||
ConfigurationState.Instance.UI.ShowNames.Value = value;
|
||||
@@ -762,7 +758,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
#region PrivateMethods
|
||||
|
||||
private static IComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
|
||||
private static SortExpressionComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
|
||||
ascending
|
||||
? SortExpressionComparer<ApplicationData>.Ascending(selector)
|
||||
: SortExpressionComparer<ApplicationData>.Descending(selector);
|
||||
@@ -791,15 +787,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void RefreshGrid()
|
||||
{
|
||||
Applications.ToObservableChangeSet()
|
||||
var appsList = Applications.ToObservableChangeSet()
|
||||
.Filter(Filter)
|
||||
.Sort(GetComparer())
|
||||
#pragma warning disable MVVMTK0034
|
||||
.Bind(out _appsObservableList)
|
||||
#pragma warning restore MVVMTK0034
|
||||
.Bind(out var apps)
|
||||
.AsObservableList();
|
||||
|
||||
OnPropertyChanged(nameof(AppsObservableList));
|
||||
AppsObservableList = apps;
|
||||
}
|
||||
|
||||
private bool Filter(object arg)
|
||||
@@ -874,10 +868,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, firmwareVersion.VersionString);
|
||||
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
dialogTitle,
|
||||
message,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
string.Empty,
|
||||
dialogTitle,
|
||||
message,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, message);
|
||||
@@ -996,7 +990,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
waitingDialog.Close();
|
||||
|
||||
string message = ex.Message;
|
||||
if(ex is FormatException)
|
||||
if (ex is FormatException)
|
||||
{
|
||||
message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename);
|
||||
}
|
||||
@@ -1054,6 +1048,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
CacheLoadStatus = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case ShaderCacheLoadingState shaderCacheState:
|
||||
CacheLoadStatus = $"{current} / {total}";
|
||||
@@ -1074,6 +1069,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
CacheLoadStatus = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
|
||||
@@ -1110,7 +1106,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
_rendererWaitEvent.WaitOne();
|
||||
|
||||
AppHost?.Start();
|
||||
|
||||
|
||||
AppHost?.DisposeContext();
|
||||
}
|
||||
|
||||
@@ -1190,11 +1186,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
await ContentDialogHelper.ShowTextDialog(
|
||||
LocaleManager.Instance[numAdded > 0 || numRemoved > 0 ? LocaleKeys.RyujinxConfirm : LocaleKeys.RyujinxInfo],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Checkmark);
|
||||
});
|
||||
}
|
||||
@@ -1388,7 +1384,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OpenHelper.OpenFolder(screenshotsDir);
|
||||
}
|
||||
|
||||
@@ -1578,15 +1574,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool InitializeUserConfig(ApplicationData application)
|
||||
{
|
||||
// Code where conditions will be met before loading the user configuration (Global Config)
|
||||
BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value;
|
||||
// Code where conditions will be met before loading the user configuration (Global Config)
|
||||
string BackendThreadingInit = Program.BackendThreadingArg;
|
||||
|
||||
if (BackendThreadingInit is null)
|
||||
{
|
||||
BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
||||
}
|
||||
|
||||
BackendThreadingInit ??= ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
|
||||
|
||||
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
|
||||
string idGame = application.IdBaseString;
|
||||
if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat))
|
||||
@@ -1599,13 +1591,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
|
||||
{
|
||||
|
||||
List<string> Arguments = new List<string>
|
||||
List<string> Arguments = new()
|
||||
{
|
||||
"--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading
|
||||
};
|
||||
|
||||
Rebooter.RebootAppWithGame(application.Path, Arguments);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1635,7 +1627,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
#if RELEASE
|
||||
await PerformanceCheck();
|
||||
#endif
|
||||
|
||||
|
||||
Logger.RestartTime();
|
||||
|
||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id);
|
||||
@@ -1680,7 +1672,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
|
||||
gameThread.Start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void SwitchToRenderer(bool startFullscreen) =>
|
||||
@@ -1801,7 +1793,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ToggleFullscreen()
|
||||
{
|
||||
if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs)
|
||||
@@ -1963,7 +1954,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
#endregion
|
||||
|
||||
#region Context Menu commands
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> RunApplication { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => viewModel.LoadApplication(viewModel.SelectedApplication));
|
||||
@@ -1982,7 +1973,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
viewModel.RefreshView();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
public static RelayCommand<MainWindowViewModel> CreateApplicationShortcut { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => ShortcutHelper.CreateAppShortcut(
|
||||
@@ -1991,7 +1982,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
viewModel.SelectedApplication.IdString,
|
||||
viewModel.SelectedApplication.Icon
|
||||
));
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> EditGameConfiguration { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
async viewModel =>
|
||||
@@ -2058,7 +2049,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
viewModel.SelectedApplication.Path
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> OpenModManager { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => ModManagerView.Show(
|
||||
@@ -2086,11 +2077,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
OpenHelper.OpenFolder(titleModsPath);
|
||||
});
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> TrimXci { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path));
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> PurgePtcCache { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
async viewModel =>
|
||||
@@ -2280,7 +2271,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
OpenHelper.OpenFolder(shaderCacheDir);
|
||||
});
|
||||
|
||||
|
||||
public static AsyncRelayCommand<MainWindowViewModel> ExtractApplicationExeFs { get; } =
|
||||
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
|
||||
async viewModel =>
|
||||
@@ -2350,7 +2341,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
png.SaveTo(fileStream);
|
||||
});
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using DynamicData;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
@@ -131,12 +131,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
.Filter(Filter)
|
||||
.Bind(out ReadOnlyObservableCollection<ModModel> view).AsObservableList();
|
||||
|
||||
#pragma warning disable MVVMTK0034 // Event to update is fired below
|
||||
_views.Clear();
|
||||
_views.AddRange(view);
|
||||
#pragma warning restore MVVMTK0034
|
||||
Views.Clear();
|
||||
Views.AddRange(view);
|
||||
|
||||
SelectedMods = new(Views.Where(x => x.Enabled));
|
||||
SelectedMods = [.. Views.Where(x => x.Enabled)];
|
||||
|
||||
OnPropertyChanged(nameof(ModCount));
|
||||
OnPropertyChanged(nameof(Views));
|
||||
@@ -147,7 +145,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
if (arg is ModModel content)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(_search) || content.Name.ToLower().Contains(_search.ToLower());
|
||||
return string.IsNullOrWhiteSpace(_search) || content.Name.Contains(_search, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -215,6 +213,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Mods.Remove(model);
|
||||
OnPropertyChanged(nameof(ModCount));
|
||||
}
|
||||
|
||||
Sort();
|
||||
}
|
||||
|
||||
@@ -312,7 +311,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public void EnableAll()
|
||||
{
|
||||
SelectedMods = new(Mods);
|
||||
SelectedMods = [.. Mods];
|
||||
}
|
||||
|
||||
public void DisableAll()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
private readonly SettingsViewModel _baseViewModel;
|
||||
|
||||
public SettingsHacksViewModel() {}
|
||||
|
||||
public SettingsHacksViewModel() { }
|
||||
|
||||
public SettingsHacksViewModel(SettingsViewModel settingsVm)
|
||||
{
|
||||
_baseViewModel = settingsVm;
|
||||
@@ -17,20 +17,20 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
|
||||
[ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted;
|
||||
|
||||
|
||||
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
|
||||
{
|
||||
sb.AppendLine(
|
||||
"This hack applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
|
||||
.AppendLine();
|
||||
|
||||
|
||||
sb.AppendLine("From the issue on GitHub:").AppendLine();
|
||||
sb.Append(
|
||||
"When clicking very fast from game main menu to 2nd submenu, " +
|
||||
"there is a low chance that the game will softlock, " +
|
||||
"the submenu won't show up, while background music is still there.");
|
||||
});
|
||||
|
||||
|
||||
public static string NifmDisableIsAnyInternetRequestAcceptedTooltip { get; } = Lambda.String(sb =>
|
||||
{
|
||||
sb.AppendLine(
|
||||
|
||||
@@ -9,12 +9,12 @@ using Ryujinx.Audio.Backends.OpenAL;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
using Ryujinx.Audio.Backends.SoundIo;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Systems.Configuration;
|
||||
using Ryujinx.Ava.Systems.Configuration.System;
|
||||
using Ryujinx.Ava.Systems.Configuration.UI;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
@@ -72,10 +72,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public SettingsHacksViewModel DirtyHacks { get; }
|
||||
|
||||
private readonly bool _isGameRunning;
|
||||
private Bitmap _gameIcon;
|
||||
private string _gameTitle;
|
||||
private string _gamePath;
|
||||
private string _gameId;
|
||||
private readonly Bitmap _gameIcon;
|
||||
private readonly string _gameTitle;
|
||||
private readonly string _gamePath;
|
||||
private readonly string _gameId;
|
||||
public bool IsGameRunning => _isGameRunning;
|
||||
public Bitmap GameIcon => _gameIcon;
|
||||
public string GamePath => _gamePath;
|
||||
@@ -142,9 +142,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||
|
||||
|
||||
public int FocusLostActionType { get; set; }
|
||||
|
||||
|
||||
public VSyncMode VSyncMode
|
||||
{
|
||||
get => _vSyncMode;
|
||||
@@ -188,6 +188,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
VSyncMode = VSyncMode.Custom;
|
||||
}
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
@@ -201,15 +202,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
int newPercent = (int)((value / 60f) * 100);
|
||||
_customVSyncIntervalPercentageProxy = newPercent;
|
||||
OnPropertiesChanged(
|
||||
nameof(CustomVSyncIntervalPercentageProxy),
|
||||
nameof(CustomVSyncIntervalPercentageProxy),
|
||||
nameof(CustomVSyncIntervalPercentageText));
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
public bool EnablePptc { get; set; }
|
||||
public bool EnableLowPowerPptc { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public long TurboMultiplier
|
||||
{
|
||||
get => _turboModeMultiplier;
|
||||
@@ -218,13 +219,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (_turboModeMultiplier != value)
|
||||
{
|
||||
_turboModeMultiplier = value;
|
||||
|
||||
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged((nameof(TurboMultiplierPercentageText)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string TurboMultiplierPercentageText => $"{TurboMultiplier}%";
|
||||
|
||||
public bool EnableInternetAccess { get; set; }
|
||||
@@ -345,7 +346,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public AvaloniaList<string> NetworkInterfaceList
|
||||
{
|
||||
get => new(_networkInterfaces.Keys);
|
||||
get => [.. _networkInterfaces.Keys];
|
||||
}
|
||||
|
||||
public HotkeyConfig KeyboardHotkey { get; set; }
|
||||
@@ -374,39 +375,37 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
|
||||
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
Task.Run(LoadTimeZones);
|
||||
|
||||
|
||||
DirtyHacks = new SettingsHacksViewModel(this);
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsViewModel(
|
||||
VirtualFileSystem virtualFileSystem,
|
||||
VirtualFileSystem virtualFileSystem,
|
||||
ContentManager contentManager,
|
||||
bool gameRunning,
|
||||
string gamePath,
|
||||
string gameName,
|
||||
string gameId,
|
||||
byte[] gameIconData,
|
||||
string gameName,
|
||||
string gameId,
|
||||
byte[] gameIconData,
|
||||
bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_contentManager = contentManager;
|
||||
|
||||
|
||||
if (gameIconData != null && gameIconData.Length > 0)
|
||||
{
|
||||
using (var ms = new MemoryStream(gameIconData))
|
||||
{
|
||||
_gameIcon = new Bitmap(ms);
|
||||
}
|
||||
using var ms = new MemoryStream(gameIconData);
|
||||
_gameIcon = new Bitmap(ms);
|
||||
}
|
||||
|
||||
_isGameRunning = gameRunning;
|
||||
_gamePath = gamePath;
|
||||
_gameTitle = gameName;
|
||||
_gameTitle = gameName;
|
||||
_gameId = gameId;
|
||||
|
||||
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
|
||||
@@ -414,7 +413,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
string gameDir = Program.GetDirGameUserConfig(gameId, false, true);
|
||||
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
|
||||
{
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
|
||||
}
|
||||
|
||||
LoadCurrentConfiguration(); // Needed to load custom configuration
|
||||
@@ -443,8 +442,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
Task.Run(LoadAvailableGpus);
|
||||
|
||||
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
||||
LoadCurrentConfiguration();
|
||||
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
|
||||
LoadCurrentConfiguration();
|
||||
|
||||
DirtyHacks = new SettingsHacksViewModel(this);
|
||||
}
|
||||
@@ -811,7 +810,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public void DeleteConfigGame()
|
||||
{
|
||||
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
|
||||
string gameDir = Program.GetDirGameUserConfig(GameId, false, false);
|
||||
|
||||
if (File.Exists(gameDir))
|
||||
{
|
||||
@@ -839,8 +838,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public AsyncRelayCommand ResetButton => Commands.Create(async () =>
|
||||
{
|
||||
if (!WantsToReset) return;
|
||||
|
||||
if (!WantsToReset)
|
||||
return;
|
||||
|
||||
CloseWindow?.Invoke();
|
||||
ConfigurationState.Instance.LoadDefault();
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
|
||||
@@ -5,8 +5,8 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -178,17 +178,17 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
ApplicationLibrary.SaveTitleUpdatesForGame(ApplicationData, updates);
|
||||
}
|
||||
|
||||
private Task ShowNewUpdatesAddedDialog(int numAdded)
|
||||
private Task<UserResult> ShowNewUpdatesAddedDialog(int numAdded)
|
||||
{
|
||||
string msg = string.Format(LocaleManager.Instance[LocaleKeys.UpdateWindowUpdateAddedMessage], numAdded);
|
||||
return Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
return Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
await ContentDialogHelper.ShowTextDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
|
||||
msg,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
(int)Symbol.Checkmark
|
||||
));
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] DecompressYaz0(Stream stream)
|
||||
private static byte[] DecompressYaz0(MemoryStream stream)
|
||||
{
|
||||
using BinaryReader reader = new(stream);
|
||||
|
||||
|
||||
@@ -43,10 +43,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
.Sort(GetComparer())
|
||||
.Bind(out ReadOnlyObservableCollection<SaveModel> view).AsObservableList();
|
||||
|
||||
#pragma warning disable MVVMTK0034
|
||||
_views.Clear();
|
||||
_views.AddRange(view);
|
||||
#pragma warning restore MVVMTK0034
|
||||
Views.Clear();
|
||||
Views.AddRange(view);
|
||||
OnPropertyChanged(nameof(Views));
|
||||
}
|
||||
|
||||
@@ -54,13 +52,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
if (arg is SaveModel save)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
|
||||
return string.IsNullOrWhiteSpace(Search) || save.Title.Contains(Search, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private IComparer<SaveModel> GetComparer()
|
||||
private SortExpressionComparer<SaveModel> GetComparer()
|
||||
{
|
||||
return SortIndex switch
|
||||
{
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData;
|
||||
using Gommon;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Systems.AppLibrary;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -36,10 +36,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
|
||||
private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary;
|
||||
private Optional<XCITrimmerFileModel> _processingApplication = null;
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
|
||||
private readonly AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
|
||||
private MainWindowViewModel _mainWindowViewModel;
|
||||
private readonly AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
|
||||
private readonly MainWindowViewModel _mainWindowViewModel;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private string _search;
|
||||
private ProcessingMode _processingMode;
|
||||
@@ -93,12 +93,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private void SortingChanged()
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(IsSortedByName),
|
||||
nameof(IsSortedBySaved),
|
||||
nameof(SortingAscending),
|
||||
nameof(SortingField),
|
||||
nameof(IsSortedByName),
|
||||
nameof(IsSortedBySaved),
|
||||
nameof(SortingAscending),
|
||||
nameof(SortingField),
|
||||
nameof(SortingFieldName));
|
||||
|
||||
|
||||
SortAndFilter();
|
||||
}
|
||||
|
||||
@@ -110,13 +110,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private void ApplicationsChanged()
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(AllXCIFiles),
|
||||
nameof(Status),
|
||||
nameof(PotentialSavings),
|
||||
nameof(ActualSavings),
|
||||
nameof(CanTrim),
|
||||
nameof(AllXCIFiles),
|
||||
nameof(Status),
|
||||
nameof(PotentialSavings),
|
||||
nameof(ActualSavings),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim));
|
||||
|
||||
|
||||
DisplayedChanged();
|
||||
SortAndFilter();
|
||||
}
|
||||
@@ -124,9 +124,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private void SelectionChanged(bool displayedChanged = true)
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim),
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim),
|
||||
nameof(SelectedXCIFiles));
|
||||
|
||||
if (displayedChanged)
|
||||
@@ -136,10 +136,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private void ProcessingChanged()
|
||||
{
|
||||
OnPropertiesChanged(
|
||||
nameof(Processing),
|
||||
nameof(Cancel),
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(Processing),
|
||||
nameof(Cancel),
|
||||
nameof(Status),
|
||||
nameof(CanTrim),
|
||||
nameof(CanUntrim));
|
||||
}
|
||||
|
||||
@@ -245,8 +245,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (arg is XCITrimmerFileModel content)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(_search)
|
||||
|| content.Name.ToLower().Contains(_search.ToLower())
|
||||
|| content.Path.ToLower().Contains(_search.ToLower());
|
||||
|| content.Name.Contains(_search, System.StringComparison.OrdinalIgnoreCase)
|
||||
|| content.Path.Contains(_search, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -254,7 +254,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
|
||||
{
|
||||
private XciTrimmerViewModel _viewModel;
|
||||
private readonly XciTrimmerViewModel _viewModel;
|
||||
|
||||
public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user