From cd9b8cc13c3f03abe4b6b2c98281fc9b926b4acd Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Mon, 28 Sep 2026 09:27:14 +0800 Subject: test(desktop): P38 HUD 图标布局与确定性回归 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 P38HudIconTests(4 例):五段图标唯一且 7x7 点阵良构、段宽=图标+间隙+文本且 不重叠/在 1280 内、段与布局确定、昼夜底色半透明且覆盖图标与文本。 --- .../LivingVillage.Desktop.Tests.fsproj | 1 + src/LivingVillage.Desktop.Tests/P38HudIconTests.fs | 71 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/LivingVillage.Desktop.Tests/P38HudIconTests.fs (limited to 'src/LivingVillage.Desktop.Tests') diff --git a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj index 2413f29..8142917 100644 --- a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj +++ b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj @@ -18,6 +18,7 @@ + diff --git a/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs b/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs new file mode 100644 index 0000000..72885fb --- /dev/null +++ b/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs @@ -0,0 +1,71 @@ +namespace LivingVillage.Desktop.Tests + +open Microsoft.VisualStudio.TestTools.UnitTesting +open LivingVillage.Kernel +open LivingVillage.Kernel.Sim +open LivingVillage.Desktop + +/// P38 界面升级切片:顶部常驻 HUD 图标化(时段/时间/倍速/体力/钱币)的布局与确定性回归。 +[] +type P38HudIconTests () = + + let world = Sim.initialWorldN 42UL 4 + let control = SimulationControl.initial + let segments = HudLayout.segments world control + + [] + member _.EveryHudSegmentCarriesAWellFormedDistinctIcon () = + let expected = + [ "时段", HudLayout.PeriodIcon + "时间", HudLayout.ClockIcon + "倍速", HudLayout.SpeedIcon + "体力", HudLayout.EnergyIcon + "钱币", HudLayout.MoneyIcon ] + Assert.AreEqual(expected |> List.map fst, segments |> List.map (fun segment -> segment.Label)) + Assert.AreEqual(expected |> List.map snd, segments |> List.map (fun segment -> segment.Icon)) + for segment in segments do + let rows = HudLayout.iconRows segment.Icon + Assert.IsTrue(rows.Length = HudLayout.iconGrid, sprintf "%s 图标行数" segment.Label) + for row in rows do + Assert.IsTrue(row.Length = HudLayout.iconGrid, sprintf "%s 图标行宽" segment.Label) + Assert.IsTrue(rows |> List.exists (fun row -> row.Contains "1"), sprintf "%s 图标必须有实心像素" segment.Label) + let distinct = segments |> List.map (fun segment -> segment.Icon) |> List.distinct |> List.length + Assert.IsTrue(segments.Length = distinct, "每个常驻段图标应互不相同") + + [] + member _.HudLayoutReservesIconThenTextAndFitsTheStrip () = + let placed = HudLayout.layout segments + Assert.AreEqual(segments.Length, placed.Length) + let (firstX, _, _) = List.head placed + Assert.AreEqual(HudLayout.paddingX, firstX) + for (x, width, segment) in placed do + let textWidth = FloatingPrompt.measureWidth (HudLayout.segmentText segment) HudLayout.textScale + Assert.AreEqual(HudLayout.iconWidth + HudLayout.iconGap + textWidth, width) + // 图标与文本都必须落在段宽内。 + Assert.IsTrue(x + HudLayout.iconWidth <= x + width, "图标越出段宽") + Assert.IsTrue(HudLayout.textOrigin x + textWidth <= x + width, "文本越出段宽") + Assert.IsTrue(HudLayout.iconHeight <= HudLayout.barHeight, "图标必须放进窄条") + placed + |> List.pairwise + |> List.iter (fun ((x1, w1, _), (x2, _, _)) -> + Assert.IsTrue(x2 >= x1 + w1, sprintf "段重叠:%d+%d vs %d" x1 w1 x2)) + let (lastX, lastWidth, _) = List.last placed + Assert.IsTrue(lastX + lastWidth <= 1280, "最后一段必须留在 1280 视口内") + + [] + member _.HudSegmentsAndLayoutAreDeterministic () = + Assert.AreEqual(segments, HudLayout.segments world control) + Assert.AreEqual<(int * int * HudLayout.Segment) list>(HudLayout.layout segments, HudLayout.layout segments) + for segment in segments do + Assert.AreEqual(HudLayout.iconRows segment.Icon, HudLayout.iconRows segment.Icon) + + [] + member _.HudBackdropCoversIconAndTextInBothPeriods () = + for mode in [ Day; Night ] do + let palette = HudLayout.palette mode + Assert.IsTrue(palette.SegmentBackdrop.A > 0uy && palette.SegmentBackdrop.A < 255uy, "底色必须半透明") + for (x, width, _) in HudLayout.layout segments do + let rect = HudLayout.segmentBackdrop x width + Assert.IsTrue(rect.X <= x, "底色未覆盖图标左沿") + Assert.IsTrue(rect.X + rect.Width >= HudLayout.textOrigin x, "底色未覆盖文本区") + Assert.IsTrue(rect.Y >= 0 && rect.Y + rect.Height <= HudLayout.barHeight, "底色必须留在窄条内") -- cgit v1.2.3