Files
cards/scripts/ui/main.gd
team3 f2c609a08b
Some checks are pending
Tests / headless (push) Waiting to run
Tests / fenster-schnell (push) Waiting to run
Tests / fenster-voll (push) Waiting to run
Tests / balance (push) Waiting to run
update
2026-10-13 15:39:55 +02:00

130 lines
3.9 KiB
GDScript

extends Control
## Einstieg: hält den Spielstand und wechselt zwischen den Bildschirmen.
var profile: Profile
var screen: Control
var save_path: String = Profile.SAVE_PATH
var sfx: Sfx
func _ready() -> void:
_map_gamepad()
theme = Style.make_theme()
var bg := Style.Backdrop.new()
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(bg)
sfx = Sfx.new()
add_child(sfx)
profile = Profile.load_or_new(save_path)
apply_settings()
show_screen(MenuScreen.new() if profile.started() else StartDeckScreen.new())
func apply_settings() -> void:
sfx.set_volume(profile.settings.volume)
sfx.set_music_volume(profile.settings.music)
set_language(profile.settings.language)
Style.font_scale = 1.2 if profile.settings.get("big_font", false) else 1.0
Style.animations = bool(profile.settings.get("animations", true))
theme = Style.make_theme()
## Neues Profil: Sammlung und Fortschritt werden verworfen, das Startdeck wird neu gewählt.
func reset_profile() -> void:
profile = Profile.starter()
save()
apply_settings()
show_screen(StartDeckScreen.new())
func set_language(code: String) -> void:
TranslationServer.set_locale(code)
var kept: Array = [] # vorige Bildschirme, zu denen back() zurückführt (Einstellungen aus dem Kampf)
## keep: der aktuelle Bildschirm bleibt erhalten und kommt mit back() zurück.
func show_screen(s: Control, keep: bool = false) -> void:
if screen != null:
if keep:
remove_child(screen)
kept.append(screen)
else:
screen.queue_free()
for k in kept:
k.queue_free()
kept.clear()
screen = s
s.app = self
s.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(s)
if Style.animations:
s.modulate.a = 0.0
create_tween().tween_property(s, "modulate:a", 1.0, 0.15)
if pad_mode:
focus_first_button.call_deferred()
var pad_mode := false # zuletzt Gamepad benutzt: Fokusrahmen sichtbar, Steuerkreuz wechselt Knöpfe
## Gamepad in Menüs: erster Tastendruck setzt den Fokus, Maus nimmt ihn wieder weg.
func _input(event: InputEvent) -> void:
if event is InputEventJoypadButton or (event is InputEventJoypadMotion and absf(event.axis_value) > 0.5):
if not pad_mode:
pad_mode = true
if get_viewport().gui_get_focus_owner() == null:
focus_first_button()
elif event is InputEventMouseMotion and pad_mode:
pad_mode = false
get_viewport().gui_release_focus()
## Gamepad-Tasten für die Menünavigation: A bestätigt, B bricht ab (falls nicht schon zugeordnet).
func _map_gamepad() -> void:
for pair in [["ui_accept", JOY_BUTTON_A], ["ui_cancel", JOY_BUTTON_B]]:
var action: String = pair[0]
if not InputMap.has_action(action):
InputMap.add_action(action)
if not InputMap.action_get_events(action).any(func(e): return e is InputEventJoypadButton):
var ev := InputEventJoypadButton.new()
ev.button_index = pair[1]
ev.device = -1 # jedes Gamepad
InputMap.action_add_event(action, ev)
func focus_first_button() -> void:
if screen == null or screen is BattleScreen:
return
var b := _first_button(screen)
if b != null:
b.grab_focus()
func _first_button(node: Node) -> Button:
for c in node.get_children():
if c is Button and not c.disabled and c.is_visible_in_tree():
return c
var found := _first_button(c)
if found != null:
return found
return null
## Zurück: zum gemerkten Bildschirm, sonst ins Hauptmenü.
func back() -> void:
if kept.is_empty():
show_screen(MenuScreen.new())
return
var prev: Control = kept.pop_back()
screen.queue_free()
screen = prev
add_child(prev)
func save() -> void:
profile.save(save_path)