feat(ui): wire atlas Layer-1 request/re-poll to generation overlays (#960)

show_body() now requests the body's Layer-1 cascade output via
SimBridge.request_atlas_layers(); the response feeds set_generation_layer1().
The proxy returns Pending on a cache miss and generates in the background
(D-225), so the viewer re-requests every 0.5s (20-retry ceiling) until Ready,
guarding against stale responses by body_id. Serverless/test mode is a no-op
(overlays stay empty). Connected in _ready, torn down in _exit_tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 19:07:59 +02:00
co-authored by Claude Opus 4.7
parent 69ed80c96c
commit 616f7e9f3b
@@ -31,6 +31,11 @@ const MIN_ZOOM: float = 0.5
const MAX_ZOOM: float = 8.0
const ZOOM_STEP: float = 1.15
# #960: Layer-1 proxy re-poll. The proxy returns Pending on a cache miss and
# generates in the background (D-225); the client re-requests until Ready.
const GEN_RETRY_DELAY: float = 0.5
const GEN_MAX_RETRIES: int = 20 # ~10s ceiling before giving up
const PANEL_WIDTH: float = 320.0
const PANEL_MARGIN: float = 16.0
@@ -145,6 +150,8 @@ var _implant_theme = null
var _heightmap_texture: Texture2D = null
var _markers: Dictionary = {}
var _generation_layer1: Variant = null # #960: Layer1Output from the proxy (D-225)
var _gen_pending: bool = false # #960: awaiting a Layer1 response (re-polls on Pending)
var _gen_retries: int = 0
var _grid_w: float = 512.0
var _grid_h: float = 256.0
var _tex_w: float = 1024.0
@@ -208,6 +215,14 @@ func _ready() -> void:
_build_empty_notice()
_build_overlay_bar()
# #960: receive proxied Layer-1 generation output (D-225).
SimBridge.atlas_layers_received.connect(_on_atlas_layers_received)
func _exit_tree() -> void:
if SimBridge.atlas_layers_received.is_connected(_on_atlas_layers_received):
SimBridge.atlas_layers_received.disconnect(_on_atlas_layers_received)
## Called by RegionalScreen.enter() when entering the viewer for a specific body.
func show_body(body: Dictionary, system: Dictionary) -> void:
@@ -221,6 +236,10 @@ func show_body(body: Dictionary, system: Dictionary) -> void:
_refresh_screen_header()
_city_panel.visible = false
_empty_notice.visible = (_heightmap_texture == null)
_generation_layer1 = null
_gen_pending = false
_gen_retries = 0
_request_generation_layers()
grab_focus()
queue_redraw()
_overlay_node.queue_redraw()
@@ -265,6 +284,49 @@ func get_generation_layer1() -> Variant:
return _generation_layer1
## #960: request the body's Layer-1 cascade output from the server proxy.
## No-op in test mode (SimBridge has no server connection) — the overlays
## simply stay empty, which is the correct serverless behavior.
func _request_generation_layers() -> void:
var body_id: String = _dict_str(_body, "body_id", "")
if body_id.is_empty():
return
_gen_pending = true
SimBridge.request_atlas_layers(body_id)
## #960: handle a Layer-1 response. Ignores responses for a stale body (the
## user navigated away). On Pending the proxy is still generating, so we
## re-request after a short delay until Ready or the retry ceiling.
func _on_atlas_layers_received(response: Dictionary) -> void:
var body_id: String = _dict_str(_body, "body_id", "")
if str(response.get("body_id", "")) != body_id:
return
match str(response.get("status", "")):
"Ready":
_gen_pending = false
_gen_retries = 0
set_generation_layer1(response.get("layer1"))
"Pending":
if _gen_retries < GEN_MAX_RETRIES:
_gen_retries += 1
_schedule_gen_retry(body_id)
else:
_gen_pending = false # gave up — overlays stay empty
_:
_gen_pending = false # NotFound / Error — nothing to draw
func _schedule_gen_retry(body_id: String) -> void:
var timer := get_tree().create_timer(GEN_RETRY_DELAY)
timer.timeout.connect(
func() -> void:
# Re-request only if still on the same body and still waiting.
if _gen_pending and _dict_str(_body, "body_id", "") == body_id:
SimBridge.request_atlas_layers(body_id)
)
func get_hovered_city() -> Dictionary:
return _hovered_city