Flat root layout replaced with a domain-based structure:
- autoload/ the two existing singleton scripts (InteractionManager,
InteractionUI) — grouped by role, matching project.godot's
[autoload] section
- world/ the flying island: terrain.gd, and world/poi/ for the POI
marker + gate scripts/scenes
- player/ everything about the player as a character: player.gd/.tscn,
camera_rig.gd (it only exists to follow the player)
- boot/ created empty for now, will hold the opening/menu screens
main.tscn renamed to world/island.tscn — "main" stops making sense once
the actual run/main_scene becomes a boot screen (next commit). Verified
via grep that main.tscn was referenced nowhere else by path (only by UID
elsewhere, which self-heals).
Every .gd got its .uid sidecar moved alongside it. Two ext_resource
entries had no UID (poi_gate.tscn's own script ref, and island.tscn's
ref to poi_gate.tscn) and needed their path= fixed by hand; everything
else is UID-based and resolved itself after a project reimport.
Also removed two untracked-looking but actually committed editor temp
files (preview_scene.tscn*.tmp, leftovers from the unused hterrain
addon, referenced nowhere).
Verified headless: all 8 affected scenes (island, poi, poi_gate,
player, interaction_ui, and the three debug prototypes that reference
moved files) load with exit code 0. No behavior change, pure move.
65 lines
1.8 KiB
GDScript
Executable File
65 lines
1.8 KiB
GDScript
Executable File
extends CanvasLayer
|
|
|
|
@onready var panel = $Panel
|
|
@onready var title_label = $Panel/TitleLabel
|
|
@onready var message_label = $Panel/MessageLabel
|
|
@onready var option_container = $Panel/OptionContainer
|
|
@onready var hint_label = $Panel/HintLabel
|
|
|
|
var current_options: Array = []
|
|
var selected_index: int = 0
|
|
var mode: String = "menu" # "menu" oder "text"
|
|
|
|
func _ready() -> void:
|
|
panel.visible = false
|
|
|
|
func show_menu(title: String, options: Array) -> void:
|
|
mode = "menu"
|
|
panel.visible = true
|
|
title_label.text = title
|
|
message_label.text = ""
|
|
hint_label.text = "[ESC/B] Beenden"
|
|
current_options = options
|
|
selected_index = 0
|
|
_rebuild_options()
|
|
|
|
func show_text(text: String) -> void:
|
|
mode = "text"
|
|
message_label.text = text
|
|
hint_label.text = "[F/A] Weiter [ESC/B] Beenden"
|
|
_clear_options()
|
|
|
|
func hide_menu() -> void:
|
|
panel.visible = false
|
|
current_options = []
|
|
|
|
func _rebuild_options() -> void:
|
|
_clear_options()
|
|
for i in current_options.size():
|
|
var btn = Button.new()
|
|
btn.text = current_options[i]["label"]
|
|
btn.focus_mode = Control.FOCUS_ALL
|
|
option_container.add_child(btn)
|
|
var action = current_options[i]["action"]
|
|
btn.pressed.connect(_on_option_pressed.bind(action))
|
|
# Ersten Button fokussieren
|
|
if option_container.get_child_count() > 0:
|
|
option_container.get_child(0).grab_focus()
|
|
|
|
func _clear_options() -> void:
|
|
for child in option_container.get_children():
|
|
child.queue_free()
|
|
|
|
func _on_option_pressed(action: String) -> void:
|
|
InteractionManager.handle_selection(action)
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if not panel.visible:
|
|
return
|
|
if Input.is_action_just_pressed("cancel"):
|
|
InteractionManager.close()
|
|
# Im Text-Mode mit F/A weiterklicken
|
|
if mode == "text" and Input.is_action_just_pressed("interact"):
|
|
# Zurück zum Hauptmenü
|
|
InteractionManager.open_poi(InteractionManager.current_poi)
|