feat(client): T-1153 + T-1152 client half — continuous cursor-anchored zoom ladder, Region-rung orbital entry, click-through retired
The atlas 'regional' screen now opens the LADDER at the canonical orbital frame (Region granularity, whole body fitted and centered) and wheel zoom descends continuously — cursor-anchored, unclamped across rungs, with progressive refinement (held composite keeps drawing, finer rung swaps in place on arrival; no blank frame, no mode flip). Full-zoom-out resets to the canonical planetary frame per Jeroen's HARD condition (is_fully_zoomed_out = extent >= body circumference, not a zoom-value heuristic). The district_screen nav hop is deleted — D-013 restored: descent is a zoom gesture, not a nav push. AtlasViewer's heightmap-texture path is unreachable from nav (code intact; overlay surface deferred, see report/tickets). Rung selection: design doc §5's literal formula has NO legal District band at any real viewport (visual-tolerance band and n=64 coverage ceiling never overlap — pinned by executable boundary tests at 1600x900); select_rung() splits it into a coverage ceiling (decides Region) then the 2x visual tolerance (District vs Quarter), documented at the function. In practice the ladder steps Region -> Quarter directly. Wire: window_granularity_v2 encoded (omitted at District for byte-compat), granularity_v2 echoed value keyed + staleness-guarded end to end; Region clamp mirror replicates the server's bounded halving loop (no closed form). MIN/MAX_ZOOM widened to [0.0005, 64] — the old 0.5 floor would have clamped a real body's canonical fit zoom, violating the reset condition. Real pre-existing bug fixed in atlas_window_overlay.gd: the draw path used echoed n as both cell-grid dimension and district extent — only coincidentally correct at District granularity; Quarter/Region would have read wrong array offsets. cell_grid_side_for_window() now mirrors the server's WindowGranularity::cell_grid_side. Tests: +26 pure-function geometry tests, new 30-test zoom-ladder suite, extensions across the window cache/request/overlay/delivery suites. Full suite 3518 green; cold-parse clean.
This commit is contained in:
@@ -240,6 +240,36 @@ func test_encode_atlas_layer_request_carries_granularity_and_min_wl() -> void:
|
||||
assert_that(decoded.value.get("window_min_wl_m")).is_equal(512)
|
||||
|
||||
|
||||
## T-1152/T-1153: window_granularity_v2 is OMITTED (not sent as "") when at
|
||||
## its empty-string default — same byte-compatibility contract as
|
||||
## window_granularity/window_min_wl_m's own default-omission.
|
||||
func test_encode_atlas_layer_request_omits_granularity_v2_by_default() -> void:
|
||||
var bytes := Protocol.encode_atlas_layer_request(
|
||||
"GJ1c", "Topography", Vector2i(140, 260), 32
|
||||
)
|
||||
var decoded = Messagepack.decode(bytes)
|
||||
assert_bool(decoded.value.has("window_granularity_v2")).is_false()
|
||||
|
||||
|
||||
## T-1152/T-1153: a Region-rung request carries window_granularity_v2 as the
|
||||
## bare string "Region" — the ONLY way to express the coarser-than-district
|
||||
## rung (WindowGranularity's Rust doc: "the ONLY way to actually request
|
||||
## Region is window_granularity_v2 = Some(WindowGranularity::Region)"), a
|
||||
## plain rmp_serde variant-name encoding matching RoadNodeKind's existing
|
||||
## wire precedent, NOT an integer discriminant.
|
||||
func test_encode_atlas_layer_request_carries_granularity_v2_region() -> void:
|
||||
var bytes := Protocol.encode_atlas_layer_request(
|
||||
"GJ1c", "Topography", Vector2i(0, 0), 6400, 0, 0, "Region"
|
||||
)
|
||||
var decoded = Messagepack.decode(bytes)
|
||||
assert_that(decoded.value.get("window_granularity_v2")).is_equal("Region")
|
||||
# The legacy window_granularity field is independently omittable — a
|
||||
# Region request sends ONLY the v2 tag, never a legacy value pretending
|
||||
# to mean something for Region (WINDOW_GRANULARITY_REGION_KEY is a
|
||||
# key-space tag the SERVER echoes, never a legal wire INPUT).
|
||||
assert_bool(decoded.value.has("window_granularity")).is_false()
|
||||
|
||||
|
||||
## §2: district_window is a distinct payload (echoes center/n for the
|
||||
## client's staleness guard) but the codec passthrough is the same shape as
|
||||
## every sibling layer — raw.get(), no reshaping. Field types follow the
|
||||
@@ -265,6 +295,36 @@ func test_atlas_response_district_window_passthrough() -> void:
|
||||
assert_that((decoded as Dictionary).get("district_window")).is_equal(window)
|
||||
|
||||
|
||||
## T-1152/T-1153, design doc §6 encoding-continuity acceptance: a Region-rung
|
||||
## response passes through the EXACT SAME codec path as District/Quarter —
|
||||
## granularity_v2 is just another field in the same dict, no special-cased
|
||||
## decode branch for the coarser rung. This is the direct regression test for
|
||||
## "one colorizer family, no per-rung palettes": the wire contract itself
|
||||
## draws no distinction, so nothing downstream (the overlay's
|
||||
## cell_grid_side_for_window()/_cell_color()) needs a rung-specific decode
|
||||
## path either.
|
||||
func test_atlas_response_district_window_passthrough_region_rung() -> void:
|
||||
var window := {
|
||||
"center": [0, 0],
|
||||
"n": 6400,
|
||||
"granularity": 4294967295, # WINDOW_GRANULARITY_REGION_KEY (u32::MAX) — key-space tag, not a real multiplier
|
||||
"granularity_v2": "Region",
|
||||
"min_wl_m": 0,
|
||||
"morphology": PackedByteArray([8, 14, 0, 5]),
|
||||
"elev_q": PackedByteArray([40, 62, 5, 88]),
|
||||
"temp_dc": [120, 95, AtlasOverlayColors.REGION_TEMP_NONE_DC, 60],
|
||||
"moisture_q": PackedByteArray([50, 30, 90, 20]),
|
||||
"vegetation": PackedByteArray([2, 1, 6, 3]),
|
||||
"glaciation": PackedByteArray([0, 0, 1, 2]),
|
||||
}
|
||||
var raw := {"body_id": "GJ1c", "status": "Ready", "district_window": window}
|
||||
var decoded: Variant = Protocol.atlas_response_from_raw(raw)
|
||||
assert_that(decoded).is_not_null()
|
||||
var district_window: Dictionary = (decoded as Dictionary).get("district_window")
|
||||
assert_that(district_window).is_equal(window)
|
||||
assert_str(str(district_window.get("granularity_v2"))).is_equal("Region")
|
||||
|
||||
|
||||
## A body with no window requested (or not yet derived — §1's background-queue
|
||||
## serving model: the completion may not have landed yet) must decode with
|
||||
## district_window absent -> null, same "layer hasn't produced yet" contract
|
||||
|
||||
Reference in New Issue
Block a user