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 @@ - + -