Amiibo Window Layout Adjustments + Other

This commit is contained in:
_Neo_ 2025-12-06 19:44:13 +02:00
parent 39653c5250
commit ed8cda4b0e
5 changed files with 154 additions and 160 deletions

View file

@ -2995,26 +2995,26 @@
{ {
"ID": "GameListContextMenuTrimXCI", "ID": "GameListContextMenuTrimXCI",
"Translations": { "Translations": {
"ar_SA": "فحص & تقليم XCI", "ar_SA": "تقليم XCI",
"de_DE": "Überprüfen & Zuschneiden der XCI", "de_DE": "Zuschneiden der XCI",
"el_GR": "Έλεγχος & Κοπή XCI", "el_GR": "Κοπή XCI",
"en_US": "Check & Trim XCI", "en_US": "Trim XCI",
"es_ES": "Verificar & Recortar XCI", "es_ES": "Recortar XCI",
"fr_FR": "Vérifier & Réduire le XCI", "fr_FR": "Réduire le XCI",
"he_IL": "בדוק & חתוך XCI", "he_IL": "חתוך XCI",
"it_IT": "Controlla & Riduci il XCI", "it_IT": "Riduci il XCI",
"ja_JP": "XCIを確認 & トリム", "ja_JP": "XCIをトリム",
"ko_KR": "XCI 확인 & 트림", "ko_KR": "XCI 트림",
"no_NO": "Kontroller & trim XCI", "no_NO": null,
"pl_PL": "Sprawdź & Przytnij XCI", "pl_PL": "Przytnij XCI",
"pt_BR": "Verificar & Reduzir o XCI", "pt_BR": "Reduzir o XCI",
"ru_RU": "Проверить & обрезать XCI", "ru_RU": "Обрезать XCI",
"sv_SE": "Kontrollera & optimera XCI", "sv_SE": "Optimera XCI",
"th_TH": "ตรวจสอบ & ลดขนาด XCI", "th_TH": "ลดขนาด XCI",
"tr_TR": "XCI'yi Kontrol Et & Kırp", "tr_TR": "XCI'yi Kırp",
"uk_UA": "Перевірка & нарізка XCI", "uk_UA": "Нарізка XCI",
"zh_CN": "检查并精简 XCI", "zh_CN": "精简 XCI",
"zh_TW": "檢查 & 修剪 XCI" "zh_TW": "修剪 XCI"
} }
}, },
{ {
@ -15445,26 +15445,26 @@
{ {
"ID": "AmiiboSeriesLabel", "ID": "AmiiboSeriesLabel",
"Translations": { "Translations": {
"ar_SA": "مجموعة أميبو", "ar_SA": "سلسلة",
"de_DE": "Amiibo-Serie", "de_DE": "Serie",
"el_GR": "Σειρά Amiibo", "el_GR": "Σειρά",
"en_US": "Amiibo Series", "en_US": "Series",
"es_ES": "Serie de Amiibo", "es_ES": "Serie",
"fr_FR": "Séries Amiibo", "fr_FR": "Séries",
"he_IL": "סדרת אמיבו", "he_IL": "סדרה",
"it_IT": "Serie Amiibo", "it_IT": "Serie",
"ja_JP": "Amiibo シリーズ", "ja_JP": "シリーズ",
"ko_KR": "Amiibo 시리즈", "ko_KR": "시리즈",
"no_NO": "Amibo Serie", "no_NO": "Serie",
"pl_PL": "Seria Amiibo", "pl_PL": "Seria",
"pt_BR": "Franquia Amiibo", "pt_BR": "Série",
"ru_RU": "Серия Amiibo", "ru_RU": "Серия",
"sv_SE": "Amiibo-serie", "sv_SE": "Serie",
"th_TH": "ชุดซีรีส์ Amiibo", "th_TH": "ซีรีส์",
"tr_TR": "Amiibo Serisi", "tr_TR": "Seri",
"uk_UA": "Серія Amiibo", "uk_UA": "Серія",
"zh_CN": "Amiibo 系列", "zh_CN": "系列",
"zh_TW": "Amiibo 系列" "zh_TW": "系列"
} }
}, },
{ {
@ -15520,26 +15520,26 @@
{ {
"ID": "AmiiboOptionsUsRandomTagLabel", "ID": "AmiiboOptionsUsRandomTagLabel",
"Translations": { "Translations": {
"ar_SA": "هاك: استخدم UUID عشوائي للتاج", "ar_SA": "هاك: UUID عشوائي للتاج",
"de_DE": "Hack: Benutze zufällige Tag-UUID", "de_DE": "Hack: Zufällige Tag-UUID",
"el_GR": "Hack: Χρησιμοποιήστε τυχαίο UUID για το Tag", "el_GR": "Hack: Τυχαίο UUID για το Tag",
"en_US": "Hack: Use Random Tag UUID", "en_US": "Hack: Random UUID Tag",
"es_ES": "Hack: Usar UUID de Etiqueta Aleatorio", "es_ES": "Hack: UUID de Etiqueta Aleatorio",
"fr_FR": "Hack : Utiliser un Tag UUID Aléatoire", "fr_FR": "Hack : Tag UUID Aléatoire",
"he_IL": "האצה: השתמש ב-UUID אקראי לתג", "he_IL": "האצה: UUID אקראי לתג",
"it_IT": "Espediente: Usa un UUID del tag casuale", "it_IT": "Espediente: UUID del tag casuale",
"ja_JP": "ハック: ランダムなタグ UUID を使用", "ja_JP": "ハック: ランダムなタグ UUID",
"ko_KR": "핵 : 무작위 태그 UUID 사용", "ko_KR": "핵 : 무작위 태그 UUID",
"no_NO": "Hack: Bruk tilfeldig tag-UUID", "no_NO": "Hack: Tilfeldig tag-UUID",
"pl_PL": "Hack: Użyj losowego UUID tagu", "pl_PL": "Hack: Losowy UUID tagu",
"pt_BR": "Hack: Usar UUID de tag Aleatório", "pt_BR": "Hack: UUID de tag Aleatório",
"ru_RU": "Хак: Использовать случайный тег UUID", "ru_RU": "Хак: Случайный тег UUID",
"sv_SE": "Hack: Använd slumpmässig tagg för UUID", "sv_SE": "Hack: Slumpmässig tagg för UUID",
"th_TH": "แฮ็ค: ใช้ UUID แท็กแบบสุ่ม", "th_TH": "แฮ็ค: UUID แท็กแบบสุ่ม",
"tr_TR": "Hack: Rastgele bir UUID kullan", "tr_TR": "Hack: Rastgele UUID tag",
"uk_UA": "Хак: Використовувати випадковий тег UUID", "uk_UA": "Хак: Випадковий тег UUID",
"zh_CN": "破解:使用随机标签 UUID", "zh_CN": "破解:随机标签 UUID",
"zh_TW": "破解:使用隨機標籤 UUID" "zh_TW": "破解:隨機標籤 UUID"
} }
}, },
{ {

View file

@ -105,6 +105,7 @@
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuTrimXCI}" Header="{ext:Locale GameListContextMenuTrimXCI}"
IsEnabled="{Binding TrimXCIEnabled}" IsEnabled="{Binding TrimXCIEnabled}"
IsVisible="{Binding IsXCIFile}"
Icon="{ext:Icon fa-solid fa-scissors}" /> Icon="{ext:Icon fa-solid fa-scissors}" />
<MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon fa-solid fa-memory}"> <MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon fa-solid fa-memory}">
<MenuItem <MenuItem

View file

@ -317,28 +317,21 @@ namespace Ryujinx.Ava.UI.ViewModels
_amiiboSeries.Clear(); _amiiboSeries.Clear();
_amiibos.Clear(); _amiibos.Clear();
for (int i = 0; i < _amiiboList.Count; i++) foreach (var amiibo in _amiiboList)
{ {
if (!_amiiboSeries.Contains(_amiiboList[i].AmiiboSeries)) if (!_amiiboSeries.Contains(amiibo.AmiiboSeries))
{ {
if (!ShowAllAmiibo) if (!ShowAllAmiibo)
{ {
foreach (AmiiboApiGamesSwitch game in _amiiboList[i].GamesSwitch) bool compatible = amiibo.GamesSwitch.Any(game => game != null && game.GameId.Contains(TitleId));
if (compatible)
{ {
if (game != null) _amiiboSeries.Add(amiibo.AmiiboSeries);
{
if (game.GameId.Contains(TitleId))
{
AmiiboSeries.Add(_amiiboList[i].AmiiboSeries);
break;
}
}
} }
} }
else else
{ {
AmiiboSeries.Add(_amiiboList[i].AmiiboSeries); _amiiboSeries.Add(amiibo.AmiiboSeries);
} }
} }
} }
@ -347,10 +340,16 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
SelectLastScannedAmiibo(); SelectLastScannedAmiibo();
} }
else else if (_amiiboSeries.Count > 0)
{ {
SeriesSelectedIndex = 0; SeriesSelectedIndex = 0;
} }
else
{
SeriesSelectedIndex = -1;
}
FilterAmiibo();
} }
private void SelectLastScannedAmiibo() private void SelectLastScannedAmiibo()
@ -367,52 +366,52 @@ namespace Ryujinx.Ava.UI.ViewModels
List<AmiiboApi> amiiboSortedList; List<AmiiboApi> amiiboSortedList;
// If no series selected, just display all available amiibos
if (_seriesSelectedIndex < 0) if (_seriesSelectedIndex < 0)
{ {
amiiboSortedList = _amiiboList amiiboSortedList = _amiiboList
.OrderBy(amiibo => amiibo.AmiiboSeries) .OrderBy(amiibo => amiibo.AmiiboSeries)
.ThenBy(x => x.Name) .ThenBy(amiibo => amiibo.Name)
.ToList(); .ToList();
} }
else else
{ {
string selectedSeries = _amiiboSeries[SeriesSelectedIndex];
amiiboSortedList = _amiiboList amiiboSortedList = _amiiboList
.Where(amiibo => amiibo.AmiiboSeries == _amiiboSeries[SeriesSelectedIndex]) .Where(amiibo => amiibo.AmiiboSeries == selectedSeries)
.OrderBy(amiibo => amiibo.Name).ToList(); .OrderBy(amiibo => amiibo.Name)
.ToList();
} }
foreach (var amiibo in amiiboSortedList)
for (int i = 0; i < amiiboSortedList.Count; i++)
{ {
if (!_amiibos.Contains(amiiboSortedList[i])) if (!_showAllAmiibo)
{ {
if (!_showAllAmiibo) bool compatible = amiibo.GamesSwitch.Any(game => game != null && game.GameId.Contains(TitleId));
{
foreach (AmiiboApiGamesSwitch game in amiiboSortedList[i].GamesSwitch)
{
if (game != null)
{
if (game.GameId.Contains(TitleId))
{
_amiibos.Add(amiiboSortedList[i]);
break; if (compatible)
}
}
}
}
else
{ {
_amiibos.Add(amiiboSortedList[i]); _amiibos.Add(amiibo);
} }
} }
else
{
_amiibos.Add(amiibo);
}
} }
AmiiboSelectedIndex = 0; int restoredIndex = -1;
} for (int i = 0; i < _amiibos.Count; i++)
{
if (_amiibos[i].GetId() == LastScannedAmiiboId)
{
restoredIndex = i;
break;
}
}
AmiiboSelectedIndex = restoredIndex != -1 ? restoredIndex : (_amiibos.Count > 0 ? 0 : -1);
}
private void SetAmiiboDetails() private void SetAmiiboDetails()
{ {
ResetAmiiboPreview(); ResetAmiiboPreview();
@ -420,44 +419,32 @@ namespace Ryujinx.Ava.UI.ViewModels
Usage = string.Empty; Usage = string.Empty;
if (_amiiboSelectedIndex < 0 || _amiibos.Count < 1) if (_amiiboSelectedIndex < 0 || _amiibos.Count < 1)
{
return; return;
}
AmiiboApi selected = _amiibos[_amiiboSelectedIndex]; AmiiboApi selected = _amiibos[_amiiboSelectedIndex];
string imageUrl = _amiiboList.FirstOrDefault(amiibo => amiibo.Equals(selected)).Image; string imageUrl = selected.Image;
StringBuilder usageStringBuilder = new(); StringBuilder usageStringBuilder = new();
for (int i = 0; i < _amiiboList.Count; i++) foreach (var game in selected.GamesSwitch)
{ {
if (_amiiboList[i].Equals(selected)) if (game != null && game.GameId.Contains(TitleId))
{ {
bool writable = false; foreach (var usageItem in game.AmiiboUsage)
foreach (AmiiboApiGamesSwitch item in _amiiboList[i].GamesSwitch)
{ {
if (item.GameId.Contains(TitleId)) usageStringBuilder.Append($"{Environment.NewLine}- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}");
{
foreach (AmiiboApiUsage usageItem in item.AmiiboUsage)
{
usageStringBuilder.Append($"{Environment.NewLine}- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}");
writable = usageItem.Write;
}
}
} }
if (usageStringBuilder.Length == 0)
{
usageStringBuilder.Append($"{LocaleManager.Instance[LocaleKeys.Unknown]}.");
}
Usage = $"{LocaleManager.Instance[LocaleKeys.AmiiboUsage]}{(writable ? $"({LocaleManager.Instance[LocaleKeys.Writable]})" : string.Empty)}{usageStringBuilder}";
} }
} }
if (usageStringBuilder.Length == 0)
{
usageStringBuilder.Append($"{LocaleManager.Instance[LocaleKeys.Unknown]}.");
}
Usage = $"{LocaleManager.Instance[LocaleKeys.AmiiboUsage]}{usageStringBuilder}";
_ = UpdateAmiiboPreview(imageUrl); _ = UpdateAmiiboPreview(imageUrl);
} }

View file

@ -457,6 +457,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo; public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
public bool IsXCIFile => Path.GetExtension(SelectedApplication.Path)?.ToLower() == ".xci";
public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id); public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id);
public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder &&

View file

@ -16,40 +16,52 @@
WindowStartupLocation="CenterOwner" WindowStartupLocation="CenterOwner"
Width="800" Width="800"
MinHeight="650" MinHeight="650"
Height="650" Height="700"
SizeToContent="Manual" SizeToContent="Manual"
MinWidth="600" MinWidth="600"
Focusable="True"> Focusable="True">
<Design.DataContext> <Design.DataContext>
<viewModels:AmiiboWindowViewModel /> <viewModels:AmiiboWindowViewModel />
</Design.DataContext> </Design.DataContext>
<Grid RowDefinitions="Auto,Auto,*,Auto" Margin="15" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" > <Grid Grid.Row="0" RowDefinitions="Auto,Auto,*,Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid Name="FlushControls" ColumnDefinitions="Auto,Auto" Grid.Row="0" Margin="-15">
<!-- UI FlushControls -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,Auto,Auto" Name="FlushControls">
<controls:RyujinxLogo <controls:RyujinxLogo
Grid.Column="0" Grid.Column="0"
HorizontalAlignment="Left" Margin="7,0,7,0"
VerticalAlignment="Top"
Margin="7, 7, 0, 0"
ToolTip.Tip="{ext:WindowTitle Amiibo}" /> ToolTip.Tip="{ext:WindowTitle Amiibo}" />
<StackPanel Grid.Column="1" Orientation="Horizontal"> <StackPanel Grid.Column="1" Orientation="Horizontal">
<StackPanel Spacing="10" Orientation="Horizontal" HorizontalAlignment="Left"> <TextBlock Margin="8,0,0,0" VerticalAlignment="Center" Text="{ext:Locale AmiiboSeriesLabel}" />
<TextBlock Margin="0,40,0,15" VerticalAlignment="Center" Text="{ext:Locale AmiiboSeriesLabel}" /> <ComboBox Margin="5,5,0,5" SelectedIndex="{Binding SeriesSelectedIndex}" ItemsSource="{Binding AmiiboSeries}" MinWidth="100" />
<ComboBox Margin="0,40,0,15" SelectedIndex="{Binding SeriesSelectedIndex}" ItemsSource="{Binding AmiiboSeries}" MinWidth="100" />
</StackPanel>
</StackPanel> </StackPanel>
<CheckBox Grid.Column="2" Margin="15,0,0,0" IsChecked="{Binding ShowAllAmiibo}">
<TextBlock Text="{ext:Locale AmiiboOptionsShowAllLabel}" />
</CheckBox>
<CheckBox Grid.Column="3" Margin="15,0,0,0" HotKey="H" IsChecked="{Binding UseRandomUuid}" >
<TextBlock Text="{ext:Locale AmiiboOptionsUsRandomTagLabel}" />
</CheckBox>
</Grid> </Grid>
<Grid Margin="20,0,0,0" Name="NormalControls" ColumnDefinitions="*,*" Grid.Row="1" HorizontalAlignment="Stretch" >
<StackPanel Spacing="10" Orientation="Horizontal" HorizontalAlignment="Left"> <!-- UI NormalControls -->
<TextBlock VerticalAlignment="Center" Text="{ext:Locale AmiiboSeriesLabel}" /> <Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,Auto" Name="NormalControls">
<ComboBox SelectedIndex="{Binding SeriesSelectedIndex}" ItemsSource="{Binding AmiiboSeries}" MinWidth="100" /> <StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Margin="15,0,0,0" VerticalAlignment="Center" Text="{ext:Locale AmiiboSeriesLabel}" />
<ComboBox Margin="5,5,0,5" SelectedIndex="{Binding SeriesSelectedIndex}" ItemsSource="{Binding AmiiboSeries}" MinWidth="100" />
</StackPanel> </StackPanel>
<CheckBox Grid.Column="1" Margin="15,0,0,0" IsChecked="{Binding ShowAllAmiibo}">
<TextBlock Text="{ext:Locale AmiiboOptionsShowAllLabel}" />
</CheckBox>
<CheckBox Grid.Column="2" Margin="15,0,0,0" IsChecked="{Binding UseRandomUuid}" HotKey="H">
<TextBlock Text="{ext:Locale AmiiboOptionsUsRandomTagLabel}" />
</CheckBox>
</Grid> </Grid>
<DockPanel Grid.Row="2">
<!-- Amiibo ListBox, Images, Buttons -->
<StackPanel Grid.Row="2" Margin="0,20,0,20" Orientation="Horizontal" HorizontalAlignment="Center" Spacing="50">
<ListBox <ListBox
DockPanel.Dock="Left" Width="250"
Width="300" Padding="5"
Margin="20"
Padding="10"
SelectionMode="Single" SelectionMode="Single"
ItemsSource="{Binding AmiiboList}" ItemsSource="{Binding AmiiboList}"
SelectedIndex="{Binding AmiiboSelectedIndex}"> SelectedIndex="{Binding AmiiboSelectedIndex}">
@ -59,22 +71,14 @@
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>
<StackPanel Margin="20"> <StackPanel Width="250">
<Image Source="{Binding AmiiboImage}" Height="400" Width="200" HorizontalAlignment="Center" /> <Image Source="{Binding AmiiboImage}" Height="400" Width="200" />
<ScrollViewer MaxHeight="120" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" <ScrollViewer MaxHeight="120" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Margin="20" VerticalAlignment="Top" HorizontalAlignment="Stretch">
Margin="20" VerticalAlignment="Top" HorizontalAlignment="Stretch"> <TextBlock TextWrapping="Wrap" Text="{Binding Usage}" HorizontalAlignment="Center" TextAlignment="Center" />
<TextBlock TextWrapping="Wrap" Text="{Binding Usage}" HorizontalAlignment="Center"
TextAlignment="Center" />
</ScrollViewer> </ScrollViewer>
</StackPanel> </StackPanel>
</DockPanel> </StackPanel>
<Grid Grid.Row="3" Margin="10,0,0,0" ColumnDefinitions="Auto,Auto,*,Auto,Auto"> <Grid Grid.Row="3" Margin="0,0,10,10" ColumnDefinitions="Auto,Auto,*,Auto,Auto">
<CheckBox Margin="10" Grid.Column="0" IsChecked="{Binding ShowAllAmiibo}" >
<TextBlock Text="{ext:Locale AmiiboOptionsShowAllLabel}" />
</CheckBox>
<CheckBox HotKey="H" Margin="0,10,10,10" Grid.Column="1" IsChecked="{Binding UseRandomUuid}" >
<TextBlock Text="{ext:Locale AmiiboOptionsUsRandomTagLabel}" />
</CheckBox>
<Button Grid.Column="3" <Button Grid.Column="3"
IsEnabled="{Binding EnableScanning}" IsEnabled="{Binding EnableScanning}"
Name="ScanButton" Name="ScanButton"
@ -82,7 +86,7 @@
Content="{ext:Locale AmiiboScanButtonLabel}" Content="{ext:Locale AmiiboScanButtonLabel}"
Click="ScanButton_Click" /> Click="ScanButton_Click" />
<Button Grid.Column="4" <Button Grid.Column="4"
Margin="10,0" Margin="10,0,0,0"
Width="80" Width="80"
Name="CancelButton" Name="CancelButton"
HotKey="Escape" HotKey="Escape"