using System.Collections.Generic;
namespace AcDream.App.Rendering.Wb;
///
/// Phase A8 (2026-05-28): EnvCell-scoped visibility snapshot. Direct port of
/// WB's VisibilitySnapshot at
/// references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/VisibilitySnapshot.cs:1-36,
/// narrowed to the fields actually consumes
/// (BatchedByCell + VisibleLandblocks + PostPreparePoolIndex).
/// The scenery-side VisibleGroups / VisibleGfxObjIds /
/// IntersectingLandblocks are dropped — we render scenery through
/// , not through this snapshot.
///
/// Used as an immutable snapshot atomically swapped under the
/// renderer's render lock so PrepareRenderBatches (worker-driven) and
/// Render (render-thread-driven) can't race on a half-populated dict.
///
public sealed class EnvCellVisibilitySnapshot
{
/// Landblocks fully or partially inside the frustum at prepare time.
public List VisibleLandblocks { get; init; } = new();
///
/// Grouped instance data by full 32-bit cell id.
/// Outer key: CellId. Inner key: GfxObjId (ulong; bit 33 set for
/// deduplicated cell geometry per ).
/// Value: list of per-instance transforms (one per cell or per static object
/// inside that cell).
///
public Dictionary>> BatchedByCell { get; init; } = new();
///
/// Pool-index high-water mark after PrepareRenderBatches' merge phase.
/// Mirrors WB VisibilitySnapshot.PostPreparePoolIndex at
/// references/WorldBuilder/.../VisibilitySnapshot.cs:31.
/// Read by to set the pool
/// cursor to a safe region past the snapshot's owned lists, so any
/// GetPooledList calls inside Render don't trample data the
/// snapshot still references. Dropping this field caused the post-Wave-5
/// visual chaos — see
/// docs/research/2026-05-28-a8-env-cell-renderer-audit-findings.md.
///
public int PostPreparePoolIndex { get; init; }
/// True when no visible cells were produced this prepare cycle.
public bool IsEmpty => VisibleLandblocks.Count == 0 && BatchedByCell.Count == 0;
}