130 lines
3.9 KiB
GDScript
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)
|
|
|