diff --git a/tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs b/tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs index 38818c92..111b34ba 100644 --- a/tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs +++ b/tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs @@ -185,6 +185,32 @@ public class PortalVisibilityBuilderTests Assert.False(frame.OutsideView.IsEmpty); } + [Fact] + public void Build_ViewGrowthAfterDoneCell_RePopsGrownCell() + { + // Same A->B(near LEFT) + A->D(far RIGHT) + D->B(later) topology as + // Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit: B is popped via LEFT, then D grows B + // through RIGHT after B is done -> B re-pops. This is retail-faithful late growth (kept by the fix). + const uint A = 0x0001, B = 0x0002, D = 0x0003; + var a = Cell(A, new CellPortalInfo((ushort)B, 0, 0, 0), new CellPortalInfo((ushort)D, 1, 0, 0)); + a.PortalPolygons.Add(QuadX(-0.9f, -0.3f, -2f)); + a.PortalPolygons.Add(QuadX(0.3f, 0.9f, -5f)); + var b = Cell(B, new CellPortalInfo((ushort)A, 0, 0, 0), + new CellPortalInfo(0xFFFF, 1, 0, 0), new CellPortalInfo((ushort)D, 2, 0, 0)); + b.PortalPolygons.Add(QuadX(-0.9f, -0.3f, -2f)); + b.PortalPolygons.Add(QuadX(0.3f, 0.9f, -3f)); + b.PortalPolygons.Add(QuadX(0.3f, 0.9f, -5f)); + var d = Cell(D, new CellPortalInfo((ushort)B, 0, 0, 2)); + d.PortalPolygons.Add(QuadX(0.3f, 0.9f, -5f)); + var all = new Dictionary { [A] = a, [B] = b, [D] = d }; + + var frame = Build(a, all); + + // Membership (the flap-relevant output) is each cell once, regardless of re-pops. + Assert.Equal(new[] { B }, frame.OrderedVisibleCells.Where(c => c == B).ToArray()); + Assert.Contains(D, frame.OrderedVisibleCells); + } + [Fact] public void Builder_SealedCellar_NoExitPortal_OutsideViewEmpty() {