Files
aetherbound-guild/runtime/entry/entry_shell.gd
T

175 lines
6.1 KiB
GDScript

class_name ABGEntryShell
extends Control
const BootService = preload("res://entry/boot_service.gd")
const GUILD_BACKGROUND = preload("res://assets/backgrounds/p9_3_guild_hall.png")
const UI_FONT = preload("res://assets/fonts/NotoSansSC.ttf")
signal boot_completed
@export var auto_start := true
var boot_service := BootService.new()
var boot_snapshot: Dictionary = {}
var boot_generation := 0
var status_label: Label
var detail_label: Label
var progress_bar: ProgressBar
var retry_button: Button
var diagnostics_label: Label
func _ready() -> void:
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
_build_boot_screen()
if auto_start:
call_deferred("start_boot")
func start_boot() -> void:
boot_generation += 1
var generation := boot_generation
boot_snapshot = boot_service.begin()
_render_boot_state()
while generation == boot_generation and String(boot_snapshot.state) == "running":
await get_tree().process_frame
boot_snapshot = boot_service.verify_next()
_render_boot_state()
if generation == boot_generation and String(boot_snapshot.state) == "complete":
await get_tree().create_timer(0.18).timeout
if generation == boot_generation:
boot_completed.emit()
_show_next_step_hold()
func retry_boot() -> void:
if String(boot_snapshot.get("state", "")) != "error":
return
start_boot()
func _build_boot_screen() -> void:
for child in get_children():
child.queue_free()
var background := TextureRect.new()
background.name = "EntryBackground"
background.texture = GUILD_BACKGROUND
background.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
background.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
background.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(background)
var shade := ColorRect.new()
shade.name = "EntryShade"
shade.color = Color(0.035, 0.07, 0.10, 0.40)
shade.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
shade.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(shade)
var safe := MarginContainer.new()
safe.name = "EntrySafeArea"
safe.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
safe.add_theme_constant_override("margin_left", 56)
safe.add_theme_constant_override("margin_right", 56)
safe.add_theme_constant_override("margin_top", 40)
safe.add_theme_constant_override("margin_bottom", 40)
add_child(safe)
var layout := VBoxContainer.new()
layout.name = "BootLayout"
layout.alignment = BoxContainer.ALIGNMENT_END
layout.add_theme_constant_override("separation", 10)
safe.add_child(layout)
var identity := Label.new()
identity.name = "BootIdentity"
identity.text = "AETHERBOUND GUILD"
identity.add_theme_font_override("font", UI_FONT)
identity.add_theme_font_size_override("font_size", 34)
identity.add_theme_color_override("font_color", Color("#f3f6f2"))
identity.add_theme_color_override("font_shadow_color", Color(0.05, 0.08, 0.10, 0.8))
identity.add_theme_constant_override("shadow_offset_x", 2)
identity.add_theme_constant_override("shadow_offset_y", 2)
layout.add_child(identity)
status_label = Label.new()
status_label.name = "BootStatus"
status_label.add_theme_font_override("font", UI_FONT)
status_label.add_theme_font_size_override("font_size", 20)
status_label.add_theme_color_override("font_color", Color("#f3f6f2"))
layout.add_child(status_label)
detail_label = Label.new()
detail_label.name = "BootDetail"
detail_label.add_theme_font_override("font", UI_FONT)
detail_label.add_theme_font_size_override("font_size", 16)
detail_label.add_theme_color_override("font_color", Color("#d7e0dd"))
detail_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
layout.add_child(detail_label)
progress_bar = ProgressBar.new()
progress_bar.name = "BootProgress"
progress_bar.custom_minimum_size = Vector2(420, 12)
progress_bar.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
progress_bar.show_percentage = false
layout.add_child(progress_bar)
retry_button = Button.new()
retry_button.name = "BootRetry"
retry_button.text = "Retry verification"
retry_button.custom_minimum_size = Vector2(240, 52)
retry_button.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
retry_button.add_theme_font_override("font", UI_FONT)
retry_button.add_theme_font_size_override("font_size", 18)
retry_button.pressed.connect(retry_boot)
layout.add_child(retry_button)
diagnostics_label = Label.new()
diagnostics_label.name = "BootDiagnostics"
diagnostics_label.add_theme_font_override("font", UI_FONT)
diagnostics_label.add_theme_font_size_override("font_size", 14)
diagnostics_label.add_theme_color_override("font_color", Color("#ffd4d4"))
layout.add_child(diagnostics_label)
func _render_boot_state() -> void:
if status_label == null:
return
var state := String(boot_snapshot.get("state", "running"))
var step := String(boot_snapshot.get("step", "resources"))
progress_bar.max_value = max(1, int(boot_snapshot.get("total", 1)))
progress_bar.value = int(boot_snapshot.get("completed", 0))
retry_button.visible = state == "error"
diagnostics_label.visible = state == "error"
match state:
"error":
status_label.text = "Verification needs attention"
detail_label.text = "Local data was left unchanged. Resolve the issue, then retry this check."
diagnostics_label.text = "Diagnostic: %s" % String(boot_snapshot.get("code", "UNKNOWN"))
"complete":
status_label.text = "Local verification complete"
detail_label.text = "Resources, settings storage and save access are ready."
diagnostics_label.text = ""
_:
status_label.text = "Preparing the guild threshold"
detail_label.text = _step_text(step)
diagnostics_label.text = ""
func _step_text(step: String) -> String:
match step:
"resources": return "Checking required local resources..."
"storage": return "Checking local storage access..."
"preferences": return "Checking display and accessibility settings..."
"save": return "Checking the latest local run record..."
return "Completing local verification..."
func _show_next_step_hold() -> void:
status_label.text = "First-launch setup"
detail_label.text = "Language, safe area and accessibility setup will open next."
progress_bar.visible = false
retry_button.visible = false
diagnostics_label.visible = false