Merge branch 'master' into xeyes
This commit is contained in:
@@ -144,12 +144,12 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
case KeyboardMode.Numeric:
|
||||
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeNumeric);
|
||||
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||
_checkInput = text => text.All(NumericCharacterValidation.IsNumeric);
|
||||
_checkInput = text => text.All(CharacterValidation.IsNumeric);
|
||||
break;
|
||||
case KeyboardMode.Alphabet:
|
||||
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet);
|
||||
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||
_checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
|
||||
_checkInput = text => text.All(value => !CharacterValidation.IsCJK(value));
|
||||
break;
|
||||
case KeyboardMode.ASCII:
|
||||
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeASCII);
|
||||
|
||||
@@ -6,12 +6,10 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
|
||||
using UserProfileSft = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
||||
|
||||
@@ -19,6 +19,17 @@
|
||||
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
||||
Icon="{ext:Icon fa-solid fa-bookmark}"
|
||||
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||
<MenuItem
|
||||
IsVisible="{Binding HasCompatibilityEntry}"
|
||||
Click="OpenApplicationCompatibility_Click"
|
||||
Header="{ext:Locale GameListContextMenuShowCompatEntry}"
|
||||
Icon="{ext:Icon mdi-gamepad}"
|
||||
ToolTip.Tip="{ext:Locale GameListContextMenuShowCompatEntryToolTip}"/>
|
||||
<MenuItem
|
||||
Click="OpenApplicationData_Click"
|
||||
Header="{ext:Locale GameListContextMenuShowGameData}"
|
||||
Icon="{ext:Icon mdi-chart-line}"
|
||||
ToolTip.Tip="{ext:Locale GameListContextMenuShowGameDataToolTip}"/>
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Click="OpenUserSaveDirectory_Click"
|
||||
@@ -74,7 +85,6 @@
|
||||
Header="{ext:Locale GameListContextMenuTrimXCI}"
|
||||
IsEnabled="{Binding TrimXCIEnabled}"
|
||||
ToolTip.Tip="{ext:Locale GameListContextMenuTrimXCIToolTip}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon mdi-cached}">
|
||||
<MenuItem
|
||||
Click="PurgePtcCache_Click"
|
||||
@@ -112,6 +122,7 @@
|
||||
Header="{ext:Locale GameListContextMenuExtractDataRomFS}"
|
||||
ToolTip.Tip="{ext:Locale GameListContextMenuExtractDataRomFSToolTip}" />
|
||||
<MenuItem
|
||||
IsVisible="{Binding HasDlc}"
|
||||
Click="ExtractAocRomFs_Click"
|
||||
Header="{ext:Locale GameListContextMenuExtractDataAocRomFS}"
|
||||
ToolTip.Tip="{ext:Locale GameListContextMenuExtractDataAocRomFSToolTip}" />
|
||||
|
||||
@@ -2,9 +2,6 @@ using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using LibHac;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common;
|
||||
@@ -15,16 +12,14 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Compat;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Path = System.IO.Path;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
@@ -128,7 +123,11 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
await ModManagerWindow.Show(viewModel.SelectedApplication.Id, viewModel.SelectedApplication.Name);
|
||||
await ModManagerWindow.Show(
|
||||
viewModel.SelectedApplication.Id,
|
||||
viewModel.SelectedApplication.IdBase,
|
||||
viewModel.ApplicationLibrary,
|
||||
viewModel.SelectedApplication.Name);
|
||||
}
|
||||
|
||||
public async void PurgePtcCache_Click(object sender, RoutedEventArgs args)
|
||||
@@ -335,7 +334,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
return;
|
||||
|
||||
DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.IdBase, viewModel.ApplicationLibrary);
|
||||
DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, viewModel.ApplicationLibrary);
|
||||
|
||||
if (selectedDlc is not null)
|
||||
{
|
||||
@@ -387,6 +386,18 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
viewModel.SelectedApplication.Icon
|
||||
);
|
||||
}
|
||||
|
||||
public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
await CompatibilityList.Show(viewModel.SelectedApplication.IdString);
|
||||
}
|
||||
|
||||
public async void OpenApplicationData_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
await ApplicationDataView.Show(viewModel.SelectedApplication);
|
||||
}
|
||||
|
||||
public async void RunApplication_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
@@ -396,12 +407,8 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
|
||||
public async void TrimXCI_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
MainWindowViewModel viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||
|
||||
if (viewModel?.SelectedApplication != null)
|
||||
{
|
||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||
await viewModel.TrimXCIFile(viewModel.SelectedApplication.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
114
src/Ryujinx/UI/Controls/ApplicationDataView.axaml
Normal file
114
src/Ryujinx/UI/Controls/ApplicationDataView.axaml
Normal file
@@ -0,0 +1,114 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:ext="using:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Ryujinx.Ava.UI.Controls.ApplicationDataView"
|
||||
x:DataType="viewModels:ApplicationDataViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Margin="0"
|
||||
MaxWidth="256"
|
||||
MinWidth="256"
|
||||
Source="{Binding AppData.Icon, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
|
||||
<Border Margin="5, 0" Width="1" Height="256" BorderBrush="Gray" Background="Gray" />
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid
|
||||
RowDefinitions="Auto,Auto,Auto"
|
||||
ColumnDefinitions="*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<TextBlock HorizontalAlignment="Left"
|
||||
Text="{Binding FormattedVersion}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock HorizontalAlignment="Left"
|
||||
Text="{Binding FormattedDeveloper}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock HorizontalAlignment="Stretch"
|
||||
Text="{Binding FormattedFileExtension}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock HorizontalAlignment="Stretch"
|
||||
Text="{Binding FormattedFileSize}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
<Separator Grid.Row="1" Margin="0, 10, 0, 10" Height="1" BorderBrush="Gray" Background="Gray" />
|
||||
<StackPanel Grid.Row="2"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Vertical"
|
||||
Spacing="5">
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding AppData.HasPlayabilityInfo}">
|
||||
<TextBlock Padding="0, 0, 5, 0" Text="{ext:Locale GameListHeaderCompatibilityStatus}" />
|
||||
<Button
|
||||
Click="PlayabilityStatus_OnClick"
|
||||
HorizontalContentAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Background="{DynamicResource AppListBackgroundColor}"
|
||||
Padding="0">
|
||||
<TextBlock
|
||||
Margin="1.5"
|
||||
Tag="{Binding AppData.IdString}"
|
||||
Text="{Binding AppData.LocalizedStatus}"
|
||||
Foreground="{Binding AppData.PlayabilityStatus, Converter={x:Static helpers:PlayabilityStatusConverter.Shared}}"
|
||||
ToolTip.Tip="{Binding AppData.LocalizedStatusTooltip}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<Button.Styles>
|
||||
<Style Selector="Button">
|
||||
<Setter Property="MinWidth"
|
||||
Value="0" />
|
||||
<!-- avoids very wide buttons from the overall project avalonia style -->
|
||||
</Style>
|
||||
</Button.Styles>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Padding="0, 0, 5, 0" Text="{ext:Locale GameListHeaderTitleId}" />
|
||||
<Button
|
||||
Click="IdString_OnClick"
|
||||
HorizontalContentAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Background="{DynamicResource AppListBackgroundColor}"
|
||||
Padding="0">
|
||||
<TextBlock
|
||||
Margin="1.5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding AppData.IdString}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Margin="0, 10, 0, 10" Height="1" BorderBrush="Gray" Background="Gray" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding AppData.HasLdnGames}"
|
||||
Text="{Binding FormattedLdnInfo}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<Separator IsVisible="{Binding AppData.HasLdnGames}" Margin="0, 10, 0, 10" Height="1" BorderBrush="Gray" Background="Gray" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Vertical"
|
||||
Spacing="5">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding FormattedLastPlayed}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding FormattedPlayTime}"
|
||||
IsVisible="{Binding AppData.HasPlayedPreviously}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
86
src/Ryujinx/UI/Controls/ApplicationDataView.axaml.cs
Normal file
86
src/Ryujinx/UI/Controls/ApplicationDataView.axaml.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Styling;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Compat;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
{
|
||||
public partial class ApplicationDataView : UserControl
|
||||
{
|
||||
public static async Task Show(ApplicationData appData)
|
||||
{
|
||||
ContentDialog contentDialog = new()
|
||||
{
|
||||
Title = appData.Name,
|
||||
PrimaryButtonText = string.Empty,
|
||||
SecondaryButtonText = string.Empty,
|
||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
||||
MinWidth = 256,
|
||||
Content = new ApplicationDataView { DataContext = new ApplicationDataViewModel(appData) }
|
||||
};
|
||||
|
||||
Style closeButton = new(x => x.Name("CloseButton"));
|
||||
closeButton.Setters.Add(new Setter(WidthProperty, 160d));
|
||||
|
||||
Style closeButtonParent = new(x => x.Name("CommandSpace"));
|
||||
closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty,
|
||||
Avalonia.Layout.HorizontalAlignment.Center));
|
||||
|
||||
contentDialog.Styles.Add(closeButton);
|
||||
contentDialog.Styles.Add(closeButtonParent);
|
||||
|
||||
await ContentDialogHelper.ShowAsync(contentDialog);
|
||||
}
|
||||
|
||||
public ApplicationDataView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not Button { Content: TextBlock playabilityLabel })
|
||||
return;
|
||||
|
||||
if (RyujinxApp.AppLifetime.Windows.TryGetFirst(x => x is ContentDialogOverlayWindow, out Window window))
|
||||
window.Close(ContentDialogResult.None);
|
||||
|
||||
await CompatibilityList.Show((string)playabilityLabel.Tag);
|
||||
}
|
||||
|
||||
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel mwvm)
|
||||
return;
|
||||
|
||||
if (sender is not Button { Content: TextBlock idText })
|
||||
return;
|
||||
|
||||
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
|
||||
return;
|
||||
|
||||
ApplicationData appData = mwvm.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
||||
if (appData is null)
|
||||
return;
|
||||
|
||||
await clipboard.SetTextAsync(appData.IdString);
|
||||
|
||||
NotificationHelper.ShowInformation(
|
||||
"Copied Title ID",
|
||||
$"{appData.Name} ({appData.IdString})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using System;
|
||||
|
||||
|
||||
@@ -86,6 +86,30 @@
|
||||
Text="{Binding Version}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Click="PlayabilityStatus_OnClick"
|
||||
HorizontalContentAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding HasPlayabilityInfo}"
|
||||
Background="{DynamicResource AppListBackgroundColor}"
|
||||
Margin="-1, 0, 0, 0"
|
||||
Padding="0"
|
||||
ToolTip.Tip="{Binding LocalizedStatusTooltip}">
|
||||
<TextBlock
|
||||
Margin="1.5"
|
||||
Tag="{Binding IdString}"
|
||||
Text="{Binding LocalizedStatus}"
|
||||
Foreground="{Binding PlayabilityStatus, Converter={x:Static helpers:PlayabilityStatusConverter.Shared}}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<Button.Styles>
|
||||
<Style Selector="Button">
|
||||
<Setter Property="MinWidth"
|
||||
Value="0" />
|
||||
<!-- avoids very wide buttons from the overall project avalonia style -->
|
||||
</Style>
|
||||
</Button.Styles>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<StackPanel
|
||||
@@ -117,7 +141,8 @@
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Converter={helpers:MultiplayerInfoConverter}}"
|
||||
IsVisible="{Binding HasLdnGames}"
|
||||
Text="{Binding Converter={x:Static helpers:MultiplayerInfoConverter.Instance}}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Interactivity;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Compat;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
@@ -30,6 +30,17 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
if (sender is ListBox { SelectedItem: ApplicationData selected })
|
||||
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
|
||||
}
|
||||
|
||||
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel mwvm)
|
||||
return;
|
||||
|
||||
if (sender is not Button { Content: TextBlock playabilityLabel })
|
||||
return;
|
||||
|
||||
await CompatibilityList.Show((string)playabilityLabel.Tag);
|
||||
}
|
||||
|
||||
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Styling;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
|
||||
@@ -159,6 +159,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
Symbol = (Symbol)symbol,
|
||||
Margin = new Thickness(10),
|
||||
FontSize = 40,
|
||||
FlowDirection = FlowDirection.LeftToRight,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
internal class MultiplayerInfoConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
private static readonly MultiplayerInfoConverter _instance = new();
|
||||
public static readonly MultiplayerInfoConverter Instance = new();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is ApplicationData applicationData)
|
||||
{
|
||||
if (applicationData.PlayerCount != 0 && applicationData.GameCount != 0)
|
||||
{
|
||||
return $"Hosted Games: {applicationData.GameCount}\nOnline Players: {applicationData.PlayerCount}";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
if (value is not ApplicationData { HasLdnGames: true } applicationData)
|
||||
return "";
|
||||
|
||||
return new StringBuilder()
|
||||
.AppendLine(
|
||||
LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames]
|
||||
.Format(applicationData.GameCount))
|
||||
.Append(
|
||||
LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount]
|
||||
.Format(applicationData.PlayerCount))
|
||||
.ToString();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
@@ -31,7 +35,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return _instance;
|
||||
return Instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models.Input
|
||||
{
|
||||
public class GamepadInputConfig : BaseModel
|
||||
public partial class GamepadInputConfig : BaseModel
|
||||
{
|
||||
public bool EnableCemuHookMotion { get; set; }
|
||||
public string DsuServerHost { get; set; }
|
||||
@@ -25,402 +25,58 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
public ControllerType ControllerType { get; set; }
|
||||
public PlayerIndex PlayerIndex { get; set; }
|
||||
|
||||
private StickInputId _leftJoystick;
|
||||
public StickInputId LeftJoystick
|
||||
{
|
||||
get => _leftJoystick;
|
||||
set
|
||||
{
|
||||
_leftJoystick = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private StickInputId _leftJoystick;
|
||||
[ObservableProperty] private bool _leftInvertStickX;
|
||||
[ObservableProperty] private bool _leftInvertStickY;
|
||||
[ObservableProperty] private bool _leftRotate90;
|
||||
[ObservableProperty] private GamepadInputId _leftStickButton;
|
||||
|
||||
private bool _leftInvertStickX;
|
||||
public bool LeftInvertStickX
|
||||
{
|
||||
get => _leftInvertStickX;
|
||||
set
|
||||
{
|
||||
_leftInvertStickX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private StickInputId _rightJoystick;
|
||||
[ObservableProperty] private bool _rightInvertStickX;
|
||||
[ObservableProperty] private bool _rightInvertStickY;
|
||||
[ObservableProperty] private bool _rightRotate90;
|
||||
[ObservableProperty] private GamepadInputId _rightStickButton;
|
||||
|
||||
private bool _leftInvertStickY;
|
||||
public bool LeftInvertStickY
|
||||
{
|
||||
get => _leftInvertStickY;
|
||||
set
|
||||
{
|
||||
_leftInvertStickY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private GamepadInputId _dpadUp;
|
||||
[ObservableProperty] private GamepadInputId _dpadDown;
|
||||
[ObservableProperty] private GamepadInputId _dpadLeft;
|
||||
[ObservableProperty] private GamepadInputId _dpadRight;
|
||||
|
||||
private bool _leftRotate90;
|
||||
public bool LeftRotate90
|
||||
{
|
||||
get => _leftRotate90;
|
||||
set
|
||||
{
|
||||
_leftRotate90 = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _leftStickButton;
|
||||
public GamepadInputId LeftStickButton
|
||||
{
|
||||
get => _leftStickButton;
|
||||
set
|
||||
{
|
||||
_leftStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private StickInputId _rightJoystick;
|
||||
public StickInputId RightJoystick
|
||||
{
|
||||
get => _rightJoystick;
|
||||
set
|
||||
{
|
||||
_rightJoystick = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _rightInvertStickX;
|
||||
public bool RightInvertStickX
|
||||
{
|
||||
get => _rightInvertStickX;
|
||||
set
|
||||
{
|
||||
_rightInvertStickX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _rightInvertStickY;
|
||||
public bool RightInvertStickY
|
||||
{
|
||||
get => _rightInvertStickY;
|
||||
set
|
||||
{
|
||||
_rightInvertStickY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _rightRotate90;
|
||||
public bool RightRotate90
|
||||
{
|
||||
get => _rightRotate90;
|
||||
set
|
||||
{
|
||||
_rightRotate90 = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _rightStickButton;
|
||||
public GamepadInputId RightStickButton
|
||||
{
|
||||
get => _rightStickButton;
|
||||
set
|
||||
{
|
||||
_rightStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadUp;
|
||||
public GamepadInputId DpadUp
|
||||
{
|
||||
get => _dpadUp;
|
||||
set
|
||||
{
|
||||
_dpadUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadDown;
|
||||
public GamepadInputId DpadDown
|
||||
{
|
||||
get => _dpadDown;
|
||||
set
|
||||
{
|
||||
_dpadDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadLeft;
|
||||
public GamepadInputId DpadLeft
|
||||
{
|
||||
get => _dpadLeft;
|
||||
set
|
||||
{
|
||||
_dpadLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadRight;
|
||||
public GamepadInputId DpadRight
|
||||
{
|
||||
get => _dpadRight;
|
||||
set
|
||||
{
|
||||
_dpadRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonL;
|
||||
public GamepadInputId ButtonL
|
||||
{
|
||||
get => _buttonL;
|
||||
set
|
||||
{
|
||||
_buttonL = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonMinus;
|
||||
public GamepadInputId ButtonMinus
|
||||
{
|
||||
get => _buttonMinus;
|
||||
set
|
||||
{
|
||||
_buttonMinus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _leftButtonSl;
|
||||
public GamepadInputId LeftButtonSl
|
||||
{
|
||||
get => _leftButtonSl;
|
||||
set
|
||||
{
|
||||
_leftButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _leftButtonSr;
|
||||
public GamepadInputId LeftButtonSr
|
||||
{
|
||||
get => _leftButtonSr;
|
||||
set
|
||||
{
|
||||
_leftButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonZl;
|
||||
public GamepadInputId ButtonZl
|
||||
{
|
||||
get => _buttonZl;
|
||||
set
|
||||
{
|
||||
_buttonZl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonA;
|
||||
public GamepadInputId ButtonA
|
||||
{
|
||||
get => _buttonA;
|
||||
set
|
||||
{
|
||||
_buttonA = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonB;
|
||||
public GamepadInputId ButtonB
|
||||
{
|
||||
get => _buttonB;
|
||||
set
|
||||
{
|
||||
_buttonB = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonX;
|
||||
public GamepadInputId ButtonX
|
||||
{
|
||||
get => _buttonX;
|
||||
set
|
||||
{
|
||||
_buttonX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonY;
|
||||
public GamepadInputId ButtonY
|
||||
{
|
||||
get => _buttonY;
|
||||
set
|
||||
{
|
||||
_buttonY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonR;
|
||||
public GamepadInputId ButtonR
|
||||
{
|
||||
get => _buttonR;
|
||||
set
|
||||
{
|
||||
_buttonR = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonPlus;
|
||||
public GamepadInputId ButtonPlus
|
||||
{
|
||||
get => _buttonPlus;
|
||||
set
|
||||
{
|
||||
_buttonPlus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _rightButtonSl;
|
||||
public GamepadInputId RightButtonSl
|
||||
{
|
||||
get => _rightButtonSl;
|
||||
set
|
||||
{
|
||||
_rightButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _rightButtonSr;
|
||||
public GamepadInputId RightButtonSr
|
||||
{
|
||||
get => _rightButtonSr;
|
||||
set
|
||||
{
|
||||
_rightButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonZr;
|
||||
public GamepadInputId ButtonZr
|
||||
{
|
||||
get => _buttonZr;
|
||||
set
|
||||
{
|
||||
_buttonZr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _deadzoneLeft;
|
||||
public float DeadzoneLeft
|
||||
{
|
||||
get => _deadzoneLeft;
|
||||
set
|
||||
{
|
||||
_deadzoneLeft = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _deadzoneRight;
|
||||
public float DeadzoneRight
|
||||
{
|
||||
get => _deadzoneRight;
|
||||
set
|
||||
{
|
||||
_deadzoneRight = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _rangeLeft;
|
||||
public float RangeLeft
|
||||
{
|
||||
get => _rangeLeft;
|
||||
set
|
||||
{
|
||||
_rangeLeft = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _rangeRight;
|
||||
public float RangeRight
|
||||
{
|
||||
get => _rangeRight;
|
||||
set
|
||||
{
|
||||
_rangeRight = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _triggerThreshold;
|
||||
public float TriggerThreshold
|
||||
{
|
||||
get => _triggerThreshold;
|
||||
set
|
||||
{
|
||||
_triggerThreshold = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableMotion;
|
||||
public bool EnableMotion
|
||||
{
|
||||
get => _enableMotion;
|
||||
set
|
||||
{
|
||||
_enableMotion = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableRumble;
|
||||
public bool EnableRumble
|
||||
{
|
||||
get => _enableRumble;
|
||||
set
|
||||
{
|
||||
_enableRumble = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private GamepadInputId _buttonMinus;
|
||||
[ObservableProperty] private GamepadInputId _buttonPlus;
|
||||
|
||||
private bool _enableLedChanging;
|
||||
[ObservableProperty] private GamepadInputId _buttonA;
|
||||
[ObservableProperty] private GamepadInputId _buttonB;
|
||||
[ObservableProperty] private GamepadInputId _buttonX;
|
||||
[ObservableProperty] private GamepadInputId _buttonY;
|
||||
|
||||
[ObservableProperty] private GamepadInputId _buttonZl;
|
||||
[ObservableProperty] private GamepadInputId _buttonZr;
|
||||
|
||||
[ObservableProperty] private GamepadInputId _buttonL;
|
||||
[ObservableProperty] private GamepadInputId _buttonR;
|
||||
|
||||
[ObservableProperty] private GamepadInputId _leftButtonSl;
|
||||
[ObservableProperty] private GamepadInputId _leftButtonSr;
|
||||
|
||||
[ObservableProperty] private GamepadInputId _rightButtonSl;
|
||||
[ObservableProperty] private GamepadInputId _rightButtonSr;
|
||||
|
||||
public bool EnableLedChanging
|
||||
{
|
||||
get => _enableLedChanging;
|
||||
set
|
||||
{
|
||||
_enableLedChanging = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private float _deadzoneLeft;
|
||||
[ObservableProperty] private float _deadzoneRight;
|
||||
|
||||
[ObservableProperty] private float _rangeLeft;
|
||||
[ObservableProperty] private float _rangeRight;
|
||||
|
||||
[ObservableProperty] private float _triggerThreshold;
|
||||
|
||||
[ObservableProperty] private bool _enableMotion;
|
||||
|
||||
[ObservableProperty] private bool _enableRumble;
|
||||
|
||||
[ObservableProperty] private bool _enableLedChanging;
|
||||
|
||||
[ObservableProperty] private Color _ledColor;
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
@@ -449,18 +105,6 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
private Color _ledColor;
|
||||
|
||||
public Color LedColor
|
||||
{
|
||||
get => _ledColor;
|
||||
set
|
||||
{
|
||||
_ledColor = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public GamepadInputConfig(InputConfig config)
|
||||
{
|
||||
|
||||
@@ -1,322 +1,52 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models.Input
|
||||
{
|
||||
public class KeyboardInputConfig : BaseModel
|
||||
public partial class KeyboardInputConfig : BaseModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public ControllerType ControllerType { get; set; }
|
||||
public PlayerIndex PlayerIndex { get; set; }
|
||||
|
||||
private Key _leftStickUp;
|
||||
public Key LeftStickUp
|
||||
{
|
||||
get => _leftStickUp;
|
||||
set
|
||||
{
|
||||
_leftStickUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _leftStickUp;
|
||||
[ObservableProperty] private Key _leftStickDown;
|
||||
[ObservableProperty] private Key _leftStickLeft;
|
||||
[ObservableProperty] private Key _leftStickRight;
|
||||
[ObservableProperty] private Key _leftStickButton;
|
||||
|
||||
private Key _leftStickDown;
|
||||
public Key LeftStickDown
|
||||
{
|
||||
get => _leftStickDown;
|
||||
set
|
||||
{
|
||||
_leftStickDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _rightStickUp;
|
||||
[ObservableProperty] private Key _rightStickDown;
|
||||
[ObservableProperty] private Key _rightStickLeft;
|
||||
[ObservableProperty] private Key _rightStickRight;
|
||||
[ObservableProperty] private Key _rightStickButton;
|
||||
|
||||
private Key _leftStickLeft;
|
||||
public Key LeftStickLeft
|
||||
{
|
||||
get => _leftStickLeft;
|
||||
set
|
||||
{
|
||||
_leftStickLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftStickRight;
|
||||
public Key LeftStickRight
|
||||
{
|
||||
get => _leftStickRight;
|
||||
set
|
||||
{
|
||||
_leftStickRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftStickButton;
|
||||
public Key LeftStickButton
|
||||
{
|
||||
get => _leftStickButton;
|
||||
set
|
||||
{
|
||||
_leftStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickUp;
|
||||
public Key RightStickUp
|
||||
{
|
||||
get => _rightStickUp;
|
||||
set
|
||||
{
|
||||
_rightStickUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickDown;
|
||||
public Key RightStickDown
|
||||
{
|
||||
get => _rightStickDown;
|
||||
set
|
||||
{
|
||||
_rightStickDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickLeft;
|
||||
public Key RightStickLeft
|
||||
{
|
||||
get => _rightStickLeft;
|
||||
set
|
||||
{
|
||||
_rightStickLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickRight;
|
||||
public Key RightStickRight
|
||||
{
|
||||
get => _rightStickRight;
|
||||
set
|
||||
{
|
||||
_rightStickRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickButton;
|
||||
public Key RightStickButton
|
||||
{
|
||||
get => _rightStickButton;
|
||||
set
|
||||
{
|
||||
_rightStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadUp;
|
||||
public Key DpadUp
|
||||
{
|
||||
get => _dpadUp;
|
||||
set
|
||||
{
|
||||
_dpadUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadDown;
|
||||
public Key DpadDown
|
||||
{
|
||||
get => _dpadDown;
|
||||
set
|
||||
{
|
||||
_dpadDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadLeft;
|
||||
public Key DpadLeft
|
||||
{
|
||||
get => _dpadLeft;
|
||||
set
|
||||
{
|
||||
_dpadLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadRight;
|
||||
public Key DpadRight
|
||||
{
|
||||
get => _dpadRight;
|
||||
set
|
||||
{
|
||||
_dpadRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonL;
|
||||
public Key ButtonL
|
||||
{
|
||||
get => _buttonL;
|
||||
set
|
||||
{
|
||||
_buttonL = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonMinus;
|
||||
public Key ButtonMinus
|
||||
{
|
||||
get => _buttonMinus;
|
||||
set
|
||||
{
|
||||
_buttonMinus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftButtonSl;
|
||||
public Key LeftButtonSl
|
||||
{
|
||||
get => _leftButtonSl;
|
||||
set
|
||||
{
|
||||
_leftButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftButtonSr;
|
||||
public Key LeftButtonSr
|
||||
{
|
||||
get => _leftButtonSr;
|
||||
set
|
||||
{
|
||||
_leftButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonZl;
|
||||
public Key ButtonZl
|
||||
{
|
||||
get => _buttonZl;
|
||||
set
|
||||
{
|
||||
_buttonZl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonA;
|
||||
public Key ButtonA
|
||||
{
|
||||
get => _buttonA;
|
||||
set
|
||||
{
|
||||
_buttonA = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonB;
|
||||
public Key ButtonB
|
||||
{
|
||||
get => _buttonB;
|
||||
set
|
||||
{
|
||||
_buttonB = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonX;
|
||||
public Key ButtonX
|
||||
{
|
||||
get => _buttonX;
|
||||
set
|
||||
{
|
||||
_buttonX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonY;
|
||||
public Key ButtonY
|
||||
{
|
||||
get => _buttonY;
|
||||
set
|
||||
{
|
||||
_buttonY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonR;
|
||||
public Key ButtonR
|
||||
{
|
||||
get => _buttonR;
|
||||
set
|
||||
{
|
||||
_buttonR = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonPlus;
|
||||
public Key ButtonPlus
|
||||
{
|
||||
get => _buttonPlus;
|
||||
set
|
||||
{
|
||||
_buttonPlus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightButtonSl;
|
||||
public Key RightButtonSl
|
||||
{
|
||||
get => _rightButtonSl;
|
||||
set
|
||||
{
|
||||
_rightButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightButtonSr;
|
||||
public Key RightButtonSr
|
||||
{
|
||||
get => _rightButtonSr;
|
||||
set
|
||||
{
|
||||
_rightButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonZr;
|
||||
public Key ButtonZr
|
||||
{
|
||||
get => _buttonZr;
|
||||
set
|
||||
{
|
||||
_buttonZr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private Key _dpadUp;
|
||||
[ObservableProperty] private Key _dpadDown;
|
||||
[ObservableProperty] private Key _dpadLeft;
|
||||
[ObservableProperty] private Key _dpadRight;
|
||||
|
||||
[ObservableProperty] private Key _buttonMinus;
|
||||
[ObservableProperty] private Key _buttonPlus;
|
||||
|
||||
[ObservableProperty] private Key _buttonA;
|
||||
[ObservableProperty] private Key _buttonB;
|
||||
[ObservableProperty] private Key _buttonX;
|
||||
[ObservableProperty] private Key _buttonY;
|
||||
|
||||
[ObservableProperty] private Key _buttonL;
|
||||
[ObservableProperty] private Key _buttonR;
|
||||
|
||||
[ObservableProperty] private Key _buttonZl;
|
||||
[ObservableProperty] private Key _buttonZr;
|
||||
|
||||
[ObservableProperty] private Key _leftButtonSl;
|
||||
[ObservableProperty] private Key _leftButtonSr;
|
||||
|
||||
[ObservableProperty] private Key _rightButtonSl;
|
||||
[ObservableProperty] private Key _rightButtonSr;
|
||||
|
||||
public KeyboardInputConfig(InputConfig config)
|
||||
{
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class ModModel : BaseModel
|
||||
public partial class ModModel : BaseModel
|
||||
{
|
||||
private bool _enabled;
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
_enabled = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private bool _enabled;
|
||||
|
||||
public bool InSd { get; }
|
||||
public string Path { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public string FormattedName =>
|
||||
InSd && ulong.TryParse(Name, NumberStyles.HexNumber, null, out ulong applicationId)
|
||||
? $"Atmosphère: {RyujinxApp.MainWindow.ApplicationLibrary.GetNameForApplicationId(applicationId)}"
|
||||
: Name;
|
||||
|
||||
public ModModel(string path, string name, bool enabled, bool inSd)
|
||||
{
|
||||
Path = path;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class ProfileImageModel : BaseModel
|
||||
public partial class ProfileImageModel : BaseModel
|
||||
{
|
||||
public ProfileImageModel(string name, byte[] data)
|
||||
{
|
||||
@@ -14,19 +15,6 @@ namespace Ryujinx.Ava.UI.Models
|
||||
public string Name { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
private SolidColorBrush _backgroundColor = new(Colors.White);
|
||||
|
||||
public SolidColorBrush BackgroundColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return _backgroundColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
_backgroundColor = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private SolidColorBrush _backgroundColor = new(Colors.White);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ using Gommon;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Ncm;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -1,28 +1,18 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class TempProfile : BaseModel
|
||||
public partial class TempProfile : BaseModel
|
||||
{
|
||||
private readonly UserProfile _profile;
|
||||
private byte[] _image;
|
||||
private string _name = String.Empty;
|
||||
[ObservableProperty] private byte[] _image;
|
||||
[ObservableProperty] private string _name = String.Empty;
|
||||
private UserId _userId;
|
||||
|
||||
public static uint MaxProfileNameLength => 0x20;
|
||||
|
||||
public byte[] Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public UserId UserId
|
||||
{
|
||||
get => _userId;
|
||||
@@ -36,21 +26,9 @@ namespace Ryujinx.Ava.UI.Models
|
||||
|
||||
public string UserIdString => _userId.ToString();
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public TempProfile(UserProfile profile)
|
||||
{
|
||||
_profile = profile;
|
||||
|
||||
if (_profile != null)
|
||||
if (profile != null)
|
||||
{
|
||||
Image = profile.Image;
|
||||
Name = profile.Name;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Views.User;
|
||||
@@ -8,65 +9,15 @@ using Profile = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class UserProfile : BaseModel
|
||||
public partial class UserProfile : BaseModel
|
||||
{
|
||||
private readonly Profile _profile;
|
||||
private readonly NavigationDialogHost _owner;
|
||||
private byte[] _image;
|
||||
private string _name;
|
||||
private UserId _userId;
|
||||
private bool _isPointerOver;
|
||||
private IBrush _backgroundColor;
|
||||
|
||||
public byte[] Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public UserId UserId
|
||||
{
|
||||
get => _userId;
|
||||
set
|
||||
{
|
||||
_userId = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPointerOver
|
||||
{
|
||||
get => _isPointerOver;
|
||||
set
|
||||
{
|
||||
_isPointerOver = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public IBrush BackgroundColor
|
||||
{
|
||||
get => _backgroundColor;
|
||||
set
|
||||
{
|
||||
_backgroundColor = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty] private byte[] _image;
|
||||
[ObservableProperty] private string _name;
|
||||
[ObservableProperty] private UserId _userId;
|
||||
[ObservableProperty] private bool _isPointerOver;
|
||||
[ObservableProperty] private IBrush _backgroundColor;
|
||||
|
||||
public UserProfile(Profile profile, NavigationDialogHost owner)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Platform;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using Ryujinx.Common.Configuration;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Ryujinx.Common.Helper;
|
||||
using SharpMetal.QuartzCore;
|
||||
using System;
|
||||
|
||||
@@ -7,14 +8,12 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
{
|
||||
public CAMetalLayer CreateSurface()
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() && RunningPlatform.IsArm)
|
||||
{
|
||||
return new CAMetalLayer(MetalLayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Cannot create a {nameof(CAMetalLayer)} without being on ARM Mac.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,19 +43,19 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
|
||||
public RendererHost(string titleId)
|
||||
{
|
||||
switch (TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend))
|
||||
{
|
||||
case GraphicsBackend.OpenGl:
|
||||
EmbeddedWindow = new EmbeddedWindowOpenGL();
|
||||
break;
|
||||
case GraphicsBackend.Metal:
|
||||
EmbeddedWindow = new EmbeddedWindowMetal();
|
||||
break;
|
||||
case GraphicsBackend.Vulkan:
|
||||
EmbeddedWindow = new EmbeddedWindowVulkan();
|
||||
break;
|
||||
}
|
||||
|
||||
Focusable = true;
|
||||
FlowDirection = FlowDirection.LeftToRight;
|
||||
|
||||
EmbeddedWindow =
|
||||
#pragma warning disable CS8509
|
||||
TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend) switch
|
||||
#pragma warning restore CS8509
|
||||
{
|
||||
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
||||
GraphicsBackend.Metal => new EmbeddedWindowMetal(),
|
||||
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
|
||||
};
|
||||
|
||||
string backendText = EmbeddedWindow switch
|
||||
{
|
||||
EmbeddedWindowVulkan => "Vulkan",
|
||||
|
||||
26
src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs
Normal file
26
src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public class ApplicationDataViewModel : BaseModel
|
||||
{
|
||||
public ApplicationData AppData { get; }
|
||||
|
||||
public ApplicationDataViewModel(ApplicationData appData) => AppData = appData;
|
||||
|
||||
public string FormattedVersion => LocaleManager.Instance[LocaleKeys.GameListHeaderVersion].Format(AppData.Version);
|
||||
public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer);
|
||||
|
||||
public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension);
|
||||
public string FormattedLastPlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed].Format(AppData.LastPlayedString);
|
||||
public string FormattedPlayTime => LocaleManager.Instance[LocaleKeys.GameListHeaderTimePlayed].Format(AppData.TimePlayedString);
|
||||
public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString);
|
||||
|
||||
public string FormattedLdnInfo =>
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" +
|
||||
$"\n" +
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}";
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
|
||||
{
|
||||
_dlcs = appLibrary.DownloadableContents.Items
|
||||
.Where(x => x.Dlc.TitleIdBase == titleId)
|
||||
.Select(x => x.Dlc)
|
||||
_dlcs = appLibrary.FindDlcsFor(titleId)
|
||||
.OrderBy(it => it.IsBundled ? 0 : 1)
|
||||
.ThenBy(it => it.TitleId)
|
||||
.ToArray();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
@@ -9,13 +8,11 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Application = Avalonia.Application;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
@@ -72,8 +69,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void LoadDownloadableContents()
|
||||
{
|
||||
IEnumerable<(DownloadableContentModel Dlc, bool IsEnabled)> dlcs = _applicationLibrary.DownloadableContents.Items
|
||||
.Where(it => it.Dlc.TitleIdBase == _applicationData.IdBase);
|
||||
(DownloadableContentModel Dlc, bool IsEnabled)[] dlcs = _applicationLibrary.FindDlcConfigurationFor(_applicationData.Id);
|
||||
|
||||
bool hasBundledContent = false;
|
||||
foreach ((DownloadableContentModel dlc, bool isEnabled) in dlcs)
|
||||
|
||||
@@ -2,11 +2,13 @@ using Avalonia.Svg.Skia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.UI.Views.Input;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
@@ -72,6 +74,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
Visualizer = visualizer;
|
||||
model.NotifyChangesEvent += OnParentModelChanged;
|
||||
OnParentModelChanged();
|
||||
config.PropertyChanged += (_, args) =>
|
||||
{
|
||||
if (args.PropertyName is nameof(Config.UseRainbowLed))
|
||||
{
|
||||
if (Config is { UseRainbowLed: true, TurnOffLed: false, EnableLedChanging: true })
|
||||
Rainbow.Updated += (ref Color color) => ParentModel.SelectedGamepad.SetLed((uint)color.ToArgb());
|
||||
else
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32());
|
||||
}
|
||||
}
|
||||
};
|
||||
Config = config;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
@@ -63,7 +64,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
get => _selectedGamepad;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Humanizer;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
@@ -21,6 +24,19 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
[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;
|
||||
set
|
||||
{
|
||||
ConfigurationState.Instance.Hid.RainbowSpeed.Value = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(RainbowSpeedText));
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
|
||||
@@ -349,6 +349,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||
|
||||
public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id);
|
||||
|
||||
public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
|
||||
|
||||
public bool OpenDeviceSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
|
||||
@@ -629,15 +633,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
return SortMode switch
|
||||
{
|
||||
ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication],
|
||||
ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper],
|
||||
ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed],
|
||||
ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderTimePlayed],
|
||||
ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension],
|
||||
ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize],
|
||||
ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListHeaderPath],
|
||||
ApplicationSort.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite],
|
||||
ApplicationSort.TitleId => LocaleManager.Instance[LocaleKeys.DlcManagerTableHeadingTitleIdLabel],
|
||||
ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication],
|
||||
ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListSortDeveloper],
|
||||
ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListSortLastPlayed],
|
||||
ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListSortTimePlayed],
|
||||
ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListSortFileExtension],
|
||||
ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListSortFileSize],
|
||||
ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListSortPath],
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
@@ -29,6 +30,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private string _search;
|
||||
private readonly ulong _applicationId;
|
||||
private readonly ulong[] _installedDlcIds;
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
|
||||
private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
@@ -61,18 +63,23 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
get => string.Format(LocaleManager.Instance[LocaleKeys.ModWindowHeading], Mods.Count);
|
||||
}
|
||||
|
||||
public ModManagerViewModel(ulong applicationId)
|
||||
public ModManagerViewModel(ulong applicationId, ulong applicationIdBase, ApplicationLibrary appLibrary)
|
||||
{
|
||||
_applicationId = applicationId;
|
||||
|
||||
_installedDlcIds = appLibrary.DownloadableContents.Keys
|
||||
.Where(x => x.TitleIdBase == applicationIdBase)
|
||||
.Select(x => x.TitleId)
|
||||
.ToArray();
|
||||
|
||||
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
|
||||
|
||||
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
|
||||
|
||||
LoadMods(applicationId);
|
||||
LoadMods(applicationId, _installedDlcIds);
|
||||
}
|
||||
|
||||
private void LoadMods(ulong applicationId)
|
||||
private void LoadMods(ulong applicationId, ulong[] installedDlcIds)
|
||||
{
|
||||
Mods.Clear();
|
||||
SelectedMods.Clear();
|
||||
@@ -84,7 +91,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
bool inSd = path == ModLoader.GetSdModsBasePath();
|
||||
ModLoader.ModCache modCache = new();
|
||||
|
||||
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId);
|
||||
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId, _installedDlcIds);
|
||||
|
||||
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.RomfsDirs)
|
||||
{
|
||||
@@ -278,7 +285,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true);
|
||||
}
|
||||
|
||||
LoadMods(_applicationId);
|
||||
LoadMods(_applicationId, _installedDlcIds);
|
||||
}
|
||||
|
||||
public async void Add()
|
||||
|
||||
@@ -2,7 +2,7 @@ using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.OpenAL;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
@@ -16,6 +16,7 @@ using Ryujinx.Ava.Utilities.Configuration.System;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
@@ -27,8 +28,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
||||
|
||||
@@ -115,10 +114,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
||||
|
||||
public bool IsAppleSiliconMac => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
||||
|
||||
public bool IsMacOS => OperatingSystem.IsMacOS();
|
||||
|
||||
public bool EnableDiscordIntegration { get; set; }
|
||||
public bool CheckUpdatesOnStart { get; set; }
|
||||
public bool ShowConfirmExit { get; set; }
|
||||
@@ -200,7 +195,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableTextureRecompression { get; set; }
|
||||
public bool EnableMacroHLE { get; set; }
|
||||
public bool EnableColorSpacePassthrough { get; set; }
|
||||
public bool ColorSpacePassthroughAvailable => IsMacOS;
|
||||
public bool ColorSpacePassthroughAvailable => RunningPlatform.IsMacOS;
|
||||
public bool EnableFileLog { get; set; }
|
||||
public bool EnableStub { get; set; }
|
||||
public bool EnableInfo { get; set; }
|
||||
@@ -296,6 +291,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty] private bool _matchSystemTime;
|
||||
|
||||
public DateTimeOffset CurrentDate { get; set; }
|
||||
|
||||
public TimeSpan CurrentTime { get; set; }
|
||||
@@ -330,9 +327,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
[GeneratedRegex("Ryujinx-[0-9a-f]{8}")]
|
||||
private static partial Regex LdnPassphraseRegex();
|
||||
|
||||
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
||||
|
||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
||||
@@ -414,17 +408,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex)));
|
||||
}
|
||||
|
||||
public void MatchSystemTime()
|
||||
{
|
||||
(DateTimeOffset dto, TimeSpan timeOfDay) = DateTimeOffset.Now.Extract();
|
||||
|
||||
CurrentDate = dto;
|
||||
CurrentTime = timeOfDay;
|
||||
|
||||
OnPropertyChanged(nameof(CurrentDate));
|
||||
OnPropertyChanged(nameof(CurrentTime));
|
||||
}
|
||||
|
||||
public async Task LoadTimeZones()
|
||||
{
|
||||
_timeZoneContentManager = new TimeZoneContentManager();
|
||||
@@ -470,7 +453,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private bool ValidateLdnPassphrase(string passphrase)
|
||||
{
|
||||
return string.IsNullOrEmpty(passphrase) || (passphrase.Length == 16 && LdnPassphraseRegex().IsMatch(passphrase));
|
||||
return string.IsNullOrEmpty(passphrase) || (passphrase.Length == 16 && Patterns.LdnPassphrase.IsMatch(passphrase));
|
||||
}
|
||||
|
||||
public void ValidateAndSetTimeZone(string location)
|
||||
@@ -526,7 +509,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
CurrentDate = currentDateTime.Date;
|
||||
CurrentTime = currentDateTime.TimeOfDay;
|
||||
|
||||
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval.Value;
|
||||
MatchSystemTime = config.System.MatchSystemTime;
|
||||
|
||||
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval;
|
||||
CustomVSyncInterval = config.Graphics.CustomVSyncInterval;
|
||||
VSyncMode = config.Graphics.VSyncMode;
|
||||
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
|
||||
@@ -631,6 +616,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.System.TimeZone.Value = TimeZone;
|
||||
}
|
||||
|
||||
config.System.MatchSystemTime.Value = MatchSystemTime;
|
||||
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
|
||||
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
||||
config.System.DramSize.Value = DramSize;
|
||||
@@ -734,6 +720,25 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
CloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
[ObservableProperty] private bool _wantsToReset;
|
||||
|
||||
public AsyncRelayCommand ResetButton => Commands.Create(async () =>
|
||||
{
|
||||
if (!WantsToReset) return;
|
||||
|
||||
CloseWindow?.Invoke();
|
||||
ConfigurationState.Instance.LoadDefault();
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
RyujinxApp.MainWindow.LoadApplications();
|
||||
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
$"Your {RyujinxApp.FullAppName} configuration has been reset.",
|
||||
"",
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
||||
"Configuration Reset");
|
||||
});
|
||||
|
||||
public void CancelButton()
|
||||
{
|
||||
RevertIfNotSaved();
|
||||
|
||||
@@ -41,8 +41,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void LoadUpdates()
|
||||
{
|
||||
IEnumerable<(TitleUpdateModel TitleUpdate, bool IsSelected)> updates = ApplicationLibrary.TitleUpdates.Items
|
||||
.Where(it => it.TitleUpdate.TitleIdBase == ApplicationData.IdBase);
|
||||
(TitleUpdateModel TitleUpdate, bool IsSelected)[] updates = ApplicationLibrary.FindUpdateConfigurationFor(ApplicationData.Id);
|
||||
|
||||
bool hasBundledContent = false;
|
||||
SelectedUpdate = new TitleUpdateViewModelNoUpdate();
|
||||
|
||||
@@ -4,7 +4,6 @@ using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
x:Class="Ryujinx.UI.Views.Input.LedInputView">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding ParentModel.CanClearLed}">
|
||||
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColorDisable}" />
|
||||
<TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColorDisable}" />
|
||||
<CheckBox
|
||||
Margin="5"
|
||||
MinWidth="0"
|
||||
@@ -20,15 +20,33 @@
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsEnabled="{Binding !TurnOffLed}">
|
||||
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColorRainbow}" />
|
||||
<TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColorRainbow}" />
|
||||
<CheckBox
|
||||
Margin="5"
|
||||
MinWidth="0"
|
||||
IsChecked="{Binding UseRainbowLed, Mode=TwoWay}">
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsEnabled="{Binding !TurnOffLed}">
|
||||
<TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColorRainbowSpeed}" />
|
||||
<Slider HorizontalAlignment="Center"
|
||||
Value="{Binding RainbowSpeed}"
|
||||
Width="175"
|
||||
Margin="0,-3,0,0"
|
||||
Height="32"
|
||||
Padding="0,-5"
|
||||
TickFrequency="0.25"
|
||||
LargeChange="1"
|
||||
SmallChange="0.25"
|
||||
VerticalAlignment="Center"
|
||||
Minimum="1"
|
||||
Maximum="10" />
|
||||
<TextBlock Margin="5,0"
|
||||
MinWidth="75"
|
||||
Text="{Binding RainbowSpeedText}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsEnabled="{Binding ShowLedColorPicker}">
|
||||
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColor}" />
|
||||
<TextBlock MinWidth="75" MaxWidth="200" Text="{ext:Locale ControllerSettingsLedColor}" />
|
||||
<ui:ColorPickerButton
|
||||
Margin="5"
|
||||
IsMoreButtonVisible="False"
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.UI.Views.Input
|
||||
|
||||
@@ -2,7 +2,6 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Gommon;
|
||||
using LibHac.Common;
|
||||
using LibHac.Ns;
|
||||
@@ -51,7 +50,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
||||
UninstallFileTypesMenuItem.Command = Commands.Create(UninstallFileTypes);
|
||||
XciTrimmerMenuItem.Command = Commands.Create(XCITrimmerWindow.Show);
|
||||
AboutWindowMenuItem.Command = Commands.Create(AboutWindow.Show);
|
||||
CompatibilityListMenuItem.Command = Commands.Create(CompatibilityList.Show);
|
||||
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityList.Show());
|
||||
|
||||
UpdateMenuItem.Command = Commands.Create(async () =>
|
||||
{
|
||||
@@ -134,7 +133,12 @@ namespace Ryujinx.Ava.UI.Views.Main
|
||||
{
|
||||
Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager);
|
||||
|
||||
Rainbow.Enable();
|
||||
|
||||
await Window.SettingsWindow.ShowDialog(Window);
|
||||
|
||||
Rainbow.Disable();
|
||||
Rainbow.Reset();
|
||||
|
||||
Window.SettingsWindow = null;
|
||||
|
||||
|
||||
@@ -113,37 +113,37 @@
|
||||
Tag="TitleId" />
|
||||
<RadioButton
|
||||
Checked="Sort_Checked"
|
||||
Content="{ext:Locale GameListHeaderDeveloper}"
|
||||
Content="{ext:Locale GameListSortDeveloper}"
|
||||
GroupName="Sort"
|
||||
IsChecked="{Binding IsSortedByDeveloper, Mode=OneTime}"
|
||||
Tag="Developer" />
|
||||
<RadioButton
|
||||
Checked="Sort_Checked"
|
||||
Content="{ext:Locale GameListHeaderTimePlayed}"
|
||||
Content="{ext:Locale GameListSortTimePlayed}"
|
||||
GroupName="Sort"
|
||||
IsChecked="{Binding IsSortedByTimePlayed, Mode=OneTime}"
|
||||
Tag="TotalTimePlayed" />
|
||||
<RadioButton
|
||||
Checked="Sort_Checked"
|
||||
Content="{ext:Locale GameListHeaderLastPlayed}"
|
||||
Content="{ext:Locale GameListSortLastPlayed}"
|
||||
GroupName="Sort"
|
||||
IsChecked="{Binding IsSortedByLastPlayed, Mode=OneTime}"
|
||||
Tag="LastPlayed" />
|
||||
<RadioButton
|
||||
Checked="Sort_Checked"
|
||||
Content="{ext:Locale GameListHeaderFileExtension}"
|
||||
Content="{ext:Locale GameListSortFileExtension}"
|
||||
GroupName="Sort"
|
||||
IsChecked="{Binding IsSortedByType, Mode=OneTime}"
|
||||
Tag="FileType" />
|
||||
<RadioButton
|
||||
Checked="Sort_Checked"
|
||||
Content="{ext:Locale GameListHeaderFileSize}"
|
||||
Content="{ext:Locale GameListSortFileSize}"
|
||||
GroupName="Sort"
|
||||
IsChecked="{Binding IsSortedBySize, Mode=OneTime}"
|
||||
Tag="FileSize" />
|
||||
<RadioButton
|
||||
Checked="Sort_Checked"
|
||||
Content="{ext:Locale GameListHeaderPath}"
|
||||
Content="{ext:Locale GameListSortPath}"
|
||||
GroupName="Sort"
|
||||
IsChecked="{Binding IsSortedByPath, Mode=OneTime}"
|
||||
Tag="Path" />
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||
mc:Ignorable="d"
|
||||
x:DataType="viewModels:SettingsViewModel">
|
||||
<Design.DataContext>
|
||||
@@ -69,7 +70,7 @@
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<CheckBox IsChecked="{Binding UseHypervisor}"
|
||||
IsVisible="{Binding IsAppleSiliconMac}"
|
||||
IsVisible="{x:Static helper:RunningPlatform.IsArmMac}"
|
||||
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
|
||||
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||
Design.Width="1000"
|
||||
mc:Ignorable="d"
|
||||
x:DataType="viewModels:SettingsViewModel">
|
||||
@@ -48,7 +49,7 @@
|
||||
<ComboBoxItem IsEnabled="{Binding IsOpenGLAvailable}">
|
||||
<TextBlock Text="OpenGL" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem IsEnabled="{Binding IsAppleSiliconMac}">
|
||||
<ComboBoxItem IsEnabled="{x:Static helper:RunningPlatform.IsArmMac}">
|
||||
<TextBlock Text="Metal (ARM Mac only, Experimental)" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
@@ -170,7 +170,8 @@
|
||||
ToolTip.Tip="{ext:Locale TimeTooltip}"
|
||||
Width="250"/>
|
||||
<DatePicker
|
||||
VerticalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding !MatchSystemTime}"
|
||||
SelectedDate="{Binding CurrentDate}"
|
||||
ToolTip.Tip="{ext:Locale TimeTooltip}"
|
||||
Width="350" />
|
||||
@@ -181,17 +182,21 @@
|
||||
<TimePicker
|
||||
VerticalAlignment="Center"
|
||||
ClockIdentifier="24HourClock"
|
||||
IsEnabled="{Binding !MatchSystemTime}"
|
||||
SelectedTime="{Binding CurrentTime}"
|
||||
Width="350"
|
||||
ToolTip.Tip="{ext:Locale TimeTooltip}" />
|
||||
<Button
|
||||
Margin="10, 0, 0, 0"
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Click="MatchSystemTime_OnClick"
|
||||
Background="{DynamicResource SystemAccentColor}"
|
||||
ToolTip.Tip="{ext:Locale MatchTimeTooltip}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemTimeMatch}" />
|
||||
</Button>
|
||||
Text="{ext:Locale SettingsTabSystemSystemTimeMatch}"
|
||||
ToolTip.Tip="{ext:Locale MatchTimeTooltip}"
|
||||
Width="250"/>
|
||||
<CheckBox
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding MatchSystemTime}"
|
||||
ToolTip.Tip="{ext:Locale MatchTimeTooltip}"/>
|
||||
</StackPanel>
|
||||
<Separator />
|
||||
<StackPanel Margin="0,10,0,10"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
@@ -35,7 +34,5 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
||||
ViewModel.ValidateAndSetTimeZone(timeZone.Location);
|
||||
}
|
||||
}
|
||||
|
||||
private void MatchSystemTime_OnClick(object sender, RoutedEventArgs e) => ViewModel.MatchSystemTime();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.VisualTree;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
ModLoader.ModCache mods = new();
|
||||
|
||||
ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleIdValue);
|
||||
ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleIdValue, []);
|
||||
|
||||
string currentCheatFile = string.Empty;
|
||||
string buildId = string.Empty;
|
||||
|
||||
@@ -2,8 +2,6 @@ using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Styling;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
|
||||
@@ -33,7 +33,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -303,7 +302,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
LinuxHelper.RecommendedVmMaxMapCount);
|
||||
|
||||
UserResult response = await ContentDialogHelper.ShowTextDialog(
|
||||
$"Ryujinx - {LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTitle]}",
|
||||
RyujinxApp.FormatTitle(LocaleKeys.LinuxVmMaxMapCountDialogTitle, false),
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary],
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextSecondary],
|
||||
LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogButtonUntilRestart],
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
MaxLines="2"
|
||||
TextWrapping="Wrap"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Text="{Binding Name}" />
|
||||
Text="{Binding FormattedName}" />
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Spacing="10"
|
||||
|
||||
@@ -6,6 +6,7 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Common.Helper;
|
||||
using System.Threading.Tasks;
|
||||
using Button = Avalonia.Controls.Button;
|
||||
@@ -23,21 +24,21 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ModManagerWindow(ulong titleId)
|
||||
public ModManagerWindow(ulong titleId, ulong titleIdBase, ApplicationLibrary applicationLibrary)
|
||||
{
|
||||
DataContext = ViewModel = new ModManagerViewModel(titleId);
|
||||
DataContext = ViewModel = new ModManagerViewModel(titleId, titleIdBase, applicationLibrary);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static async Task Show(ulong titleId, string titleName)
|
||||
public static async Task Show(ulong titleId, ulong titleIdBase, ApplicationLibrary appLibrary, string titleName)
|
||||
{
|
||||
ContentDialog contentDialog = new()
|
||||
{
|
||||
PrimaryButtonText = string.Empty,
|
||||
SecondaryButtonText = string.Empty,
|
||||
CloseButtonText = string.Empty,
|
||||
Content = new ModManagerWindow(titleId),
|
||||
Content = new ModManagerWindow(titleId, titleIdBase, appLibrary),
|
||||
Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowTitle], titleName, titleId.ToString("X16")),
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:settings="clr-namespace:Ryujinx.Ava.UI.Views.Settings"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
|
||||
Width="1100"
|
||||
Height="850"
|
||||
MinWidth="800"
|
||||
@@ -107,24 +108,36 @@
|
||||
</Style>
|
||||
</ui:NavigationView.Styles>
|
||||
</ui:NavigationView>
|
||||
<ReversibleStackPanel
|
||||
Grid.Row="2"
|
||||
Margin="10"
|
||||
Spacing="10"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
ReverseOrder="{Binding IsMacOS}">
|
||||
<Button
|
||||
Classes="accent"
|
||||
Content="{ext:Locale SettingsButtonOk}"
|
||||
Command="{Binding OkButton}" />
|
||||
<Button
|
||||
HotKey="Escape"
|
||||
Content="{ext:Locale SettingsButtonCancel}"
|
||||
Command="{Binding CancelButton}" />
|
||||
<Button
|
||||
Content="{ext:Locale SettingsButtonApply}"
|
||||
Command="{Binding ApplyButton}" />
|
||||
</ReversibleStackPanel>
|
||||
<Grid Grid.Row="2"
|
||||
ColumnDefinitions="Auto,*,Auto">
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||
<Button
|
||||
IsEnabled="{Binding WantsToReset}"
|
||||
Margin="10"
|
||||
Content="{ext:Locale SettingsButtonReset}"
|
||||
Command="{Binding ResetButton}" />
|
||||
<CheckBox IsChecked="{Binding WantsToReset}"/>
|
||||
<TextBlock Text="{ext:Locale SettingsButtonResetConfirm}"/>
|
||||
</StackPanel>
|
||||
<ReversibleStackPanel
|
||||
Grid.Column="2"
|
||||
Margin="10"
|
||||
Spacing="10"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
ReverseOrder="{x:Static helper:RunningPlatform.IsMacOS}">
|
||||
<Button
|
||||
Classes="accent"
|
||||
Content="{ext:Locale SettingsButtonOk}"
|
||||
Command="{Binding OkButton}" />
|
||||
<Button
|
||||
HotKey="Escape"
|
||||
Content="{ext:Locale SettingsButtonCancel}"
|
||||
Command="{Binding CancelButton}" />
|
||||
<Button
|
||||
Content="{ext:Locale SettingsButtonApply}"
|
||||
Command="{Binding ApplyButton}" />
|
||||
</ReversibleStackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</window:StyleableAppWindow>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
@@ -34,7 +31,6 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
#if DEBUG
|
||||
this.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Alt));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
public SettingsWindow()
|
||||
|
||||
Reference in New Issue
Block a user