diff --git a/client/ui/implant/apps/atlas/atlas_viewer.gd b/client/ui/implant/apps/atlas/atlas_viewer.gd index a6a8f5a21..c879945ae 100644 --- a/client/ui/implant/apps/atlas/atlas_viewer.gd +++ b/client/ui/implant/apps/atlas/atlas_viewer.gd @@ -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