The wrapped tile column (Lendel: -6400 canonicalized to 12739) drew at its canonical column — off-canvas right — leaving the mosaic's left third black. nearest_wrap_image() re-expresses a tile column as the wrap-image closest to held_center for DRAWING only (requests/cache keys stay canonical). The draw-position test asserts overlap FRACTION, not bare intersects() — the buggy placement still clipped ~2px of viewport edge at Lendel scale, so intersects() alone would false-pass. The full-zoom-out reset restored center but not the fit zoom, and its 'already there' guard keyed on a lagging field so it could only ever fire once. The guard now also matches tile mode and compares _view_zoom against the freshly computed fit — restoring the FULL canonical transform (center, offset, fit zoom) and re-firing as a continued gesture keeps zooming out (Jeroen's hard condition, both live shapes). +8 revert-verified tests incl. the continued-gesture reset repro; smoke stub gained get_body_radius_km (crash confirmed real under a real driver before fixing). Suites 286 green; gdlint clean.
932 lines
44 KiB
GDScript
932 lines
44 KiB
GDScript
## T-1142 (Jeroen's second/third hands-on findings): pure-function tests for
|
|
## AtlasWindowViewer's fit-and-center math (fit_window_view) and pole-wall
|
|
## pan clamp (clamp_pan_offset_to_pole_wall) — both extracted specifically so
|
|
## the "viewport + n -> zoom/offset" transform is unit-testable without a
|
|
## live Control tree.
|
|
class_name TestAtlasWindowGeometry
|
|
extends GdUnitTestSuite
|
|
|
|
const AtlasWindowGeometry := preload("res://ui/implant/apps/atlas/atlas_window_geometry.gd")
|
|
const AtlasDescendGeometry := preload("res://ui/implant/apps/atlas/atlas_descend_geometry.gd")
|
|
|
|
const MIN_ZOOM: float = 0.5
|
|
const MAX_ZOOM: float = 8.0
|
|
const CELL_PIXEL_SIZE: float = 16.0
|
|
|
|
|
|
# =============================================================================
|
|
# fit_window_view — the "postage stamp" fix (item 2)
|
|
# =============================================================================
|
|
|
|
|
|
## n=32, cell_px=16 -> native composite is 512x512. T-1145 item 1: COVER
|
|
## fit derives zoom from the LARGER viewport dimension (1920, not 1080) with
|
|
## NO margin factor — zoom = 1920 / 512 = 3.75 — well inside [MIN_ZOOM,
|
|
## MAX_ZOOM], so the clamp is a no-op here.
|
|
func test_fit_window_view_computes_expected_zoom_for_a_wide_viewport() -> void:
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2(1920.0, 1080.0), 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
var expected_zoom: float = 1920.0 / 512.0
|
|
assert_float(fit["zoom"]).is_equal_approx(expected_zoom, 0.001)
|
|
|
|
|
|
## The composite must be CENTERED — offset.x/.y each leave an equal margin on
|
|
## both sides of the (n*cell_px*zoom)-sized composite (a NEGATIVE "margin" is
|
|
## fine and expected under cover — it just means the composite overhangs
|
|
## that axis, checked separately by test_fit_window_view_covers_with_no_gap).
|
|
func test_fit_window_view_centers_the_composite() -> void:
|
|
var viewport := Vector2(1920.0, 1080.0)
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
viewport, 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
var composite_scaled: float = 32.0 * CELL_PIXEL_SIZE * float(fit["zoom"])
|
|
var offset: Vector2 = fit["offset"]
|
|
# The composite's right/bottom edge is offset + composite_scaled — the
|
|
# margin on the far side must equal the margin on the near side (offset).
|
|
var right_margin: float = viewport.x - (offset.x + composite_scaled)
|
|
var bottom_margin: float = viewport.y - (offset.y + composite_scaled)
|
|
assert_float(right_margin).is_equal_approx(offset.x, 0.01)
|
|
assert_float(bottom_margin).is_equal_approx(offset.y, 0.01)
|
|
|
|
|
|
## T-1145 item 1 (Jeroen's round-2 finding, KALLAST window): a wide viewport
|
|
## must show NO side margins — the composite's LONG axis (the one the cover
|
|
## zoom is derived from) must land EXACTLY at the viewport edges (offset ~=
|
|
## 0 on that axis), and the SHORT axis must OVERHANG past both edges
|
|
## (negative margin — the composite is bigger than the viewport there,
|
|
## exactly what "cover" means). This is the literal assertion the coordinator
|
|
## asked for: no side margins at 16:9.
|
|
func test_fit_window_view_covers_with_no_gap_on_the_long_axis() -> void:
|
|
var viewport := Vector2(1920.0, 1080.0)
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
viewport, 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
var composite_scaled: float = 32.0 * CELL_PIXEL_SIZE * float(fit["zoom"])
|
|
var offset: Vector2 = fit["offset"]
|
|
# Long axis (X, 1920 > 1080): the composite must span EXACTLY the
|
|
# viewport width — zero margin on both sides.
|
|
assert_float(offset.x).override_failure_message(
|
|
"the long (cover) axis must have NO side margin — offset.x should be ~0"
|
|
).is_equal_approx(0.0, 0.5)
|
|
var right_margin: float = viewport.x - (offset.x + composite_scaled)
|
|
assert_float(right_margin).override_failure_message(
|
|
"the long (cover) axis's far edge must have NO margin either"
|
|
).is_equal_approx(0.0, 0.5)
|
|
# Short axis (Y, 1080 < 1920): the composite must OVERHANG (negative
|
|
# margin) past BOTH edges — this is the data that extends into pan-space.
|
|
assert_float(offset.y).override_failure_message(
|
|
"the short axis must OVERHANG past the top edge (negative offset)"
|
|
).is_less(0.0)
|
|
|
|
|
|
## A TALL viewport (portrait) must cover the same way, just with the axes
|
|
## swapped — long axis (Y) gets zero margin, short axis (X) overhangs.
|
|
func test_fit_window_view_covers_a_tall_viewport_too() -> void:
|
|
var viewport := Vector2(1080.0, 1920.0)
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
viewport, 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
var offset: Vector2 = fit["offset"]
|
|
assert_float(offset.y).override_failure_message(
|
|
"the long (cover) axis (Y, portrait) must have NO side margin"
|
|
).is_equal_approx(0.0, 0.5)
|
|
assert_float(offset.x).override_failure_message(
|
|
"the short axis (X, portrait) must overhang past the left edge"
|
|
).is_less(0.0)
|
|
|
|
|
|
## A perfectly square viewport needs NO overhang on either axis — cover and
|
|
## contain agree exactly at a 1:1 aspect ratio (the degenerate case where
|
|
## "long" and "short" axis are the same).
|
|
func test_fit_window_view_square_viewport_has_no_overhang_either_axis() -> void:
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2(1024.0, 1024.0), 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
assert_vector(fit["offset"]).is_equal_approx(Vector2.ZERO, Vector2(0.5, 0.5))
|
|
|
|
|
|
## Jeroen's exact bug: an n=32 composite (512px native) in a real ~1920px
|
|
## viewport must NOT render at zoom=1.0 (the old, unfitted "postage stamp"
|
|
## behavior) — the fit must scale it up to fill (now: COVER) the viewport.
|
|
func test_fit_window_view_scales_up_a_small_composite_to_fill_the_viewport() -> void:
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2(1920.0, 1080.0), 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
assert_float(fit["zoom"]).override_failure_message(
|
|
"a 512px composite in a 1920x1080 viewport must be scaled UP, not left at 1.0"
|
|
).is_greater(1.0)
|
|
|
|
|
|
## A huge n (e.g. n=64 at a tiny viewport) must clamp to MIN_ZOOM, never
|
|
## shrink the composite into illegibility below the floor.
|
|
func test_fit_window_view_clamps_to_min_zoom_for_a_tiny_viewport() -> void:
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2(200.0, 150.0), 64, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
assert_float(fit["zoom"]).is_equal_approx(MIN_ZOOM, 0.001)
|
|
|
|
|
|
## A small n (e.g. n=2) at a huge viewport must clamp to MAX_ZOOM, never
|
|
## scale past the ceiling.
|
|
func test_fit_window_view_clamps_to_max_zoom_for_a_tiny_composite() -> void:
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2(3840.0, 2160.0), 2, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
assert_float(fit["zoom"]).is_equal_approx(MAX_ZOOM, 0.001)
|
|
|
|
|
|
## Degenerate inputs (zero viewport, zero n) must not divide by zero — a safe
|
|
## fallback (zoom=1.0, offset=ZERO), never a crash or NaN.
|
|
func test_fit_window_view_degenerate_inputs_are_safe() -> void:
|
|
var fit_zero_viewport: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2.ZERO, 32, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
assert_float(fit_zero_viewport["zoom"]).is_equal_approx(1.0, 0.001)
|
|
var fit_zero_n: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
Vector2(1920.0, 1080.0), 0, CELL_PIXEL_SIZE, MIN_ZOOM, MAX_ZOOM
|
|
)
|
|
assert_float(fit_zero_n["zoom"]).is_equal_approx(1.0, 0.001)
|
|
|
|
|
|
# =============================================================================
|
|
# clamp_pan_offset_to_pole_wall — item 5 (pole hard wall, row axis only)
|
|
# =============================================================================
|
|
|
|
|
|
## Deep inside the valid range (window nowhere near a pole), the clamp must
|
|
## be a no-op — offset passes through unchanged.
|
|
func test_pole_wall_clamp_is_a_noop_far_from_the_poles() -> void:
|
|
var offset := Vector2(10.0, 20.0)
|
|
var clamped: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
offset, Vector2(1920.0, 1080.0), Vector2i(0, 0), 32, 4785, CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_that(clamped).is_equal(offset)
|
|
|
|
|
|
## X is NEVER clamped by the pole wall (item 6: east-west is seamless) — even
|
|
## an absurdly large X offset passes through untouched.
|
|
func test_pole_wall_clamp_never_touches_x() -> void:
|
|
var offset := Vector2(999999.0, 0.0)
|
|
var clamped: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
offset, Vector2(1920.0, 1080.0), Vector2i(0, 0), 32, 4785, CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_float(clamped.x).is_equal_approx(999999.0, 0.001)
|
|
|
|
|
|
## The core pole-wall behavior: dragging FAR past the north pole (offset.y
|
|
## driven to an extreme) must clamp — the resulting offset must be LESS than
|
|
## the extreme requested, and a SECOND, even-more-extreme drag must produce
|
|
## the SAME clamped value (further dragging is inert once pinned at the wall).
|
|
func test_pole_wall_clamp_pins_offset_when_dragged_past_the_pole() -> void:
|
|
var rows_half := 100
|
|
var held_center := Vector2i(0, 90) # near the south pole already (row 90 of 100)
|
|
var extreme_offset := Vector2(0.0, 5000.0) # a huge downward drag
|
|
var clamped: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
extreme_offset, Vector2(800.0, 800.0), held_center, 32, rows_half, CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_float(clamped.y).override_failure_message(
|
|
"an extreme drag toward the pole must be clamped, not pass through"
|
|
).is_less(extreme_offset.y)
|
|
|
|
var even_more_extreme := Vector2(0.0, 50000.0)
|
|
var clamped_again: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
even_more_extreme, Vector2(800.0, 800.0), held_center, 32, rows_half, CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_float(clamped_again.y).override_failure_message(
|
|
"further dragging past an already-pinned wall must be inert (same clamped value)"
|
|
).is_equal_approx(clamped.y, 0.01)
|
|
|
|
|
|
## Symmetric check on the north side: a huge UPWARD drag near the north pole
|
|
## also clamps.
|
|
func test_pole_wall_clamp_pins_offset_on_the_north_side_too() -> void:
|
|
var rows_half := 100
|
|
var held_center := Vector2i(0, -90) # near the north pole
|
|
var extreme_offset := Vector2(0.0, -5000.0) # a huge upward drag
|
|
var clamped: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
extreme_offset, Vector2(800.0, 800.0), held_center, 32, rows_half, CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_float(clamped.y).override_failure_message(
|
|
"an extreme drag toward the north pole must be clamped"
|
|
).is_greater(extreme_offset.y)
|
|
|
|
|
|
## rows_half <= 0 (a no-radius body, or a degenerate district_extent()) means
|
|
## "no wall concept" — the clamp is a no-op, matching
|
|
## canonicalize_district_center()'s own no-radius identity disposition.
|
|
func test_pole_wall_clamp_is_noop_when_rows_half_is_zero() -> void:
|
|
var offset := Vector2(0.0, 999999.0)
|
|
var clamped: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
offset, Vector2(800.0, 800.0), Vector2i(0, 0), 32, 0, CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_that(clamped).is_equal(offset)
|
|
|
|
|
|
## Tiny-body edge case (documented open item in atlas_window_viewer.gd's own
|
|
## _clamp_offset_to_pole_wall doc): a window TALLER than the whole planet's
|
|
## row span (n=64 window, rows_half=10 -> pole-to-pole is only 20 districts)
|
|
## must not crash or produce an inverted/degenerate clamp range — the offset
|
|
## still comes back as a finite Vector2, and repeated extreme drags still
|
|
## converge to a stable pinned value (not NaN, not unbounded).
|
|
func test_pole_wall_clamp_handles_a_window_taller_than_the_planet() -> void:
|
|
var rows_half := 10
|
|
var held_n := 64
|
|
var held_center := Vector2i(0, 0)
|
|
var clamped: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
Vector2(0.0, 999999.0), Vector2(800.0, 800.0), held_center, held_n, rows_half,
|
|
CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_bool(is_finite(clamped.y)).override_failure_message(
|
|
"a window taller than the planet's row span must still produce a finite clamp"
|
|
).is_true()
|
|
var clamped_again: Vector2 = AtlasWindowGeometry.clamp_pan_offset_to_pole_wall(
|
|
Vector2(0.0, 9999999.0), Vector2(800.0, 800.0), held_center, held_n, rows_half,
|
|
CELL_PIXEL_SIZE, 1.0
|
|
)
|
|
assert_float(clamped_again.y).is_equal_approx(clamped.y, 0.01)
|
|
|
|
|
|
# =============================================================================
|
|
# Cross-check: clamp bounds derived from district_extent() (the SAME source
|
|
# canonicalize_district_center() uses) — confirms the two T-1142 fixes (item
|
|
# 5 pole wall, item 6a wrap/clamp) agree on what "the pole" even is.
|
|
# =============================================================================
|
|
|
|
|
|
func test_pole_wall_rows_half_matches_canonicalize_rows_half() -> void:
|
|
var radius_km := 6238.4 # GJ380c
|
|
var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km)
|
|
var rows_half: int = int(extent["rows_half"])
|
|
# A center exactly at (0, rows_half) must canonicalize to itself (already
|
|
# at the pole boundary, not past it) — pins that the SAME rows_half both
|
|
# fixes consume describes an inclusive boundary, not an exclusive one.
|
|
var canonical: Vector2i = AtlasDescendGeometry.canonicalize_district_center(
|
|
Vector2i(0, rows_half), radius_km
|
|
)
|
|
assert_int(canonical.y).is_equal(rows_half)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1153: select_rung() — REDESIGNED (live round 3 finding) per-rung
|
|
# single-window COVERAGE CEILING model, superseding the original
|
|
# `2x`-visual-tolerance-only reading of design doc §5. Select the FINEST
|
|
# rung whose own single-window coverage ceiling (MAX_COVERAGE_M) still
|
|
# covers the current world extent: Quarter <= 32,768 m; District <=
|
|
# 131,072 m; Region otherwise (including tiled coverage beyond its own
|
|
# single-window ceiling, a viewer-level concern — see select_rung()'s own
|
|
# doc for the full derivation and why this REPLACES the earlier two-gate
|
|
# design entirely, not just patches it).
|
|
# =============================================================================
|
|
|
|
|
|
## Deep zoom-in (a tiny extent) selects Quarter — comfortably under its own
|
|
## 32,768 m ceiling.
|
|
func test_select_rung_picks_quarter_well_under_its_ceiling() -> void:
|
|
var rung: String = AtlasWindowGeometry.select_rung(2000.0, 1000.0)
|
|
assert_str(rung).is_equal("Quarter")
|
|
|
|
|
|
## An extent past Quarter's own ceiling but under District's selects
|
|
## District — the finest rung that can still cover it in one window.
|
|
func test_select_rung_picks_district_between_the_two_ceilings() -> void:
|
|
# 60,000 m is past Quarter's 32,768 m ceiling but well under District's
|
|
# 131,072 m one.
|
|
var rung: String = AtlasWindowGeometry.select_rung(60_000.0, 100.0)
|
|
assert_str(rung).is_equal("District")
|
|
|
|
|
|
## An extent past BOTH Quarter's and District's ceilings selects Region —
|
|
## neither finer rung's single window can cover this much world.
|
|
func test_select_rung_picks_region_past_both_finer_ceilings() -> void:
|
|
var rung: String = AtlasWindowGeometry.select_rung(40_075_264.0, 1920.0)
|
|
assert_str(rung).is_equal("Region")
|
|
|
|
|
|
## Exactly AT Quarter's own ceiling (32,768 m) must still select Quarter —
|
|
## the rule is `<=`, not `<`.
|
|
func test_select_rung_quarter_ceiling_boundary_is_inclusive() -> void:
|
|
var rung: String = AtlasWindowGeometry.select_rung(32_768.0, 100.0)
|
|
assert_str(rung).is_equal("Quarter")
|
|
|
|
|
|
## One metre past Quarter's ceiling must flip to District — confirms the
|
|
## ceiling bites right at its own boundary, not one cell short of it.
|
|
func test_select_rung_one_past_quarter_ceiling_is_district() -> void:
|
|
var rung: String = AtlasWindowGeometry.select_rung(32_769.0, 100.0)
|
|
assert_str(rung).is_equal("District")
|
|
|
|
|
|
## Exactly AT District's own ceiling (131,072 m) must still select District.
|
|
func test_select_rung_district_ceiling_boundary_is_inclusive() -> void:
|
|
var rung: String = AtlasWindowGeometry.select_rung(131_072.0, 100.0)
|
|
assert_str(rung).is_equal("District")
|
|
|
|
|
|
## One metre past District's ceiling must flip to Region.
|
|
func test_select_rung_one_past_district_ceiling_is_region() -> void:
|
|
var rung: String = AtlasWindowGeometry.select_rung(131_073.0, 100.0)
|
|
assert_str(rung).is_equal("Region")
|
|
|
|
|
|
## canvas_px is unused by the coverage rule (kept for signature stability,
|
|
## see select_rung()'s own doc) — degenerate/zero values must not change the
|
|
## selected rung at all, unlike the old `2x`-tolerance design's special-cased
|
|
## fallback.
|
|
func test_select_rung_canvas_px_does_not_affect_selection() -> void:
|
|
var with_real_canvas: String = AtlasWindowGeometry.select_rung(2000.0, 1000.0)
|
|
var with_zero_canvas: String = AtlasWindowGeometry.select_rung(2000.0, 0.0)
|
|
assert_str(with_zero_canvas).is_equal(with_real_canvas)
|
|
|
|
|
|
## spacing_for_rung() is select_rung()'s inverse lookup — pin the three known
|
|
## values against the D-243 constants directly (not against RUNG_TABLE
|
|
## indices, which would just restate the implementation).
|
|
func test_spacing_for_rung_matches_d243_constants() -> void:
|
|
assert_float(AtlasWindowGeometry.spacing_for_rung("Quarter")).is_equal_approx(512.0, 0.001)
|
|
assert_float(AtlasWindowGeometry.spacing_for_rung("District")).is_equal_approx(2048.0, 0.001)
|
|
assert_float(AtlasWindowGeometry.spacing_for_rung("Region")).is_equal_approx(204_800.0, 0.001)
|
|
|
|
|
|
## An unknown tag falls back to District — matching the server's own
|
|
## "unknown -> District" posture at every wire-decode boundary.
|
|
func test_spacing_for_rung_unknown_tag_falls_back_to_district() -> void:
|
|
assert_float(AtlasWindowGeometry.spacing_for_rung("Nonsense")).is_equal_approx(2048.0, 0.001)
|
|
|
|
|
|
## MAX_COVERAGE_M's three values, pinned directly against the formulas
|
|
## select_rung()'s own doc derives them from — a regression guard
|
|
## independent of select_rung()'s own boundary tests above, so a future
|
|
## accidental edit to the constants table itself (not just the selection
|
|
## logic) is caught here too.
|
|
func test_max_coverage_m_matches_derived_formulas() -> void:
|
|
assert_float(AtlasWindowGeometry.MAX_COVERAGE_M["Quarter"]).is_equal_approx(32_768.0, 0.001)
|
|
assert_float(AtlasWindowGeometry.MAX_COVERAGE_M["District"]).is_equal_approx(131_072.0, 0.001)
|
|
assert_float(AtlasWindowGeometry.MAX_COVERAGE_M["Region"]).is_equal_approx(13_107_200.0, 0.001)
|
|
|
|
|
|
## The exact scenario that surfaced the original design flaw
|
|
## (live-testing enter_orbital()'s own fit zoom): a whole Earth-like body's
|
|
## circumference (~40,075 km, matching AtlasDescendGeometry.district_extent()'s
|
|
## own cols*DISTRICT_M for radius=6371km) fitted to a 1920px-wide viewport at
|
|
## CELL_PIXEL_SIZE=16 must select Region — the direct regression guard for
|
|
## the bug an early version of select_rung() had (picking District here,
|
|
## which would have meant the canonical orbital frame requests a
|
|
## District-tier derive spanning an entire planet — the exact R1-catastrophe
|
|
## cost scenario the design doc §4 rejects).
|
|
func test_select_rung_at_orbital_fit_zoom_selects_region() -> void:
|
|
var radius_km := 6371.0
|
|
var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km)
|
|
var n: int = int(extent["cols"])
|
|
var composite_native: float = float(n) * CELL_PIXEL_SIZE
|
|
var viewport := Vector2(1920.0, 1080.0)
|
|
var fit_zoom: float = maxf(viewport.x, viewport.y) / composite_native
|
|
var world_extent: float = AtlasWindowGeometry.world_extent_m(CELL_PIXEL_SIZE, fit_zoom, viewport)
|
|
var rung: String = AtlasWindowGeometry.select_rung(
|
|
world_extent, maxf(viewport.x, viewport.y)
|
|
)
|
|
assert_str(rung).override_failure_message(
|
|
"the canonical orbital fit-zoom (whole-planet view) must select Region,"
|
|
+ " never a District-tier derive spanning an entire planet"
|
|
).is_equal("Region")
|
|
|
|
|
|
## **Live round 3 regression, the direct fix target:** at 1600x900 (the
|
|
## coordinator's capture viewport), zooming IN from the orbital fit all the
|
|
## way to Quarter's own ceiling must pass through District along the way —
|
|
## a wheel-zoom gesture crossing world_extent_m from Region's territory down
|
|
## to Quarter's must select District for SOME real span of extent in
|
|
## between, not skip straight from Region to Quarter (the exact "money shot"
|
|
## the coordinator wants capture-worthy: a visible SHARPEN in place, not a
|
|
## jump).
|
|
func test_select_rung_district_is_reachable_between_region_and_quarter() -> void:
|
|
# An extent comfortably between District's and Quarter's ceilings (e.g.
|
|
# the midpoint) must select District — proving the band is non-empty,
|
|
# unlike the old two-gate design where it was empty by construction at
|
|
# every real viewport (see git history / the coordinator's live-round
|
|
# finding for the retired analysis).
|
|
var midpoint: float = (
|
|
(AtlasWindowGeometry.MAX_COVERAGE_M["Quarter"] as float)
|
|
+ (AtlasWindowGeometry.MAX_COVERAGE_M["District"] as float)
|
|
) * 0.5
|
|
var rung: String = AtlasWindowGeometry.select_rung(midpoint, 1600.0)
|
|
assert_str(rung).override_failure_message(
|
|
"District must be reachable between Quarter's and District's own"
|
|
+ " coverage ceilings — the redesigned rule must not skip it"
|
|
).is_equal("District")
|
|
|
|
|
|
# =============================================================================
|
|
# T-1153: world_extent_m() — the `E` half of the §5 rule, computed from the
|
|
# viewer's own zoom/viewport state.
|
|
# =============================================================================
|
|
|
|
|
|
## At zoom=1.0, CELL_PIXEL_SIZE=16: one DISTRICT (2,048 m, the fixed display
|
|
## unit — see world_extent_m()'s own doc for why this is rung-INDEPENDENT)
|
|
## occupies 16 screen px, so a 1920px-wide viewport shows
|
|
## 1920/16 * 2048 = 245,760 m.
|
|
func test_world_extent_m_at_zoom_one() -> void:
|
|
var extent: float = AtlasWindowGeometry.world_extent_m(
|
|
CELL_PIXEL_SIZE, 1.0, Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_float(extent).is_equal_approx(1920.0 / CELL_PIXEL_SIZE * 2048.0, 1.0)
|
|
|
|
|
|
## Doubling the zoom must HALVE the displayed world extent — zooming in
|
|
## shows less world, not more.
|
|
func test_world_extent_m_halves_when_zoom_doubles() -> void:
|
|
var extent_1x: float = AtlasWindowGeometry.world_extent_m(
|
|
CELL_PIXEL_SIZE, 1.0, Vector2(1920.0, 1080.0)
|
|
)
|
|
var extent_2x: float = AtlasWindowGeometry.world_extent_m(
|
|
CELL_PIXEL_SIZE, 2.0, Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_float(extent_2x).is_equal_approx(extent_1x * 0.5, 1.0)
|
|
|
|
|
|
## The composite's on-screen footprint is rung-invariant (world_extent_m()'s
|
|
## own doc) — a change in held rung with NO change in zoom/viewport must
|
|
## leave the displayed world extent UNCHANGED. This is the direct regression
|
|
## test for the bug this function's signature once had (a granularity_v2
|
|
## parameter that silently changed the formula per rung, when only zoom
|
|
## should) — the function no longer TAKES a rung parameter at all, so this
|
|
## pins that omission is intentional, not an oversight.
|
|
func test_world_extent_m_has_no_rung_parameter() -> void:
|
|
var extent_a: float = AtlasWindowGeometry.world_extent_m(
|
|
CELL_PIXEL_SIZE, 1.0, Vector2(1920.0, 1080.0)
|
|
)
|
|
var extent_b: float = AtlasWindowGeometry.world_extent_m(
|
|
CELL_PIXEL_SIZE, 1.0, Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_float(extent_a).is_equal_approx(extent_b, 0.001)
|
|
|
|
|
|
## Degenerate zoom (<=0) must not divide by zero — a safe zero extent.
|
|
func test_world_extent_m_degenerate_zoom_is_safe() -> void:
|
|
var extent: float = AtlasWindowGeometry.world_extent_m(
|
|
CELL_PIXEL_SIZE, 0.0, Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_float(extent).is_equal_approx(0.0, 0.001)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1153: is_fully_zoomed_out() — Jeroen's HARD condition's trigger predicate.
|
|
# =============================================================================
|
|
|
|
|
|
func test_is_fully_zoomed_out_true_when_extent_covers_full_circumference() -> void:
|
|
var radius_km := 6371.0
|
|
var circumference_m: float = TAU * radius_km * 1000.0
|
|
assert_bool(AtlasWindowGeometry.is_fully_zoomed_out(circumference_m, radius_km)).is_true()
|
|
assert_bool(
|
|
AtlasWindowGeometry.is_fully_zoomed_out(circumference_m * 1.5, radius_km)
|
|
).is_true()
|
|
|
|
|
|
func test_is_fully_zoomed_out_false_when_extent_is_less_than_circumference() -> void:
|
|
var radius_km := 6371.0
|
|
var circumference_m: float = TAU * radius_km * 1000.0
|
|
assert_bool(
|
|
AtlasWindowGeometry.is_fully_zoomed_out(circumference_m * 0.5, radius_km)
|
|
).is_false()
|
|
|
|
|
|
## A no-radius body (tiny test body) has no circumference concept — never
|
|
## auto-resets, matching enter_orbital()'s own no-radius fallback disposition.
|
|
func test_is_fully_zoomed_out_false_for_no_radius_body() -> void:
|
|
assert_bool(AtlasWindowGeometry.is_fully_zoomed_out(1e12, 0.0)).is_false()
|
|
|
|
|
|
# =============================================================================
|
|
# T-1153: screen_center_to_district() — the shared screen<->district formula
|
|
# behind both the pan-edge refetch and the rung-reselect refetch.
|
|
# =============================================================================
|
|
|
|
|
|
## At the exact center of a symmetric fit (offset centers the composite,
|
|
## zoom=1.0), the screen center must map back to the held center exactly.
|
|
func test_screen_center_to_district_at_rest_returns_held_center() -> void:
|
|
var held_n := 32
|
|
var held_center := Vector2i(10, 20)
|
|
var composite_native: float = float(held_n) * CELL_PIXEL_SIZE
|
|
var viewport := Vector2(composite_native, composite_native)
|
|
var offset := Vector2.ZERO # composite exactly fills the viewport, top-left at origin
|
|
var result: Vector2i = AtlasWindowGeometry.screen_center_to_district(
|
|
viewport, offset, 1.0, CELL_PIXEL_SIZE, held_center, held_n
|
|
)
|
|
assert_that(result).is_equal(held_center)
|
|
|
|
|
|
## Panning the offset must shift the recovered district position in the
|
|
## OPPOSITE direction of the offset shift (dragging the composite right
|
|
## reveals districts to the WEST at screen-center).
|
|
func test_screen_center_to_district_shifts_with_pan_offset() -> void:
|
|
var held_n := 32
|
|
var held_center := Vector2i(0, 0)
|
|
var composite_native: float = float(held_n) * CELL_PIXEL_SIZE
|
|
var viewport := Vector2(composite_native, composite_native)
|
|
var at_rest: Vector2i = AtlasWindowGeometry.screen_center_to_district(
|
|
viewport, Vector2.ZERO, 1.0, CELL_PIXEL_SIZE, held_center, held_n
|
|
)
|
|
var panned: Vector2i = AtlasWindowGeometry.screen_center_to_district(
|
|
viewport, Vector2(CELL_PIXEL_SIZE * 4.0, 0.0), 1.0, CELL_PIXEL_SIZE, held_center, held_n
|
|
)
|
|
assert_int(panned.x).override_failure_message(
|
|
"dragging the composite EAST (positive offset) must reveal districts to the WEST"
|
|
).is_less(at_rest.x)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1153 (moved from atlas_window_viewer.gd for testability): WASD held-pan
|
|
# direction is exercised live only (reads the global Input singleton) —
|
|
# edge-scroll suppression/direction are pure and covered here directly.
|
|
# =============================================================================
|
|
|
|
|
|
func test_is_cursor_edge_scrolling_true_near_an_edge() -> void:
|
|
var result: bool = AtlasWindowGeometry.is_cursor_edge_scrolling(
|
|
true, false, Vector2(800.0, 600.0), Vector2(10.0, 300.0), 24.0
|
|
)
|
|
assert_bool(result).is_true()
|
|
|
|
|
|
func test_is_cursor_edge_scrolling_false_away_from_any_edge() -> void:
|
|
var result: bool = AtlasWindowGeometry.is_cursor_edge_scrolling(
|
|
true, false, Vector2(800.0, 600.0), Vector2(400.0, 300.0), 24.0
|
|
)
|
|
assert_bool(result).is_false()
|
|
|
|
|
|
func test_is_cursor_edge_scrolling_suppressed_when_over_ui() -> void:
|
|
var result: bool = AtlasWindowGeometry.is_cursor_edge_scrolling(
|
|
true, true, Vector2(800.0, 600.0), Vector2(10.0, 300.0), 24.0
|
|
)
|
|
assert_bool(result).is_false()
|
|
|
|
|
|
func test_is_cursor_edge_scrolling_suppressed_without_app_focus() -> void:
|
|
var result: bool = AtlasWindowGeometry.is_cursor_edge_scrolling(
|
|
false, false, Vector2(800.0, 600.0), Vector2(10.0, 300.0), 24.0
|
|
)
|
|
assert_bool(result).is_false()
|
|
|
|
|
|
func test_edge_scroll_direction_points_west_near_left_edge() -> void:
|
|
var direction: Vector2 = AtlasWindowGeometry.edge_scroll_direction(
|
|
Vector2(800.0, 600.0), Vector2(5.0, 300.0), 24.0
|
|
)
|
|
assert_float(direction.x).is_less(0.0)
|
|
assert_float(direction.y).is_equal_approx(0.0, 0.001)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1153, live round 3 (Jeroen's ruling, design doc §4): compute_tile_grid()
|
|
# — the orbital rest state's multi-window mosaic.
|
|
# =============================================================================
|
|
|
|
|
|
## The exact live-round scenario: GJ380c/Lendel (radius 6238.4 km) needs a
|
|
## 3x2 = 6-tile grid — the coordinator's own estimate, confirmed here as an
|
|
## executable regression.
|
|
func test_compute_tile_grid_lendel_produces_six_tiles() -> void:
|
|
var tiles: Array = AtlasWindowGeometry.compute_tile_grid(6238.4)
|
|
assert_int(tiles.size()).override_failure_message(
|
|
"GJ380c/Lendel must tile into 3x2=6 windows, matching the coordinator's own"
|
|
+ " live-round finding (13,107.2 km single-window coverage vs. 39,198 km"
|
|
+ " circumference)"
|
|
).is_equal(6)
|
|
|
|
|
|
## A tiny body whose whole circumference fits in ONE Region window's
|
|
## coverage ceiling must produce exactly ONE tile — tiling degenerates
|
|
## gracefully to the pre-existing single-window behavior when it isn't
|
|
## actually needed.
|
|
func test_compute_tile_grid_tiny_body_produces_one_tile() -> void:
|
|
# radius small enough that circumference << MAX_COVERAGE_M["Region"]
|
|
# (13,107,200 m) — a few hundred km radius comfortably qualifies.
|
|
var tiles: Array = AtlasWindowGeometry.compute_tile_grid(50.0)
|
|
assert_int(tiles.size()).is_equal(1)
|
|
assert_that(tiles[0]).is_equal(Vector2i.ZERO)
|
|
|
|
|
|
## A no-radius body (tiny test body) must produce exactly one tile at the
|
|
## canonical origin — matching enter_orbital()'s own no-radius fallback
|
|
## disposition (no circumference/tiling concept without a radius).
|
|
func test_compute_tile_grid_no_radius_produces_single_origin_tile() -> void:
|
|
var tiles: Array = AtlasWindowGeometry.compute_tile_grid(0.0)
|
|
assert_int(tiles.size()).is_equal(1)
|
|
assert_that(tiles[0]).is_equal(Vector2i.ZERO)
|
|
|
|
|
|
## Every tile center must be a LEGAL canonicalized DistrictPos — column
|
|
## wrapped into [0, cols), row clamped into [-rows_half, rows_half] — the
|
|
## same range canonicalize_district_center() enforces everywhere else in
|
|
## this cluster (pan refetch, entry, rung-reselect). A raw, uncanonicalized
|
|
## tile center would fail the server's own normalize_window_center() (or
|
|
## silently alias to a different tile than intended).
|
|
func test_compute_tile_grid_tiles_are_all_canonicalized() -> void:
|
|
var radius_km := 6238.4
|
|
var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km)
|
|
var cols: int = int(extent["cols"])
|
|
var rows_half: int = int(extent["rows_half"])
|
|
var tiles: Array = AtlasWindowGeometry.compute_tile_grid(radius_km)
|
|
for tile: Vector2i in tiles:
|
|
assert_int(tile.x).override_failure_message(
|
|
"tile column %d must be wrapped into [0, %d)" % [tile.x, cols]
|
|
).is_greater_equal(0)
|
|
assert_int(tile.x).is_less(cols)
|
|
assert_int(tile.y).override_failure_message(
|
|
"tile row %d must be clamped into [-%d, %d]" % [tile.y, rows_half, rows_half]
|
|
).is_greater_equal(-rows_half)
|
|
assert_int(tile.y).is_less_equal(rows_half)
|
|
|
|
|
|
## No two tiles may share the same canonicalized center — compute_tile_grid()
|
|
## must dedupe (a pole-row clamp or column-wrap collision producing the exact
|
|
## same DistrictPos twice would otherwise request/draw the same tile twice,
|
|
## wasting a request and drawing one tile over another).
|
|
func test_compute_tile_grid_has_no_duplicate_centers() -> void:
|
|
var tiles: Array = AtlasWindowGeometry.compute_tile_grid(6238.4)
|
|
var seen: Dictionary = {}
|
|
for tile: Vector2i in tiles:
|
|
assert_bool(seen.has(tile)).override_failure_message(
|
|
"tile center %s appears more than once in the grid" % str(tile)
|
|
).is_false()
|
|
seen[tile] = true
|
|
|
|
|
|
## The tile grid's own center of mass must land on the canonical origin
|
|
## (0,0) — the tile-set's symmetric layout (each axis' centers computed as
|
|
## `(index - (count-1)/2) * TILE_N`) is centered on the SAME canonical origin
|
|
## enter_orbital() uses, so the tile-set's overall framing agrees with
|
|
## single-window enter_orbital()'s own "center on (0,0)" contract.
|
|
func test_compute_tile_grid_is_centered_on_the_canonical_origin() -> void:
|
|
var tiles: Array = AtlasWindowGeometry.compute_tile_grid(6238.4)
|
|
var sum_col := 0
|
|
var sum_row := 0
|
|
for tile: Vector2i in tiles:
|
|
sum_col += tile.x
|
|
sum_row += tile.y
|
|
# Column centers wrap (periodic), so a raw average isn't meaningful there
|
|
# the way it is for rows — assert row symmetry directly instead (rows
|
|
# never wrap, so their average must be very close to 0 for a
|
|
# symmetric grid).
|
|
var avg_row: float = float(sum_row) / float(tiles.size())
|
|
assert_float(avg_row).override_failure_message(
|
|
"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)
|
|
|
|
|
|
# =============================================================================
|
|
# Live round 5: nearest_wrap_image() — the tile-mosaic WRAP half of "the
|
|
# mosaic doesn't fully draw" (the left-third-black repro).
|
|
# =============================================================================
|
|
|
|
|
|
## Live round 5's OWN repro, pinned exactly: Lendel's wrapped tile
|
|
## canonicalizes to column 12739 (`-6400 mod 19139`) — the CORRECT
|
|
## request/cache key — but its nearest wrap-image relative to the canonical
|
|
## origin (held_center.x = 0) is -6400, the actual visible position
|
|
## immediately west of center.
|
|
func test_nearest_wrap_image_matches_the_lendel_repro() -> void:
|
|
var result: int = AtlasWindowGeometry.nearest_wrap_image(12739, 0, 19139)
|
|
assert_int(result).override_failure_message(
|
|
"the wrapped tile's nearest wrap-image relative to held_center=0 must be"
|
|
+ " -6400 (its actual on-screen position), not 12739 (the correct REQUEST"
|
|
+ " key, but the wrong DRAW position)"
|
|
).is_equal(-6400)
|
|
|
|
|
|
## The two Lendel tiles that were NEVER wrapped (already close to
|
|
## held_center) must round-trip unchanged — the fix must not perturb tiles
|
|
## that were already drawing correctly.
|
|
func test_nearest_wrap_image_is_a_noop_for_already_nearby_columns() -> void:
|
|
var cols := 19139
|
|
for col: int in [0, 6400]:
|
|
var result: int = AtlasWindowGeometry.nearest_wrap_image(col, 0, cols)
|
|
assert_int(result).override_failure_message(
|
|
"column %d is already the nearest wrap-image to held_center=0 — must"
|
|
+ " be returned unchanged" % col
|
|
).is_equal(col)
|
|
|
|
|
|
## The result must always be a LEGAL wrap-image of the canonical column —
|
|
## i.e. `result mod cols == canonical_col mod cols` — regardless of which
|
|
## image is nearest. This is the correctness invariant the whole function
|
|
## exists to preserve: re-expressing a column for DRAWING must never change
|
|
## WHICH district it actually refers to.
|
|
func test_nearest_wrap_image_preserves_the_canonical_identity() -> void:
|
|
var cols := 19139
|
|
for held_col: int in [-50000, -1, 0, 1, 9569, 19138, 50000]:
|
|
var result: int = AtlasWindowGeometry.nearest_wrap_image(12739, held_col, cols)
|
|
assert_int(posmod(result, cols)).override_failure_message(
|
|
"nearest_wrap_image(12739, %d, %d) = %d must still canonicalize back"
|
|
+ " to 12739 — it may only pick a DIFFERENT wrap-image, never a"
|
|
+ " different district" % [held_col, cols, result]
|
|
).is_equal(12739)
|
|
|
|
|
|
## The chosen wrap-image must be the CLOSEST one to held_center — never
|
|
## farther than half the circumference away (otherwise a different
|
|
## wrap-image would have been nearer).
|
|
func test_nearest_wrap_image_is_within_half_circumference_of_held_center() -> void:
|
|
var cols := 19139
|
|
for canonical_col: int in [0, 1, 9569, 12739, 19138]:
|
|
for held_col: int in [-30000, -500, 0, 500, 25000]:
|
|
var result: int = AtlasWindowGeometry.nearest_wrap_image(canonical_col, held_col, cols)
|
|
var distance: int = absi(result - held_col)
|
|
assert_int(distance).override_failure_message(
|
|
(
|
|
"nearest_wrap_image(%d, %d, %d) = %d is %d districts from"
|
|
+ " held_center — must never exceed half the circumference"
|
|
+ " (%d), or a closer wrap-image exists"
|
|
)
|
|
% [canonical_col, held_col, cols, result, distance, cols / 2]
|
|
).is_less_equal(cols / 2)
|
|
|
|
|
|
## `cols <= 0` (no-radius bodies, which never tile per compute_tile_grid()'s
|
|
## own doc) must be a safe no-op passthrough — no periodicity to resolve.
|
|
func test_nearest_wrap_image_zero_cols_is_a_passthrough() -> void:
|
|
var result: int = AtlasWindowGeometry.nearest_wrap_image(12739, 0, 0)
|
|
assert_int(result).is_equal(12739)
|
|
|
|
|
|
## The coordinator's own draw-position counterpart to
|
|
## test_compute_tile_grid_tiles_are_all_canonicalized(): the wrapped tile's
|
|
## DRAW rect (via district_to_canvas_local(), fed through
|
|
## nearest_wrap_image() the way _draw_tile_mosaic() now does) must land
|
|
## SUBSTANTIALLY on-canvas when the view covers the whole body — the exact
|
|
## Lendel shape (whole-body fit at entry, held_center at the canonical
|
|
## origin). A bare `Rect2.intersects()` check is NOT discriminating enough
|
|
## here: at Lendel's own whole-body-fit scale, the BUGGY placement (feeding
|
|
## the canonical column directly) happens to clip the viewport edge by only
|
|
## a couple of px (confirmed by hand-computation — the tile-grid's own
|
|
## edge-to-edge tiling means a full-circumference shift lands almost
|
|
## exactly one screen-width away, so `intersects()` alone would pass on a
|
|
## near-miss that still reads as "the left third is black" visually).
|
|
## Asserting a MEANINGFUL overlap FRACTION (at least half the tile's own
|
|
## area) is what actually distinguishes "correctly drawn" from "barely
|
|
## clipping the edge."
|
|
func test_wrapped_tile_draw_rect_lands_substantially_on_canvas_at_whole_body_view() -> void:
|
|
var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body
|
|
var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km)
|
|
var cols: int = int(extent["cols"])
|
|
var held_center := Vector2i.ZERO
|
|
var held_n: int = cols # enter_orbital()'s own whole-body held_n
|
|
var tile_n: int = AtlasWindowGeometry.TILE_N
|
|
var half_tile: float = float(tile_n) * 0.5
|
|
|
|
# The whole-body fit zoom/viewport (matching enter_orbital()'s own fit).
|
|
var viewport := Vector2(1600.0, 900.0)
|
|
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
|
viewport, held_n, CELL_PIXEL_SIZE, 0.0001, 64.0
|
|
)
|
|
var view_zoom: float = fit["zoom"]
|
|
var view_offset: Vector2 = fit["offset"]
|
|
|
|
# The wrapped tile's own canonical center — mirrors compute_tile_grid()'s
|
|
# own dedup/canonicalize step for Lendel's westmost tile.
|
|
var wrapped_raw_col := -6400
|
|
var canonical_col: int = posmod(wrapped_raw_col, cols)
|
|
|
|
var draw_col: int = AtlasWindowGeometry.nearest_wrap_image(canonical_col, held_center.x, cols)
|
|
var tile_top_left := Vector2(float(draw_col) - half_tile, 0.0 - half_tile)
|
|
var local_origin: Vector2 = AtlasWindowGeometry.district_to_canvas_local(
|
|
tile_top_left, held_center, held_n, CELL_PIXEL_SIZE
|
|
)
|
|
var extent_px: float = float(tile_n) * CELL_PIXEL_SIZE
|
|
|
|
# Canvas-local -> screen space: _canvas.position = view_offset,
|
|
# _canvas.scale = view_zoom (AtlasWindowViewer._apply_transform()'s own
|
|
# transform, mirrored here since this is a pure-geometry test with no
|
|
# live Control/Node2D tree).
|
|
var screen_top_left: Vector2 = view_offset + local_origin * view_zoom
|
|
var screen_extent: Vector2 = Vector2(extent_px, extent_px) * view_zoom
|
|
var tile_rect := Rect2(screen_top_left, screen_extent)
|
|
var viewport_rect := Rect2(Vector2.ZERO, viewport)
|
|
|
|
var overlap: Rect2 = viewport_rect.intersection(tile_rect)
|
|
var tile_area: float = screen_extent.x * screen_extent.y
|
|
var overlap_fraction: float = 0.0
|
|
if tile_area > 0.0:
|
|
overlap_fraction = (overlap.size.x * overlap.size.y) / tile_area
|
|
|
|
assert_float(overlap_fraction).override_failure_message(
|
|
(
|
|
"the wrapped tile's draw rect %s overlaps the viewport %s by only"
|
|
+ " %.1f%% of its own area — must be at least 50%% when the view"
|
|
+ " covers the whole body. This is live round 5's 'left third of the"
|
|
+ " mosaic is black' repro: drawing the CANONICAL column (%d) directly"
|
|
+ " (without nearest_wrap_image()) places this tile off-canvas RIGHT"
|
|
+ " instead of its true position on the LEFT"
|
|
)
|
|
% [tile_rect, viewport_rect, overlap_fraction * 100.0, canonical_col]
|
|
).is_greater_equal(0.5)
|
|
|
|
|
|
## 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)
|