diff --git a/src/HexManiac.Core/Models/Runs/Sprites/LzSpriteRun.cs b/src/HexManiac.Core/Models/Runs/Sprites/LzSpriteRun.cs index c260bc56..9265fc24 100644 --- a/src/HexManiac.Core/Models/Runs/Sprites/LzSpriteRun.cs +++ b/src/HexManiac.Core/Models/Runs/Sprites/LzSpriteRun.cs @@ -18,7 +18,6 @@ public LzSpriteRun(SpriteFormat spriteFormat, IDataModel data, int start, SortedSpan sources = null) : base(data, start, spriteFormat.AllowLengthErrors, sources) { - if (start== 0xB9E8C4) { } SpriteFormat = spriteFormat; if (spriteFormat.ExpectedByteLength > DecompressedLength) InvalidateLength(); var hintContent = string.Empty; diff --git a/src/HexManiac.Core/ViewModels/ImageEditorViewModel.cs b/src/HexManiac.Core/ViewModels/ImageEditorViewModel.cs index bc3f0a57..d6dd0110 100644 --- a/src/HexManiac.Core/ViewModels/ImageEditorViewModel.cs +++ b/src/HexManiac.Core/ViewModels/ImageEditorViewModel.cs @@ -71,6 +71,11 @@ namespace HavenSoft.HexManiac.Core.ViewModels { #endregion + #region Pages + private int spritePage; + public int SpritePage { get => spritePage; set => Set(ref spritePage, value, _ => Refresh()); } + #endregion + private IImageToolStrategy toolStrategy; private EyeDropperTool eyeDropperStrategy; // stored separately because of right-click private PanTool panStrategy; // stored separately because of center-click @@ -242,7 +247,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { public void Refresh() { var spriteAddress = model.ReadPointer(SpritePointer); var spriteRun = (ISpriteRun)model.GetNextRun(spriteAddress); - pixels = spriteRun.GetPixels(model, 0); + pixels = spriteRun.GetPixels(model, SpritePage); Render(); RefreshPaletteColors(); } @@ -299,7 +304,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { private void UpdateSpriteModel() { var spriteAddress = model.ReadPointer(SpritePointer); var spriteRun = (ISpriteRun)model.GetNextRun(spriteAddress); - spriteRun.SetPixels(model, history.CurrentChange, 0, pixels); + spriteRun.SetPixels(model, history.CurrentChange, SpritePage, pixels); } private void UpdateSelectionFromPaletteHover(PaletteCollection sender, PropertyChangedEventArgs e) { diff --git a/src/HexManiac.Core/ViewModels/Tools/SpriteTool.cs b/src/HexManiac.Core/ViewModels/Tools/SpriteTool.cs index ad601fb0..d53fc650 100644 --- a/src/HexManiac.Core/ViewModels/Tools/SpriteTool.cs +++ b/src/HexManiac.Core/ViewModels/Tools/SpriteTool.cs @@ -384,7 +384,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { public ICommand NextPalettePage => nextPalPage; private StubCommand openInImageTab; - public ICommand OpenInImageTab => StubCommand(ref openInImageTab, () => viewPort.OpenImageEditorTab(spriteAddress), () => { + public ICommand OpenInImageTab => StubCommand(ref openInImageTab, () => viewPort.OpenImageEditorTab(spriteAddress, spritePage, palPage), () => { if (model.GetNextRun(spriteAddress) is ISpriteRun spriteRun && !spriteRun.SupportsEdit) return false; return exportPair.CanExecute(null); }); diff --git a/src/HexManiac.Core/ViewModels/ViewPort.cs b/src/HexManiac.Core/ViewModels/ViewPort.cs index fd45b97b..273d4805 100644 --- a/src/HexManiac.Core/ViewModels/ViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ViewPort.cs @@ -1561,8 +1561,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels { RequestTabChange(this, newTab); } - public void OpenImageEditorTab(int address) { - var newTab = new ImageEditorViewModel(history, Model, address); + public void OpenImageEditorTab(int address, int spritePage, int palettePage) { + var newTab = new ImageEditorViewModel(history, Model, address) { SpritePage = spritePage }; RequestTabChange(this, newTab); } diff --git a/src/HexManiac.Tests/ImageEditorTests.cs b/src/HexManiac.Tests/ImageEditorTests.cs index b1c64201..7e4dfd7b 100644 --- a/src/HexManiac.Tests/ImageEditorTests.cs +++ b/src/HexManiac.Tests/ImageEditorTests.cs @@ -64,6 +64,23 @@ namespace HavenSoft.HexManiac.Tests { editor = new ImageEditorViewModel(history, model, 0); } + private void Create2PageCompressedSprite() { + // header: 10 40 00 00 + // body: 0b00111000 00 00 1F0 1F0 1F0 00 00 00 + // 0x00 00 00 00 00 00 + + model.WriteValue(history.CurrentChange, 0, 0x4010); + model[4] = 0b00111000; + model.WriteMultiByteValue(7, 2, history.CurrentChange, 0x1F0); + model.WriteMultiByteValue(9, 2, history.CurrentChange, 0x1F0); + model.WriteMultiByteValue(11, 2, history.CurrentChange, 0x1F0); + + var sprite = new LzSpriteRun(new SpriteFormat(4, 1, 1, "palette"), model, 0, new SortedSpan(0x80)); + model.ObserveAnchorWritten(history.CurrentChange, "sprite", sprite); + + editor.Refresh(); + } + [Fact] public void Palette_Default_NoColorsSelected() { Assert.Empty(editor.Palette.Elements.Where(sc => sc.Selected)); @@ -638,5 +655,18 @@ namespace HavenSoft.HexManiac.Tests { Assert.True(editor.ShowSelectionRect(5, 5)); } + + [Fact] + public void TwoPageSprite_RequestSecondPage_EditsSecondPage() { + Create2PageCompressedSprite(); + editor.SpritePage = 1; + editor.Palette.Elements[1].Color = White; + editor.Palette.SelectionStart = 1; + + ToolMove(new Point(-4, -4)); + + var decompress = LZRun.Decompress(model, 0); + Assert.Equal(1, decompress[0x20] & 0xF); + } } }