Render DEBUGMAP tiled field surfaces
This commit is contained in:
@@ -81,6 +81,22 @@ public class AgfDecoderTests
|
||||
Assert.Contains(image.Pixels.Where((_, i) => (i & 3) == 3), a => a is > 0 and < 255);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0x32da, "SO005.AGF")]
|
||||
[InlineData(0x32db, "SO007.AGF")]
|
||||
[InlineData(0x32dc, "SO008A.AGF")]
|
||||
[InlineData(0x32dd, "SO007A.AGF")]
|
||||
public void InstalledFieldMapSheetsResolveAndDecodeByRawCatalogIndex(int rawId, string name)
|
||||
{
|
||||
var resources = ResourceMap.Load();
|
||||
var asset = resources.ResolveRawTexture(rawId);
|
||||
Assert.NotNull(asset);
|
||||
Assert.Equal(name, asset.Name);
|
||||
var image = resources.DecodeTexture(asset);
|
||||
Assert.True(image.Width > 0);
|
||||
Assert.True(image.Height > 0);
|
||||
}
|
||||
|
||||
private sealed class MemoryStore(byte[] bytes) : IAssetStore
|
||||
{
|
||||
public Stream Open(AssetEntry entry) => new MemoryStream(bytes, writable: false);
|
||||
|
||||
@@ -102,6 +102,8 @@ public class GfxCommandBufferTests
|
||||
=> (0x1fb, new[] { G(handle), G(slot), I(0), I(0), G(w), G(h), G(dx), G(dy) });
|
||||
|
||||
private static (int, Operand[]) SetTex(int resId, int slot) => (0x1f9, new[] { G(resId), G(slot), I(0) });
|
||||
private static (int, Operand[]) SetRawTex(long resId, long slot, long colorKey)
|
||||
=> (0x249, new[] { I(resId), I(slot), I(colorKey) });
|
||||
|
||||
[Fact]
|
||||
public void SetThenDrawTextureMakesAVisibleObjectFromTheSurface()
|
||||
@@ -122,4 +124,26 @@ public class GfxCommandBufferTests
|
||||
Assert.Equal(0x25, vis[0].SurfaceResId); // resolved from the object's live source slot
|
||||
Assert.Equal((800, 600, 0, 0), (vis[0].W, vis[0].H, vis[0].DstX, vis[0].DstY));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RawTextureLoadBypassesSceneResourceNormalizationAndFeedsRetainedDraws()
|
||||
{
|
||||
var t = T();
|
||||
var scene = ScriptAssembler.Assemble(t, "RAW-GFX", new List<(int, Operand[])>
|
||||
{
|
||||
SetRawTex(0x32da, 0x3e, 0),
|
||||
(0x1fb, new[] { I(0x100), I(0x3e), I(0), I(0), I(100), I(100), I(20), I(30) }),
|
||||
Exit(),
|
||||
}, System.Array.Empty<string>());
|
||||
var host = new RecordingHost { TextureResourceIdOffset = 0x1000 };
|
||||
var vm = new VirtualMachine(scene, t, host);
|
||||
|
||||
vm.Run();
|
||||
|
||||
Assert.Equal((0x32daL, 0x3e), Assert.Single(host.Textures));
|
||||
var visible = Assert.Single(vm.Gfx.SnapshotVisibleObjects());
|
||||
Assert.Equal(0x32da, visible.SurfaceResId);
|
||||
Assert.Equal(0, visible.ColorKey);
|
||||
Assert.Equal((100, 100, 20, 30), (visible.W, visible.H, visible.DstX, visible.DstY));
|
||||
}
|
||||
}
|
||||
|
||||
76
engine/Age.Engine.Tests/GfxRangeTransformTests.cs
Normal file
76
engine/Age.Engine.Tests/GfxRangeTransformTests.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Age.Engine.Model;
|
||||
using Age.Engine.Sys4;
|
||||
using Age.Engine.Vm;
|
||||
using Xunit;
|
||||
|
||||
public class GfxRangeTransformTests
|
||||
{
|
||||
[Fact]
|
||||
public void RangeCameraCentersItsAnchorAndLeavesUiHandlesUnchanged()
|
||||
{
|
||||
var gfx = new GfxState();
|
||||
gfx.SetSurface(1, 1, -1);
|
||||
gfx.BindDraw(10, 1, 0, 0, 1, 1, 500, 350); // selected map object at the camera anchor
|
||||
gfx.BindDraw(20, 1, 0, 0, 1, 1, 500, 350); // screen-fixed UI object outside the range
|
||||
gfx.SetRangeTransform(10, 1, (500, 350, 0));
|
||||
gfx.SetRangeTranslationCurrent((-100, -50, 0));
|
||||
gfx.SetRangeScaleCurrent((150, 150, 100));
|
||||
|
||||
var objects = gfx.SnapshotVisibleObjects();
|
||||
var map = objects.Single(x => x.Handle == 10);
|
||||
var ui = objects.Single(x => x.Handle == 20);
|
||||
var mapOrigin = Transform2DMath.Build(map.Transform).FromLocalOrigin(map.DstX, map.DstY)
|
||||
.Then(map.RangeTransform!.Value).Apply(0, 0);
|
||||
var uiOrigin = Transform2DMath.Build(ui.Transform).FromLocalOrigin(ui.DstX, ui.DstY).Apply(0, 0);
|
||||
|
||||
Assert.Equal((400.0, 300.0), mapOrigin);
|
||||
Assert.Null(ui.RangeTransform);
|
||||
Assert.Equal((500.0, 350.0), uiOrigin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RangeScaleTargetUsesTheOrdinaryOneShotClock()
|
||||
{
|
||||
var gfx = new GfxState();
|
||||
gfx.SetSurface(1, 1, -1);
|
||||
gfx.BindDraw(10, 1, 0, 0, 1, 1, 410, 300);
|
||||
gfx.SetRangeTransform(10, 1, (400, 300, 0));
|
||||
gfx.SetRangeScaleCurrent((100, 100, 100));
|
||||
gfx.SetRangeScaleChannel(delayMs: 0, durationMs: 300, percent: (200, 200, 100));
|
||||
|
||||
gfx.SnapshotVisibleObjects(1000); // seeds the native-style shared channel start
|
||||
var halfway = gfx.SnapshotVisibleObjects(1150).Single();
|
||||
var p = Transform2DMath.Build(halfway.Transform).FromLocalOrigin(halfway.DstX, halfway.DstY)
|
||||
.Then(halfway.RangeTransform!.Value).Apply(0, 0);
|
||||
|
||||
Assert.Equal((415.0, 300.0), p);
|
||||
Assert.True(gfx.HasActiveTimedPresentation(1150));
|
||||
gfx.SnapshotVisibleObjects(1300);
|
||||
Assert.False(gfx.HasActiveTimedPresentation(1300));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Opcode229SelectsRangeWithoutCreatingAnOrdinaryObject()
|
||||
{
|
||||
var table = OpcodeTableJson.Load(Paths.OpcodesJson);
|
||||
var script = ScriptAssembler.Assemble(table, "RANGE", new List<(int, Operand[])>
|
||||
{
|
||||
(0x229, new[] { I(1), I(100), I(400), I(300), I(0) }),
|
||||
(0x22c, new[] { I(0), I(0), I(0) }),
|
||||
(0x22a, new[] { I(100), I(100), I(100) }),
|
||||
(0x2, System.Array.Empty<Operand>()),
|
||||
}, System.Array.Empty<string>());
|
||||
var vm = new VirtualMachine(script, table, new RecordingHost());
|
||||
|
||||
vm.Run();
|
||||
|
||||
Assert.Null(vm.Gfx.TryGet(1));
|
||||
vm.Gfx.SetSurface(1, 1, -1);
|
||||
vm.Gfx.BindDraw(1, 1, 0, 0, 1, 1, 400, 300);
|
||||
Assert.NotNull(vm.Gfx.SnapshotVisibleObjects().Single().RangeTransform);
|
||||
}
|
||||
|
||||
private static Operand I(long v) => new(0, v);
|
||||
}
|
||||
@@ -42,12 +42,15 @@ internal class RecordingHost : IHost
|
||||
public readonly List<int> ClearedRenderTargets = new();
|
||||
public readonly List<(int First, int Count)> ReleasedSurfaceRanges = new();
|
||||
public readonly List<(int Source, int Target, long Interval)> SurfaceCrossfades = new();
|
||||
public readonly List<(long Resource, int Slot)> Textures = new();
|
||||
public readonly List<bool> MessageSkipChanges = new();
|
||||
public readonly List<bool> PhysicalMessageSkipChanges = new();
|
||||
public readonly List<long> CursorResources = new();
|
||||
public readonly List<bool> AdvPagePresentationSuspended = new();
|
||||
public int CursorClearCount;
|
||||
public int SceneContextResets;
|
||||
public long TextureResourceIdOffset;
|
||||
public long ResolveTextureResourceId(long resourceId) => resourceId + TextureResourceIdOffset;
|
||||
public void ShowText(int offset, string text) => Lines.Add((offset, text));
|
||||
public void SetAdvTextCursor(int layoutSlot, int x, int y) => TextCursors.Add((layoutSlot, x, y));
|
||||
public void DrawStringToSurface(int surfaceSlot, int x, int y, string text)
|
||||
@@ -123,7 +126,7 @@ internal class RecordingHost : IHost
|
||||
public void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument)
|
||||
=> SurfaceCrossfades.Add((sourceSurface, targetSurface, intervalArgument));
|
||||
public void CreateTexture(int slot, int w, int h) { }
|
||||
public void SetTexture(long resId, int slot) { }
|
||||
public void SetTexture(long resId, int slot) => Textures.Add((resId, slot));
|
||||
public void ClearRenderTarget(int surfaceSlot) => ClearedRenderTargets.Add(surfaceSlot);
|
||||
public void ReleaseSurfaceRange(int firstSlot, int count) => ReleasedSurfaceRanges.Add((firstSlot, count));
|
||||
public void DrawTexture(int slot, int sx, int sy, int w, int h, int dx, int dy) { }
|
||||
|
||||
Reference in New Issue
Block a user