using System;
using System.Collections.Generic;
using System.Numerics;
using AcDream.App.Rendering;
using AcDream.App.Rendering.Gpu;
using AcDream.App.Tests.Rendering.Gpu;
using AcDream.App.UI;
using AcDream.App.UI.Layout;
using AcDream.Core.Chat;
using AcDream.Core.Items;
using AcDream.Core.Properties;
using AcDream.Core.Selection;
using AcDream.Runtime.Gameplay;
using AcDream.UI.Abstractions;
using AcDream.UI.Abstractions.Panels.Chat;
namespace AcDream.App.Tests.UI.Layout;
///
/// CT-GF1 fix round (S1): a draw-capture regression sweep mounting each major
/// retained window through its REAL controller (the same production Bind
/// entry points other suites already exercise individually) with a NON-ZERO
/// sprite resolver, drawing through a , and
/// asserting a per-window VERTEX-COUNT FLOOR plus the presence of one KEY
/// sprite id. Every key sprite id is read LIVE off the bound
/// controller/element after Bind — never a hardcoded numeric guess (this
/// project's workflow forbids guessing dat ids) — so the assertion tracks
/// whatever the real import/bind pipeline actually resolved, not an
/// assumption about it.
///
/// This is the class of coverage the CH6a/b BLOCKER 1 bug slipped past: an
/// authored non-zero sprite id sitting right there on the ElementInfo, with
/// nothing actually reaching DrawSprite because the widget was built
/// without its resolve delegate. A structural/geometry test (FindElement,
/// property checks) cannot see that class of regression; only an actual draw
/// pass through a real render context can.
///
///
/// Windows covered: Character (this is ALSO CT-GF1's own motivating
/// case — its chrome draws via
/// , the exact code path
/// the S2/item-1 fix-round caution note calls out as needing re-proof after
/// moving the ambient clip to wrap it), Chat (Imported chrome, real
/// committed fixture), Vendor (Imported chrome, real committed
/// fixture), Options (the 4-tab panel host — no
/// wrapper; mounts as a bare
/// , matching OptionsPanelControllerTests's
/// own established pattern). SKIPPED for lack of a reusable, fixture-driven,
/// SINGLE top-level Bind entry point at the time of writing: Inventory/
/// Paperdoll (composed from several independent controllers, no single
/// window-level Bind), the social panel and the map/house host (their own
/// mount probes are Lane=Manual, live-DAT-only — see
/// SocialPanelLiveMountProbeTests/MapHousePanelSlotProbeTests).
///
///
///
/// Floors are set at roughly 40-45% of this session's OBSERVED vertex count
/// per window (Character 588, Chat 162, Vendor 54, Options 240 — see each
/// Build* method's own trailing comment) — per the fix-round
/// instruction, loose enough to survive legitimate content growth/shrinkage,
/// tight enough to still catch "half (or all) of this window stopped
/// drawing" (a resolve-wiring regression), not exact counts.
///
///
public sealed class UiWindowDrawCaptureSweepTests
{
private sealed class NullGpuFrameSource : ICurrentGpuFrameSource
{
public IGpuFrame? CurrentFrame => null;
}
private static (RecordingGpuDevice device, TextRenderer renderer, UiRenderContext ctx) MakeContext(
float w, float h)
{
var device = new RecordingGpuDevice();
var renderer = new TextRenderer(device, new NullGpuFrameSource(), "unused");
renderer.Begin(new Vector2(w, h));
var ctx = new UiRenderContext(renderer, new Vector2(w, h));
return (device, renderer, ctx);
}
/// Total vertex count across every recorded sprite segment — the
/// same per-segment Verts.Count / 8 convention every other test in
/// this suite uses (8 floats packed per vertex).
private static int TotalVertexCount(TextRenderer renderer)
{
int total = 0;
foreach (var seg in renderer.DebugSpriteSegmentVerts)
total += seg.Verts.Count / 8;
return total;
}
public static IEnumerable