Files
settled-reach/client/ui/meta/screens/loading/loading_screen.gd
T
jpmschweitzerandClaude Opus 4.6 f24d08f756 refactor(ui): migrate 6 meta screens to MetaScreen pattern (Workstream 2)
Relocates main_menu, character_creation, settings_dialog, debug_console,
bug_report_dialog, loading_screen from flat client/ui/ into structured
client/ui/meta/screens/<name>/. All six now extend MetaScreen instead
of Control; the base handles open/close lifecycle, visibility,
captures_input, and — for overlays — the sim-pause contract.

Screen policies set per Tyre's proposal:
- settings_dialog: pauses_sim=false, PUSHES onto MetaStack
- debug_console: pauses_sim=true, PUSHES (D-088 routing via base)
- bug_report_dialog: pauses_sim=true, PUSHES
- loading_screen: closable_by_escape=false, PUSHES
- main_menu, character_creation: scene-roots, extend MetaScreen for
  the lifecycle contract only, do NOT push onto the stack

character_creation stays at its current surface (tabs, descriptor,
creation_confirmed signal unchanged). Tab consolidation and
CharacterProfile migration happen in Workstreams 5 and 6.

Knock-on changes:
- main.tscn ModalLayer CanvasLayer renamed to MetaLayer; main.gd
  @onready refs updated; constants.gd comment updated; test_client_p3
  and test_ui_framework_sprint15 assertions updated; test_monologue_display
  and .tscn header comments updated.
- OPEN_MENU handler now pushes settings_dialog onto MetaStack before
  calling open(). Full ESC priority chain lands in Workstream 4.
- atlas_app.gd: _unhandled_key_input signature widened from
  InputEventKey to InputEvent with an is-check, per Godot 4 API. Pre-
  existing narrowing was silently tolerated until main.tscn started
  fully instantiating under the new pattern.
- test_client_p3: entity_renderer type annotations corrected from
  ColorRect to Sprite2D (stale since a prior refactor); facing
  indicator rotation assertion switched to angle_difference() for
  modular-safe comparison.

Verification:
- gdlint client/scripts/ client/ui/ — zero problems
- godot --headless --path client --quit — no SCRIPT ERROR
- test_client_p3: 24/24 pass
- test_ui_framework_sprint15: 54/54 pass
- test_implant_nav_stack: 52/52 pass
- test_implant_registry: 42/42 pass
- test_implant_app_lifecycle: 36/36 pass

Workstream 1 foundation (84105916) remains unchanged. Workstreams 3-8
follow: protocol layer, Option A sequencing, 3-tab restructure,
Bookmark tab, location picker, Skills stub.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 21:58:24 +02:00

87 lines
3.0 KiB
GDScript

extends MetaScreen
## #257: Loading screen overlay — blocks input during save/load round-trip.
## Shown when LOAD_GAME fires; hidden when save_result arrives (success or failure).
## Full-screen, dark overlay with centered status text.
## #724: Shows client version (from project.yaml) and protocol version below the status text.
const BG_COLOR := Color(0.0, 0.0, 0.0, 0.75)
const TEXT_COLOR := Color("#c8d0e0")
const VERSION_COLOR := Color("#667788")
const FONT_SIZE := 18
const VERSION_FONT_SIZE := 11
var _label: Label = null
var _version_label: Label = null
func _ready() -> void:
closable_by_escape = false
visible = false
mouse_filter = Control.MOUSE_FILTER_IGNORE
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
_build_ui()
func _build_ui() -> void:
var bg := ColorRect.new()
bg.color = BG_COLOR
bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(bg)
_label = Label.new()
_label.text = UIStrings.get_text("notifications.loading")
_label.add_theme_font_size_override("font_size", FONT_SIZE)
_label.add_theme_color_override("font_color", TEXT_COLOR)
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_label.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(_label)
# client_ver and proto_ver are independent — project.yaml version is the client release,
# Protocol.PROTOCOL_VERSION is the wire protocol. Mismatches between builds are visible
# only to the observer reading the loading-screen label; a future ticket will surface them.
var client_ver := _read_client_version()
var proto_ver: int = Protocol.PROTOCOL_VERSION
_version_label = Label.new()
_version_label.text = "v%s · protocol %d" % [client_ver, proto_ver]
_version_label.add_theme_font_size_override("font_size", VERSION_FONT_SIZE)
_version_label.add_theme_color_override("font_color", VERSION_COLOR)
_version_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_version_label.anchor_left = 0.0
_version_label.anchor_right = 1.0
_version_label.anchor_top = 1.0
_version_label.anchor_bottom = 1.0
_version_label.offset_top = -32.0
_version_label.offset_bottom = -8.0
_version_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(_version_label)
func _read_client_version() -> String:
var yaml_path := ProjectSettings.globalize_path("res://") + "/../project.yaml"
if not FileAccess.file_exists(yaml_path):
return "?.?.?"
var file := FileAccess.open(yaml_path, FileAccess.READ)
if file == null:
return "?.?.?"
var content := file.get_as_text()
file.close()
for line: String in content.split("\n"):
if line.begins_with("version:"):
var parts := line.split(":", false, 1)
if parts.size() >= 2:
return parts[1].strip_edges()
return "?.?.?"
func show_loading() -> void:
MetaStack.push(self)
open()
## Hide the loading overlay. success=false is reserved for future failure-state UI.
func hide_loading(_success: bool = true) -> void:
close()