feat(selection): port retail offscreen target indicator
This commit is contained in:
parent
ea4f52ec51
commit
ec1bb19609
9 changed files with 404 additions and 97 deletions
|
|
@ -15,7 +15,7 @@ namespace AcDream.App.Tests.Rendering;
|
|||
public sealed class RetailSelectionAssetTests
|
||||
{
|
||||
[Fact]
|
||||
public void InstalledDat_ResolvesAllFourVividTargetCorners()
|
||||
public void InstalledDat_ResolvesAllTwelveVividTargetImages()
|
||||
{
|
||||
string datDir = ResolveDatDir();
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
|
|
@ -24,7 +24,7 @@ public sealed class RetailSelectionAssetTests
|
|||
uint subMapDid = master.ClientEnumToID[0x10000009u];
|
||||
var subMap = Assert.IsType<EnumIDMap>(dats.Get<EnumIDMap>(subMapDid));
|
||||
|
||||
for (uint index = 0; index < 4; index++)
|
||||
for (uint index = 0; index < 12; index++)
|
||||
{
|
||||
uint enumValue = 1u + index;
|
||||
uint did = RetailDataIdResolver.Resolve(dats, enumValue, 0x10000009u);
|
||||
|
|
@ -35,7 +35,8 @@ public sealed class RetailSelectionAssetTests
|
|||
$"enum 0x{enumValue:X8} resolved 0x{did:X8}");
|
||||
Assert.NotNull(surface);
|
||||
Assert.Equal(0x06000000u, did & 0xFF000000u);
|
||||
Assert.Equal((12, 12), (surface.Width, surface.Height));
|
||||
Assert.Equal(index < 4 ? (12, 12) : (24, 24),
|
||||
(surface.Width, surface.Height));
|
||||
|
||||
Palette? palette = surface.DefaultPaletteId != 0
|
||||
? dats.Get<Palette>(surface.DefaultPaletteId)
|
||||
|
|
@ -51,7 +52,7 @@ public sealed class RetailSelectionAssetTests
|
|||
coloredPixels++;
|
||||
}
|
||||
Assert.True(coloredPixels == 0,
|
||||
$"corner {index + 1} has {coloredPixels} non-grayscale source pixels");
|
||||
$"image {index + 1} has {coloredPixels} non-grayscale source pixels");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,4 +37,78 @@ public sealed class VividTargetIndicatorLayoutTests
|
|||
Assert.Equal(new Vector2(8f, 8f), layout.RootPosition);
|
||||
Assert.Equal(new Vector2(66f, 87f), layout.RootSize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProjectionHasNoDistanceOrWorldDrawVisibilityGate()
|
||||
{
|
||||
Matrix4x4 projection = Matrix4x4.CreatePerspectiveFieldOfView(
|
||||
MathF.PI / 2f, 4f / 3f, 0.1f, 100f);
|
||||
|
||||
VividTargetProjection result = VividTargetIndicatorController.ComputeProjection(
|
||||
new Vector3(0f, 0f, -1_000_000f),
|
||||
1f,
|
||||
Matrix4x4.Identity,
|
||||
projection,
|
||||
new Vector2(800f, 600f));
|
||||
|
||||
Assert.Equal(VividTargetProjectionStatus.OnScreen, result.Status);
|
||||
Assert.InRange((result.RectMin.X + result.RectMax.X) * 0.5f, 399.9f, 400.1f);
|
||||
Assert.InRange((result.RectMin.Y + result.RectMax.Y) * 0.5f, 299.9f, 300.1f);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(100f, 0f, -10f, 0f, 6u)]
|
||||
[InlineData(0f, 100f, -10f, 90f, 9u)]
|
||||
[InlineData(-100f, 0f, -10f, 180f, 11u)]
|
||||
[InlineData(0f, -100f, -10f, 270f, 8u)]
|
||||
public void OffScreenDirectionMatchesRetailViewerAxes(
|
||||
float x, float y, float z, float expectedAngle, uint expectedImageEnum)
|
||||
{
|
||||
Matrix4x4 projection = Matrix4x4.CreatePerspectiveFieldOfView(
|
||||
MathF.PI / 2f, 4f / 3f, 0.1f, 100f);
|
||||
|
||||
VividTargetProjection result = VividTargetIndicatorController.ComputeProjection(
|
||||
new Vector3(x, y, z),
|
||||
1f,
|
||||
Matrix4x4.Identity,
|
||||
projection,
|
||||
new Vector2(800f, 600f));
|
||||
|
||||
Assert.Equal(VividTargetProjectionStatus.OffScreen, result.Status);
|
||||
Assert.Equal(expectedAngle, result.AngleDegrees, precision: 3);
|
||||
Assert.Equal(expectedImageEnum,
|
||||
VividTargetIndicatorController.SelectOffScreenImageEnum(result.AngleDegrees));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0f, 768f, 288f)]
|
||||
[InlineData(90f, 388f, 8f)]
|
||||
[InlineData(180f, 8f, 288f)]
|
||||
[InlineData(270f, 388f, 568f)]
|
||||
public void OffScreenImageClampsToRetailEightPixelEdge(
|
||||
float angle, float expectedLeft, float expectedTop)
|
||||
{
|
||||
Vector2 position = VividTargetIndicatorController.ComputeOffScreenPosition(
|
||||
angle,
|
||||
new Vector2(800f, 600f),
|
||||
new Vector2(24f, 24f));
|
||||
|
||||
Assert.Equal(expectedLeft, position.X, precision: 3);
|
||||
Assert.Equal(expectedTop, position.Y, precision: 3);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0f, 6u)]
|
||||
[InlineData(22.999f, 6u)]
|
||||
[InlineData(23f, 7u)]
|
||||
[InlineData(68f, 9u)]
|
||||
[InlineData(113f, 12u)]
|
||||
[InlineData(158f, 11u)]
|
||||
[InlineData(203f, 10u)]
|
||||
[InlineData(248f, 8u)]
|
||||
[InlineData(293f, 5u)]
|
||||
[InlineData(338f, 6u)]
|
||||
public void DirectionImageUsesRetailSectorBoundaries(float angle, uint expected)
|
||||
=> Assert.Equal(expected,
|
||||
VividTargetIndicatorController.SelectOffScreenImageEnum(angle));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue