diff --git a/PKHeX.Avalonia/App.axaml b/PKHeX.Avalonia/App.axaml
index 55e5a0d2a..6d5764500 100644
--- a/PKHeX.Avalonia/App.axaml
+++ b/PKHeX.Avalonia/App.axaml
@@ -5,5 +5,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs b/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs
index 9bc2198b2..46e34db14 100644
--- a/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs
+++ b/PKHeX.Avalonia/ViewModels/MainWindowViewModel.cs
@@ -67,6 +67,11 @@ public MainWindowViewModel(IDialogService dialogService)
{
SlotSelected = pk => PkmEditor.PopulateFields(pk),
GetEditorPKM = () => PkmEditor.PreparePKM(),
+ OpenInventoryCommand = OpenInventoryCommand,
+ OpenBoxLayoutCommand = OpenBoxLayoutCommand,
+ OpenWondercardCommand = OpenWondercardCommand,
+ OpenEventFlagsCommand = OpenEventFlagsCommand,
+ OpenSettingsEditorCommand = OpenSettingsEditorCommand,
};
LoadPlugins();
}
diff --git a/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs b/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs
index db2fa3535..3a535140d 100644
--- a/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs
+++ b/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs
@@ -35,6 +35,12 @@ public partial class PKMEditorViewModel : ObservableObject
[ObservableProperty] private bool _isShiny;
[ObservableProperty] private bool _isEgg;
+ // New fields
+ [ObservableProperty] private string _pidHex = "00000000";
+ [ObservableProperty] private uint _exp;
+ [ObservableProperty] private int _friendship;
+ [ObservableProperty] private int _language;
+
// Stats
[ObservableProperty] private int _hp;
[ObservableProperty] private int _atk;
@@ -43,6 +49,14 @@ public partial class PKMEditorViewModel : ObservableObject
[ObservableProperty] private int _spD;
[ObservableProperty] private int _spe;
+ // Base Stats (read-only display)
+ [ObservableProperty] private int _base_HP;
+ [ObservableProperty] private int _base_ATK;
+ [ObservableProperty] private int _base_DEF;
+ [ObservableProperty] private int _base_SPA;
+ [ObservableProperty] private int _base_SPD;
+ [ObservableProperty] private int _base_SPE;
+
// IVs
[ObservableProperty] private int _iv_HP;
[ObservableProperty] private int _iv_ATK;
@@ -78,6 +92,8 @@ public partial class PKMEditorViewModel : ObservableObject
public IReadOnlyList NatureList => GameInfo.FilteredSources.Natures;
public IReadOnlyList HeldItemList => GameInfo.FilteredSources.Items;
public IReadOnlyList MoveList => GameInfo.FilteredSources.Moves;
+ public IReadOnlyList AbilityList => GameInfo.FilteredSources.Abilities;
+ public IReadOnlyList LanguageList => GameInfo.FilteredSources.Languages;
// Selected ComboItem bindings
[ObservableProperty] private ComboItem? _selectedSpecies;
@@ -87,6 +103,8 @@ public partial class PKMEditorViewModel : ObservableObject
[ObservableProperty] private ComboItem? _selectedMove2;
[ObservableProperty] private ComboItem? _selectedMove3;
[ObservableProperty] private ComboItem? _selectedMove4;
+ [ObservableProperty] private ComboItem? _selectedAbility;
+ [ObservableProperty] private ComboItem? _selectedLanguage;
partial void OnSelectedSpeciesChanged(ComboItem? value)
{
@@ -130,6 +148,18 @@ public partial class PKMEditorViewModel : ObservableObject
Move4 = (ushort)value.Value;
}
+ partial void OnSelectedAbilityChanged(ComboItem? value)
+ {
+ if (value is not null)
+ Ability = value.Value;
+ }
+
+ partial void OnSelectedLanguageChanged(ComboItem? value)
+ {
+ if (value is not null)
+ Language = value.Value;
+ }
+
public void Initialize(SaveFile sav)
{
_sav = sav;
@@ -151,6 +181,12 @@ public void PopulateFields(PKM pk)
IsShiny = pk.IsShiny;
IsEgg = pk.IsEgg;
+ // New fields
+ PidHex = pk.PID.ToString("X8");
+ Exp = pk.EXP;
+ Friendship = pk.CurrentFriendship;
+ Language = pk.Language;
+
Hp = pk.Stat_HPCurrent;
Atk = pk.Stat_ATK;
Def = pk.Stat_DEF;
@@ -158,6 +194,15 @@ public void PopulateFields(PKM pk)
SpD = pk.Stat_SPD;
Spe = pk.Stat_SPE;
+ // Base stats
+ var pi = pk.PersonalInfo;
+ Base_HP = pi.HP;
+ Base_ATK = pi.ATK;
+ Base_DEF = pi.DEF;
+ Base_SPA = pi.SPA;
+ Base_SPD = pi.SPD;
+ Base_SPE = pi.SPE;
+
Iv_HP = pk.IV_HP;
Iv_ATK = pk.IV_ATK;
Iv_DEF = pk.IV_DEF;
@@ -189,6 +234,8 @@ public void PopulateFields(PKM pk)
SelectedMove2 = MoveList.FirstOrDefault(x => x.Value == pk.Move2);
SelectedMove3 = MoveList.FirstOrDefault(x => x.Value == pk.Move3);
SelectedMove4 = MoveList.FirstOrDefault(x => x.Value == pk.Move4);
+ SelectedAbility = AbilityList.FirstOrDefault(x => x.Value == pk.Ability);
+ SelectedLanguage = LanguageList.FirstOrDefault(x => x.Value == pk.Language);
UpdateSprite();
}
@@ -210,6 +257,13 @@ public void PopulateFields(PKM pk)
Entity.Ability = Ability;
Entity.HeldItem = HeldItem;
+ // New fields
+ if (uint.TryParse(PidHex, System.Globalization.NumberStyles.HexNumber, null, out var pid))
+ Entity.PID = pid;
+ Entity.EXP = Exp;
+ Entity.CurrentFriendship = (byte)Math.Clamp(Friendship, 0, 255);
+ Entity.Language = Language;
+
Entity.IV_HP = Iv_HP;
Entity.IV_ATK = Iv_ATK;
Entity.IV_DEF = Iv_DEF;
diff --git a/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs b/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs
index e5187d8d7..e5de32f01 100644
--- a/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs
+++ b/PKHeX.Avalonia/ViewModels/SAVEditorViewModel.cs
@@ -1,9 +1,13 @@
using System;
using System.Collections.ObjectModel;
+using System.Windows.Input;
+using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PKHeX.Avalonia.Controls;
+using PKHeX.Avalonia.Converters;
using PKHeX.Core;
+using PKHeX.Drawing.Misc.Avalonia;
using PKHeX.Drawing.PokeSprite.Avalonia;
namespace PKHeX.Avalonia.ViewModels;
@@ -30,12 +34,23 @@ public partial class SAVEditorViewModel : ObservableObject
[ObservableProperty]
private bool _isLoaded;
+ [ObservableProperty]
+ private Bitmap? _boxWallpaper;
+
public ObservableCollection BoxSlots { get; } = [];
public ObservableCollection PartySlots { get; } = [];
+ public ObservableCollection BoxNames { get; } = [];
/// Manages drag-and-drop operations between slots.
public SlotChangeManager SlotManager { get; }
+ // SAV tool command delegates — wired from MainWindowViewModel
+ public ICommand? OpenInventoryCommand { get; set; }
+ public ICommand? OpenBoxLayoutCommand { get; set; }
+ public ICommand? OpenWondercardCommand { get; set; }
+ public ICommand? OpenEventFlagsCommand { get; set; }
+ public ICommand? OpenSettingsEditorCommand { get; set; }
+
public SAVEditorViewModel()
{
SlotManager = new SlotChangeManager(this);
@@ -55,17 +70,37 @@ public void LoadSaveFile(SaveFile sav)
BoxCount = sav.BoxCount;
CurrentBox = 0;
IsLoaded = true;
+ RefreshBoxNames();
RefreshBox();
RefreshParty();
}
+ private void RefreshBoxNames()
+ {
+ BoxNames.Clear();
+ if (_sav is null)
+ return;
+
+ for (int i = 0; i < _sav.BoxCount; i++)
+ {
+ var name = _sav is IBoxDetailNameRead n ? n.GetBoxName(i) : $"Box {i + 1}";
+ BoxNames.Add(name);
+ }
+ }
+
+ partial void OnCurrentBoxChanged(int value)
+ {
+ if (_sav is null)
+ return;
+ RefreshBox();
+ }
+
[RelayCommand]
private void NextBox()
{
if (_sav is null)
return;
CurrentBox = (CurrentBox + 1) % BoxCount;
- RefreshBox();
}
[RelayCommand]
@@ -74,7 +109,6 @@ private void PreviousBox()
if (_sav is null)
return;
CurrentBox = (CurrentBox - 1 + BoxCount) % BoxCount;
- RefreshBox();
}
private void RefreshBox()
@@ -84,6 +118,17 @@ private void RefreshBox()
BoxName = _sav is IBoxDetailNameRead n ? n.GetBoxName(CurrentBox) : $"Box {CurrentBox + 1}";
+ // Update wallpaper
+ try
+ {
+ var wpBitmap = _sav.WallpaperImage(CurrentBox);
+ BoxWallpaper = SKBitmapToAvaloniaBitmapConverter.ToAvaloniaBitmap(wpBitmap);
+ }
+ catch
+ {
+ BoxWallpaper = null;
+ }
+
int slotCount = Math.Min(30, _sav.BoxSlotCount);
for (int i = 0; i < slotCount && i < BoxSlots.Count; i++)
{
diff --git a/PKHeX.Avalonia/Views/PKMEditorView.axaml b/PKHeX.Avalonia/Views/PKMEditorView.axaml
index 8d7b2492d..6d907cf60 100644
--- a/PKHeX.Avalonia/Views/PKMEditorView.axaml
+++ b/PKHeX.Avalonia/Views/PKMEditorView.axaml
@@ -6,88 +6,117 @@
x:DataType="vm:PKMEditorViewModel">
-
-
-
-
+
+
+
+
-
-
+
+
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
@@ -97,63 +126,83 @@
-
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
@@ -190,7 +239,13 @@
-
+
+
+
+
+
+
+
@@ -200,17 +255,23 @@
-
+
+
+
+
+
+
+
-
+
-
+
-
+
diff --git a/PKHeX.Avalonia/Views/SAVEditorView.axaml b/PKHeX.Avalonia/Views/SAVEditorView.axaml
index 483836fcc..71e2df660 100644
--- a/PKHeX.Avalonia/Views/SAVEditorView.axaml
+++ b/PKHeX.Avalonia/Views/SAVEditorView.axaml
@@ -9,32 +9,44 @@
-
+
-
-
-
+
+
+ FontSize="11" Padding="0" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -69,9 +81,24 @@
-
+
+
+
+
+
+
diff --git a/PKHeX.Avalonia/Views/SlotControl.axaml b/PKHeX.Avalonia/Views/SlotControl.axaml
index 6fc84434d..46f2263fd 100644
--- a/PKHeX.Avalonia/Views/SlotControl.axaml
+++ b/PKHeX.Avalonia/Views/SlotControl.axaml
@@ -7,10 +7,29 @@
Width="70" Height="58"
Margin="0">
+
+
+
+
+
+
+
+
diff --git a/PKHeX.Drawing.Misc.Avalonia/ResourceLoader.cs b/PKHeX.Drawing.Misc.Avalonia/ResourceLoader.cs
index 528b5ce6e..6a798fab5 100644
--- a/PKHeX.Drawing.Misc.Avalonia/ResourceLoader.cs
+++ b/PKHeX.Drawing.Misc.Avalonia/ResourceLoader.cs
@@ -39,7 +39,9 @@ private static void EnsureInitialized()
if (lastDot < 0)
return null;
- return manifestName[(lastDot + 1)..^4];
+ var key = manifestName[(lastDot + 1)..^4];
+ key = key.Replace('-', '_'); // Normalize hyphens to underscores to match WinForms convention
+ return key;
}
///
diff --git a/PKHeX.Drawing.PokeSprite.Avalonia/ResourceLoader.cs b/PKHeX.Drawing.PokeSprite.Avalonia/ResourceLoader.cs
index cd5449d39..87e2ac02b 100644
--- a/PKHeX.Drawing.PokeSprite.Avalonia/ResourceLoader.cs
+++ b/PKHeX.Drawing.PokeSprite.Avalonia/ResourceLoader.cs
@@ -42,7 +42,9 @@ private static void EnsureInitialized()
if (lastDot < 0)
return null;
- return manifestName[(lastDot + 1)..^4]; // between last dot and .png
+ var key = manifestName[(lastDot + 1)..^4]; // between last dot and .png
+ key = key.Replace('-', '_'); // Normalize hyphens to underscores to match WinForms convention
+ return key;
}
///