Establishes the ImplantApp faux-mobile-OS architecture (D-191):
Foundation:
- ImplantAppManifest (Resource): @export vars for app_path, scene_path, default_key, default_mode, preserves_state
- ImplantNavStack (Node): push/pop/replace/reset_to_default, synchronous screen_changed signal
- ImplantApp (Control base class): absorbs HudGroups boilerplate; on_install/on_open/on_close/on_insert_deactivated lifecycle hooks
- ImplantRegistry (autoload): lazy-scans res://ui/implant/apps/*/app.tres; avoids autoload parse-order trap
Atlas app (replaces atlas_panel + atlas_reach_map + atlas_system_map + atlas_planet_map + root viewer files):
- apps/atlas/app.tres — manifest (implant/map, FULLSCREEN, key=M)
- apps/atlas/atlas_app.gd — coordinator; 4-screen nav via ImplantNavStack
- apps/atlas/screens/{reach,system,planet,regional}_screen.gd — enter/leave interface
- apps/atlas/{atlas_viewer,atlas_marker_overlay,atlas_overlay_bar}.gd — moved from root
Economics app (replaces economics_panel):
- apps/economics/app.tres — manifest (implant/economics, INSERT, key=N)
- apps/economics/economics_app.gd — thin shell delegating to OverviewScreen
- apps/economics/screens/overview_screen.gd — full panel logic, enter/leave interface
Wiring:
- project.godot: add ImplantRegistry autoload after HudGroups
- main.gd: registry-driven key toggle loop; rename atlas_panel→atlas_app, economics_panel→economics_app
- hud.tscn: swap to new scene paths; remove legacy StarMap node
- snapshot_consumers.gd: on_insert_deactivated() uniformly; rename vars
- hud_groups.gd: remove stale starchart compat comment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 lines
1.5 KiB
GDScript
70 lines
1.5 KiB
GDScript
class_name ImplantNavStack
|
|
extends Node
|
|
## Intra-app navigation stack for ImplantApp subclasses (#844, D-191).
|
|
## Mutation is synchronous: screen_changed fires before push/pop/replace returns.
|
|
|
|
signal screen_changed(current_screen_id: String)
|
|
|
|
var _stack: Array[String] = []
|
|
var _payloads: Array[Dictionary] = []
|
|
var _default_screen_id: String = ""
|
|
|
|
|
|
func set_default(screen_id: String) -> void:
|
|
_default_screen_id = screen_id
|
|
|
|
|
|
func push(screen_id: String, payload: Dictionary = {}) -> void:
|
|
_stack.append(screen_id)
|
|
_payloads.append(payload)
|
|
screen_changed.emit(screen_id)
|
|
|
|
|
|
func pop() -> void:
|
|
if _stack.is_empty():
|
|
push_warning("ImplantNavStack: pop() on empty stack")
|
|
return
|
|
_stack.pop_back()
|
|
_payloads.pop_back()
|
|
if not _stack.is_empty():
|
|
screen_changed.emit(_stack.back())
|
|
elif not _default_screen_id.is_empty():
|
|
push(_default_screen_id)
|
|
|
|
|
|
func replace(screen_id: String, payload: Dictionary = {}) -> void:
|
|
if not _stack.is_empty():
|
|
_stack.pop_back()
|
|
_payloads.pop_back()
|
|
_stack.append(screen_id)
|
|
_payloads.append(payload)
|
|
screen_changed.emit(screen_id)
|
|
|
|
|
|
func reset_to_default() -> void:
|
|
_stack.clear()
|
|
_payloads.clear()
|
|
if not _default_screen_id.is_empty():
|
|
push(_default_screen_id)
|
|
|
|
|
|
func is_empty() -> bool:
|
|
return _stack.is_empty()
|
|
|
|
|
|
func push_default() -> void:
|
|
if not _default_screen_id.is_empty():
|
|
push(_default_screen_id)
|
|
|
|
|
|
func current() -> String:
|
|
if _stack.is_empty():
|
|
return ""
|
|
return _stack.back()
|
|
|
|
|
|
func current_payload() -> Dictionary:
|
|
if _payloads.is_empty():
|
|
return {}
|
|
return _payloads.back()
|