fix(client): T-1153/T-1152 round 4 — mosaic canvas-local frame, offset recompute on rung crossing, tile texture RID lifetime; real-driver draw smoke

Three live-found rendering bugs, all invisible to green unit suites:
- _draw_tile_mosaic placed tiles from absolute district (0,0); canvas-
  local (0,0) is held_center - held_n/2 everywhere else, and tile-mode
  held_n is the whole-body extent — the entire mosaic drew tens of
  thousands of px off-canvas. New pure district_to_canvas_local() +
  viewer accessors route every tile through the shared frame.
- _maybe_reselect_rung updated held_n across crossings without
  recomputing _view_offset — the single-window composite landed off-
  canvas the moment any crossing happened (why District/Quarter were
  black too). New pure recompute_offset_for_held_n_change().
- _build_tile_texture created an unstored ImageTexture per _draw,
  racing the RenderingServer's deferred upload — CPU pixels correct,
  screen white. Per-tile-index texture cache, same reference-identity
  discipline as the single-window _cached_texture.

Structural close of the twice-bitten 'nothing asserts pixels' gap:
test_atlas_window_overlay_draw_smoke.gd renders overlay output into a
SubViewport and asserts visible pixels for both modes — runs under a
real driver (invocation documented in DEVOPS.md, visual_capture
precedent; migration to the T-1157 harness noted on that ticket), skips
loud-but-green under the gate's headless run (verified green-with-skips
AND genuinely red with detection forced off). +7 geometry/crossing
tests, all revert-verified. Targeted suites 270 green; gdlint clean.
This commit is contained in:
2026-07-22 14:41:00 +02:00
parent 9ffda88e57
commit 493a7345d3
7 changed files with 732 additions and 92 deletions
+104
View File
@@ -677,3 +677,107 @@ func test_compute_tile_grid_is_centered_on_the_canonical_origin() -> void:
"the tile grid's row centers must average to ~0 (symmetric around the"
+ " canonical origin's equator row)"
).is_equal_approx(0.0, float(AtlasWindowGeometry.TILE_N))
# =============================================================================
# Live round 4: district_to_canvas_local() + recompute_offset_for_held_n_change()
# — the two pure functions behind both round-4 draw-path fixes (tile mosaic
# placement, single-window offset recompute across a rung crossing).
# =============================================================================
## A district AT the held window's own center must land at canvas-local
## `(held_n/2 * cell_px, held_n/2 * cell_px)` — the center of the
## `[0, held_n*cell_px)` square the single-window `Rect2(0,0,extent,extent)`
## draw call already assumes.
func test_district_to_canvas_local_center_district_lands_at_half_extent() -> void:
var held_center := Vector2i(100, 200)
var held_n := 64
var result: Vector2 = AtlasWindowGeometry.district_to_canvas_local(
Vector2(held_center), held_center, held_n, CELL_PIXEL_SIZE
)
var expected: float = float(held_n) * 0.5 * CELL_PIXEL_SIZE
assert_that(result).is_equal(Vector2(expected, expected))
## The window's own top-left corner (held_center - held_n/2) must land at
## canvas-local (0,0) — the exact invariant single-window `_draw()` and
## `fit_window_view()` both assume.
func test_district_to_canvas_local_top_left_corner_lands_at_origin() -> void:
var held_center := Vector2i(0, 0)
var held_n := 32
var top_left := Vector2(held_center) - Vector2.ONE * (float(held_n) * 0.5)
var result: Vector2 = AtlasWindowGeometry.district_to_canvas_local(
top_left, held_center, held_n, CELL_PIXEL_SIZE
)
assert_that(result).is_equal(Vector2.ZERO)
## Live round 4's OWN repro, pinned directly: a tile far from held_center
## (0,0) at whole-body scale (held_n ~19,139, Lendel's raw circumference)
## must NOT land near canvas-local (0,0) — the round-4 bug's exact failure
## mode (treating absolute district (0,0) as the canvas origin regardless of
## held_center/held_n) would place it there instead.
func test_district_to_canvas_local_matches_the_live_round_4_repro_scale() -> void:
var held_center := Vector2i.ZERO
var held_n := 19139 # Lendel's raw district-column count (live round 4's own repro)
var tile_center := Vector2(6400, 0) # one TILE_N east of the body's own center
var result: Vector2 = AtlasWindowGeometry.district_to_canvas_local(
tile_center, held_center, held_n, CELL_PIXEL_SIZE
)
var buggy_result: Vector2 = tile_center * CELL_PIXEL_SIZE # the round-4 bug's own formula
assert_bool(is_equal_approx(result.x, buggy_result.x)).override_failure_message(
"a tile away from held_center must NOT land where the round-4 bug's"
+ " absolute-district-(0,0)-relative formula would put it — got %.1f, the"
+ " buggy formula's own value is %.1f"
% [result.x, buggy_result.x]
).is_false()
## Zero held_n is a degenerate/never-real-in-practice input (a body always
## has SOME district extent) but must not divide-by-zero or crash — `half`
## is simply 0, so the district maps 1:1 to canvas-local (scaled by cell_px).
func test_district_to_canvas_local_zero_held_n_does_not_crash() -> void:
var result: Vector2 = AtlasWindowGeometry.district_to_canvas_local(
Vector2(5, 5), Vector2i.ZERO, 0, CELL_PIXEL_SIZE
)
assert_that(result).is_equal(Vector2(5, 5) * CELL_PIXEL_SIZE)
## The core contract this function exists for: recomputing `_view_offset` so
## a KNOWN screen point continues to map to canvas-local
## `new_held_n/2 * cell_px` (the new window's own center) — i.e. feeding the
## OUTPUT back through district_to_canvas_local()'s own "center district ->
## half-extent local" identity (tested above) and applying the resulting
## transform must reproduce the SAME screen point exactly.
func test_recompute_offset_for_held_n_change_preserves_the_screen_point() -> void:
var screen_point := Vector2(800.0, 450.0)
var view_zoom := 2.5
var new_held_n := 16
var offset: Vector2 = AtlasWindowGeometry.recompute_offset_for_held_n_change(
screen_point, view_zoom, new_held_n, CELL_PIXEL_SIZE
)
var new_local: Vector2 = Vector2.ONE * (float(new_held_n) * 0.5 * CELL_PIXEL_SIZE)
var reconstructed_screen_point: Vector2 = new_local * view_zoom + offset
assert_that(reconstructed_screen_point).is_equal_approx(screen_point, Vector2.ONE * 0.01)
## Live round 4's OWN repro: crossing from Region (~thousands-districts held_n)
## to District (64) or Quarter (16) must produce a DIFFERENT offset than
## leaving `_view_offset` untouched would — pinning that this function's
## OUTPUT actually depends on `new_held_n` (the exact thing the round-4 bug
## got wrong by never calling this function at all).
func test_recompute_offset_for_held_n_change_differs_for_different_held_n() -> void:
var screen_point := Vector2(800.0, 450.0)
var view_zoom := 3.378 # live round 4's own District-band zoom value
var offset_district: Vector2 = AtlasWindowGeometry.recompute_offset_for_held_n_change(
screen_point, view_zoom, 64, CELL_PIXEL_SIZE
)
var offset_quarter: Vector2 = AtlasWindowGeometry.recompute_offset_for_held_n_change(
screen_point, view_zoom, 16, CELL_PIXEL_SIZE
)
assert_that(offset_district).override_failure_message(
"a rung crossing that changes held_n must recompute a DIFFERENT"
+ " _view_offset — reusing the same offset across the crossing is"
+ " exactly the live round 4 bug (composite renders off-canvas)"
).is_not_equal(offset_quarter)
@@ -0,0 +1,344 @@
## Live round 4: a REAL draw smoke test — the "does anything draw at all"
## gap has now bitten twice (round 4's tile-mosaic coordinate bug AND its
## per-tile-texture-lifetime bug, both invisible to test_atlas_window_overlay.gd's
## existing suite, which only asserts on the CACHE FIELDS being populated —
## never on an actual composited pixel). This file closes that gap
## structurally: render AtlasWindowOverlay into a REAL SubViewport, force a
## GPU sync, grab the rendered Image, and assert a meaningful fraction of
## pixels differ from the background color — for BOTH the single-window path
## (a) and the tile-mosaic path (b), matching the coordinator's explicit ask.
##
## **REQUIRES A REAL RENDERING DRIVER — SKIPS (not fails) under
## `tests/run-godot`'s hardcoded `--headless`** (dummy driver, no GPU texture
## output; confirmed directly: SubViewport.get_texture().get_image() returns
## an all-zero/unusable image under it). This matters beyond "the assertions
## are meaningless there": the push gate runs the FULL suite through
## `tests/run-godot --headless` for every push, for everyone — a loud FAILURE
## here would bounce every future push project-wide, not just report a local
## false negative. Every test below carries the gdUnit4 fuzzer-arg skip
## convention (`_do_skip`/`_skip_reason`, matching test_input_gate_live.gd's
## own server-binary-not-built skip) keyed on `_dummy_renderer_active()`, so
## `tests/run-godot --filter test_atlas_window_overlay_draw_smoke` reports
## green-with-skips under headless, not red.
##
## To actually exercise this file's assertions, run it with a real driver:
## godot4 --display-driver x11 --rendering-driver opengl3 \
## -s addons/gdUnit4/bin/GdUnitCmdTool.gd --ignoreHeadlessMode -c \
## -a res://tests/test_atlas_window_overlay_draw_smoke.gd
## (matching tests/visual_capture.gd's own documented "requires a real
## rendering driver" precedent — see docs/DEVOPS.md's own note on this file.)
class_name TestAtlasWindowOverlayDrawSmoke
extends GdUnitTestSuite
const AtlasWindowOverlay := preload("res://ui/implant/apps/atlas/atlas_window_overlay.gd")
const AtlasWindowGeometry := preload("res://ui/implant/apps/atlas/atlas_window_geometry.gd")
const COLOR_BG: Color = Color("#0d1117") # AtlasWindowViewer.COLOR_BG, mirrored (private const)
const VIEWPORT_SIZE: Vector2i = Vector2i(512, 512)
## Minimum fraction of the captured image that must differ from COLOR_BG for
## a draw to count as "genuinely rendered something" — low enough to tolerate
## a mostly-water/mostly-one-color composite (round 4's own repro shots were
## legitimately near-uniform ocean at some zooms), high enough that a
## fully-blank/fully-background/fully-white frame (both round 4 bugs) fails it.
const MIN_NON_BACKGROUND_FRACTION: float = 0.05
const SKIP_REASON: String = (
"no real rendering driver (dummy/headless) — run with e.g."
+ " `godot4 --display-driver x11 --rendering-driver opengl3"
+ " -s addons/gdUnit4/bin/GdUnitCmdTool.gd --ignoreHeadlessMode -c"
+ " -a res://tests/test_atlas_window_overlay_draw_smoke.gd` to exercise this file"
)
## True under Godot's `--display-driver headless` (the dummy renderer
## `tests/run-godot`'s hardcoded `--headless` flag selects) — `DisplayServer.
## get_name()` reports `"headless"` there and the real driver name (`"X11"`,
## `"Wayland"`, etc.) otherwise, confirmed directly against both this
## worktree's `tests/run-godot` invocation and a real `--display-driver x11
## --rendering-driver opengl3` run. Named as a function, not a const, since
## `DisplayServer` singleton state isn't available at script-parse time.
static func _dummy_renderer_active() -> bool:
return DisplayServer.get_name() == "headless"
## Single-window viewer stub — mirrors test_atlas_window_overlay.gd's
## _ViewerStub exactly (is_tile_mode() -> false), so this exercises the
## SAME single-window draw path that suite's cache tests cover, just
## through a REAL render instead of inspecting `_cached_texture` directly.
class _SingleWindowViewerStub:
var window: Variant = null
func get_district_window() -> Variant:
return window
func is_overlay_visible(_overlay_id: String) -> bool:
return false
func get_cell_pixel_size() -> float:
return 16.0
func is_tile_mode() -> bool:
return false
## Tile-mode viewer stub — is_tile_mode() -> true, get_tile_set() returns a
## bare object exposing get_tiles() (AtlasWindowOverlay's own duck-typed
## contract, matching AtlasWindowTileSet.get_tiles()'s public shape exactly:
## Array of {"center": Vector2i, "window": Variant}).
class _TileModeViewerStub:
var tiles: Array = []
var held_center: Vector2i = Vector2i.ZERO
var held_n: int = 0
func get_district_window() -> Variant:
return null
func is_overlay_visible(_overlay_id: String) -> bool:
return false
func get_cell_pixel_size() -> float:
return 16.0
func is_tile_mode() -> bool:
return true
func get_tile_set() -> Variant:
return _TileSetStub.new(tiles)
func get_held_center() -> Vector2i:
return held_center
func get_held_n() -> int:
return held_n
class _TileSetStub:
var _tiles: Array = []
func _init(tiles: Array) -> void:
_tiles = tiles
func get_tiles() -> Array:
return _tiles
## A `Node2D._draw()`-based flat-fill background — deliberately NOT a
## `ColorRect` (a `Control`). A `ColorRect` parented directly under a bare
## `SubViewport` (no intervening `Control` container establishing its own
## layout rect) did not reliably render in this harness: sampled pixels came
## back fully transparent `(0,0,0,0)` regardless of the ColorRect's `color`/
## `size`, even after entering the tree before sizing. `AtlasWindowOverlay`
## itself is a bare `Node2D` using `draw_rect()` for its own background wash
## (`AtlasWindowViewer._draw()`'s own `COLOR_BG` fill) — matching that same,
## already-proven-working `Node2D.draw_rect()` pattern here sidesteps
## whatever `Control`-specific layout/compositing gap caused the ColorRect
## failure, rather than debugging that gap for its own sake.
class _BackgroundRect extends Node2D:
var fill_color: Color = Color.BLACK
var fill_size: Vector2 = Vector2.ZERO
func _draw() -> void:
draw_rect(Rect2(Vector2.ZERO, fill_size), fill_color)
static func _mock_window(center: Vector2i = Vector2i.ZERO, n: int = 64) -> Dictionary:
# A checkerboard-ish morphology spread (not all-one-zone) so the built
# composite has genuine color VARIATION, not just "one flat non-background
# color" — closer to what a real terrain response looks like.
var cells: int = n * n
var morphology := PackedByteArray()
var elev_q := PackedByteArray()
morphology.resize(cells)
elev_q.resize(cells)
for i in range(cells):
morphology[i] = (i % 4) as int # cycles through the 4 morphology zones
elev_q[i] = (i * 7) % 100 as int
return {
"center": [center.x, center.y],
"n": n,
"granularity_v2": "District",
"morphology": morphology,
"elev_q": elev_q,
"temp_dc": [],
"moisture_q": PackedByteArray(),
"vegetation": PackedByteArray(),
"glaciation": PackedByteArray(),
}
## Renders `overlay` (any Node2D with its own `_draw()` — an
## AtlasWindowOverlay for (a)/(b) below, or a bare `_BackgroundRect` probe for
## the harness sanity check) parented under a Node2D positioned/scaled the
## way AtlasWindowViewer._canvas would be, into a fresh SubViewport, and
## returns the captured Image. `zoom` mirrors AtlasWindowViewer._canvas.scale
## (real `fit_window_view()` output is a small fraction, e.g. ~0.006 for a
## whole-body tile mosaic per live round 4's own repro) — WITHOUT it, a
## tile's real-world extent (TILE_N * cell_px = 102,400 local units) is so
## much larger than any realistic test viewport that a mis-POSITIONED tile
## still overlaps the frame purely by being gigantic, making the position
## math this test exists to catch silently unfalsifiable (confirmed
## directly: an earlier version of this test without a zoom scale kept
## passing even with live round 4's tile-coordinate bug deliberately
## reintroduced). Also confirmed directly: a hand-rolled duplicate of this
## same SubViewport/settle-loop setup (the harness sanity check's ORIGINAL
## standalone version) was measurably less reliable under a real driver than
## going through this shared path — reuse over duplication here isn't just
## tidiness, it's the more reliable rendering path.
func _render_to_image(overlay: Node2D, zoom: float = 1.0) -> Image:
var sub_viewport := SubViewport.new()
sub_viewport.size = VIEWPORT_SIZE
sub_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
sub_viewport.transparent_bg = false
add_child(sub_viewport)
auto_free(sub_viewport)
var bg := _BackgroundRect.new()
bg.fill_color = COLOR_BG
bg.fill_size = Vector2(VIEWPORT_SIZE)
sub_viewport.add_child(bg)
bg.queue_redraw()
var canvas := Node2D.new()
canvas.position = Vector2(VIEWPORT_SIZE) * 0.5 # center the composite's local (0,0)
canvas.scale = Vector2(zoom, zoom)
sub_viewport.add_child(canvas)
canvas.add_child(overlay)
overlay.queue_redraw()
# Bounded settle wait, NOT `await RenderingServer.frame_post_draw` — that
# signal never fires under the dummy/headless driver (confirmed directly:
# a first version of this file using it hung for the full 300s
# tests/run-godot wall-clock cap and was force-killed, producing a FALSE
# "0 tests, passed" result — exactly the silent-hang failure mode the
# `_do_skip`/`_dummy_renderer_active()` gate (this file's header doc) now
# avoids structurally instead). A fixed small number of `process_frame`
# awaits settles real rendering — confirmed sufficient against a real
# driver during this fix's own live verification.
for _i in range(6):
await get_tree().process_frame
return sub_viewport.get_texture().get_image()
## Fraction of `image`'s pixels whose RGB differs from COLOR_BG (alpha
## ignored — the ColorRect background is opaque, everything drawn on top of
## it is what's under test).
static func _non_background_fraction(image: Image) -> float:
var w: int = image.get_width()
var h: int = image.get_height()
if w <= 0 or h <= 0:
return 0.0
var total: int = w * h
var differing: int = 0
var bg_rgb: Color = Color(COLOR_BG.r, COLOR_BG.g, COLOR_BG.b, 1.0)
for y in range(h):
for x in range(w):
var px: Color = image.get_pixel(x, y)
var px_rgb: Color = Color(px.r, px.g, px.b, 1.0)
if not px_rgb.is_equal_approx(bg_rgb):
differing += 1
return float(differing) / float(total)
## (a) Single-window path: a District-rung response must render as visibly
## non-background pixels through AtlasWindowOverlay._draw()'s own
## Rect2(0,0,extent,extent) draw call — the "does the OVERLAY actually paint
## something for a real window" half of the gap. Positions it at the
## SubViewport's center via the surrounding Node2D, mirroring _canvas's role
## in the real viewer.
##
## Honest scope note: live round 4's SECOND bug (leaving `_view_offset`
## stale across a rung crossing in `_maybe_reselect_rung()`) lived entirely
## in AtlasWindowViewer's transform bookkeeping, ONE LAYER ABOVE this
## overlay-only test's boundary — it never touched `_draw()` itself, so a
## pure-overlay smoke test structurally cannot reproduce it (there is no
## "stale vs. fresh offset" state to compare inside the overlay alone). That
## regression's coverage is `_maybe_reselect_rung()`'s own unit tests in
## test_atlas_zoom_ladder.gd. This test's job is narrower and still real:
## proving the overlay's draw call itself produces visible output for
## legitimate window data, closing the "the composite Rect2 call is
## silently a no-op" class of bug regardless of which layer caused it.
func test_single_window_draw_produces_visible_pixels(
_do_skip := _dummy_renderer_active(), _skip_reason := SKIP_REASON
) -> void:
var overlay: AtlasWindowOverlay = AtlasWindowOverlay.new()
var stub := _SingleWindowViewerStub.new()
stub.window = _mock_window(Vector2i.ZERO, 32)
overlay.viewer = stub
var image: Image = await _render_to_image(overlay)
var fraction: float = _non_background_fraction(image)
assert_float(fraction).override_failure_message(
(
"single-window composite must render VISIBLE non-background pixels — got"
+ " only %.2f%% of the frame differing from COLOR_BG. This is exactly the"
+ " shape of live round 4's second bug: _view_offset left stale across a"
+ " rung crossing pushed the composite off-canvas, so nothing but"
+ " background/chrome ever appeared, despite the underlying window data"
+ " and draw calls being individually 'correct' in isolation."
)
% (fraction * 100.0)
).is_greater(MIN_NON_BACKGROUND_FRACTION)
## (b) Tile-mosaic path: a tile at a district center AWAY from the body's
## own origin must still render as visibly non-background pixels once
## correctly placed via `district_to_canvas_local()`'s shared held_center/
## held_n convention — this is the path round 4's FIRST and THIRD bugs
## (tile-local-origin math ignoring that convention, and per-tile
## ImageTexture objects with no persistent reference being garbage-
## collected/GPU-desynced before their draw command flushed) would both
## have failed. Uses production-realistic scale (live round 4's own Lendel
## repro: raw circumference ~19,139 districts) — see the tile-center
## comment below for why scale matters here specifically.
func test_tile_mosaic_draw_produces_visible_pixels(
_do_skip := _dummy_renderer_active(), _skip_reason := SKIP_REASON
) -> void:
var overlay: AtlasWindowOverlay = AtlasWindowOverlay.new()
var stub := _TileModeViewerStub.new()
var tile_n: int = AtlasWindowGeometry.TILE_N
var cell_px: float = stub.get_cell_pixel_size()
stub.held_center = Vector2i.ZERO
stub.held_n = 19139
# A SINGLE tile chosen so the CORRECT canvas-local formula
# (`district_to_canvas_local()`, anchored at `held_center - held_n/2`)
# lands it centered in the viewport, while the round-4 BUGGY formula
# (anchored at absolute district (0,0) directly) lands it almost
# `held_n/2 * cell_px` local units away — tens of thousands of units at
# this scale, i.e. genuinely fully off a 512x512 viewport, not just
# "shifted but still overlapping" (confirmed by hand-computation: a
# smaller/toy-scale version of this test stayed green with the bug
# reintroduced, because the shift stayed within the viewport bounds
# either way — this scale/center combination is chosen specifically to
# avoid that false-negative).
var half_tile: float = float(tile_n) * 0.5
var half_body: float = float(stub.held_n) * 0.5
var lone_tile_center := Vector2i(roundi(half_tile - half_body), roundi(half_tile - half_body))
stub.tiles = [
{"center": lone_tile_center, "window": _mock_window(lone_tile_center, 64)},
]
overlay.viewer = stub
# A zoom small enough that the buggy-vs-correct shift (~half_body * cell_px
# local units) is comfortably larger than the viewport — see the center
# choice's own doc above for why this specific magnitude matters.
var zoom: float = float(VIEWPORT_SIZE.x) * 1.5 / (half_body * cell_px)
var image: Image = await _render_to_image(overlay, zoom)
var fraction: float = _non_background_fraction(image)
assert_float(fraction).override_failure_message(
(
"tile mosaic must render VISIBLE non-background pixels across its tiles —"
+ " got only %.2f%% of the frame differing from COLOR_BG. This is exactly"
+ " the shape of live round 4's bugs: (1) tile local-origin computed"
+ " relative to absolute district (0,0) instead of the shared"
+ " held_center/held_n canvas-local convention pushed the whole mosaic"
+ " off-canvas, and (2) even once correctly positioned, an unstored"
+ " per-draw-call ImageTexture rendered as a blank/white gap despite"
+ " provably-correct CPU-side pixel data — both invisible to any test that"
+ " only inspects Dictionary/cache state, never an actual composited pixel."
)
% (fraction * 100.0)
).is_greater(MIN_NON_BACKGROUND_FRACTION)
+52
View File
@@ -449,6 +449,58 @@ func test_zoom_crossing_fires_request_and_accepts_wire_accurate_refinement() ->
assert_str(v._held_granularity_v2).is_equal(request_granularity)
## Live round 4's SECOND bug, pinned directly: `_maybe_reselect_rung()` must
## recompute `_view_offset` (via AtlasWindowGeometry.
## recompute_offset_for_held_n_change()) the instant `_held_n` changes across
## a rung crossing — leaving it untouched (the round-4 bug) means the single-
## window `Rect2(0,0,extent)` draw call renders at whatever screen position
## the OLD (Region-scale) offset happened to put canvas-local (0,0), which
## for a whole-body `held_n` vs. a 64-district District `held_n` is tens or
## hundreds of thousands of px away from the viewport — the exact "pitch
## black" repro. Asserts the NEW held window's own extent actually overlaps
## the viewport after the crossing, the concrete on-screen consequence a
## stale offset breaks.
func test_zoom_crossing_recomputes_view_offset_so_the_new_window_is_on_screen() -> void:
var v: AtlasWindowViewer = auto_free(AtlasWindowViewer.new())
add_child(v)
v.size = Vector2(1600.0, 900.0)
var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body
v.enter_orbital({"body_id": "GJ380c", "body_radius_km": radius_km}, {})
assert_bool(v.is_tile_mode()).is_true()
var cursor_pos := Vector2(1100.0, 300.0)
for _i in range(60):
v._zoom_at(cursor_pos, 1.15)
if not v.is_tile_mode():
break
assert_bool(v.is_tile_mode()).override_failure_message(
"sanity: this test needs to actually cross out of tile mode to exercise"
+ " the held_n change _maybe_reselect_rung() must react to"
).is_false()
# The new (post-crossing) window's screen-space rect, using the SAME
# formula the overlay's single-window _draw() itself uses
# (Rect2(0,0,extent,extent) in canvas-local space, then _canvas's own
# position/scale transform — _view_offset/_view_zoom here mirror that
# exactly, since _apply_transform() is what sets _canvas.position/scale).
var extent_screen: float = float(v._held_n) * v.CELL_PIXEL_SIZE * v._view_zoom
var screen_top_left: Vector2 = v._view_offset
var screen_bottom_right: Vector2 = screen_top_left + Vector2(extent_screen, extent_screen)
var viewport_rect := Rect2(Vector2.ZERO, v.size)
var window_rect := Rect2(screen_top_left, Vector2(extent_screen, extent_screen))
assert_bool(viewport_rect.intersects(window_rect)).override_failure_message(
(
"the new (post-crossing) held window's screen rect %s must overlap the"
+ " viewport %s — a stale _view_offset (never recomputed for the new"
+ " held_n=%d) is exactly live round 4's 'pitch black' bug: the composite"
+ " renders somewhere entirely off-canvas despite request/response/data"
+ " all being individually correct"
)
% [window_rect, viewport_rect, v._held_n]
).is_true()
# =============================================================================
# T-1153: E/W wrap and pole-wall clamps at EVERY rung — both are extent-
# relative (CELL_PIXEL_SIZE-based district-space math, unchanged regardless