"Version X is available" in the top bar is now a button that opens an Update popup: - Update and restart gets the download link from the server (the redirect is not followed, as the Gitea link needs no token), downloads the new game next to the running one with a progress bar, checks it (complete, and an MZ or ELF file), swaps it in and restarts. The quiz is saved first and continues. On Windows the running .exe is renamed to .old, put back if the swap fails, and deleted at the next start. - Download in browser opens the .exe, the Linux package, or the release page on other platforms. - From the editor, an unwritable folder or another platform, only the browser download is offered, with the reason. The message now fits between the tabs and the buttons in every theme; in Nord and Christmas it ran into Sync. The macOS export preset is removed, and the unused download_client_* functions are replaced by fetch_client_download_url. Closes #13 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
183 lines
6.6 KiB
GDScript
183 lines
6.6 KiB
GDScript
class_name MainWindow
|
|
extends Control
|
|
## The main window: the top bar, the popups opened from it, and below it the quiz or the
|
|
## statistics, depending on the chosen tab.
|
|
##
|
|
## Everything that is not part of a quiz lives here.
|
|
|
|
## How far a tab slides in from the side when it is chosen.
|
|
const TAB_SLIDE: float = 60.0
|
|
|
|
## Dims the window behind an open popup and keeps clicks from reaching the buttons under it.
|
|
var popup_backdrop: PopupBackdrop
|
|
|
|
@onready var top_bar: TopBar = $TopBar
|
|
@onready var quiz: Quiz = $Quiz
|
|
@onready var search_popup: SearchPopup = $SearchPopup
|
|
@onready var sync_popup: SyncPopup = %SyncPopup
|
|
@onready var shortcuts_popup: ShortcutsPopup = %ShortcutsPopup
|
|
@onready var qr_popup: QRPopup = %QRPopup
|
|
@onready var about_popup: AboutPopup = %AboutPopup
|
|
@onready var log_popup: LogPopup = %LogPopup
|
|
@onready var settings_popup: SettingsPopup = %SettingsPopup
|
|
@onready var update_popup: UpdatePopup = %UpdatePopup
|
|
@onready var statistics_view: StatisticsView = $StatisticsView
|
|
@onready var soundtrack_stats_popup: SoundtrackStatsPopup = $SoundtrackStatsPopup
|
|
|
|
|
|
func _ready() -> void:
|
|
popup_backdrop = PopupBackdrop.add_to(self, _popups())
|
|
# Every button grows a little under the mouse and shrinks when clicked
|
|
ButtonBounce.add_to_every_button(get_tree())
|
|
if OS.has_feature("macos"):
|
|
GameLog.debug("is_mac")
|
|
quiz.search_pressed.connect(show_search)
|
|
top_bar.sync_pressed.connect(sync_soundtracks)
|
|
top_bar.tab_selected.connect(show_tab)
|
|
top_bar.shortcuts_pressed.connect(show_shortcuts)
|
|
top_bar.about_pressed.connect(show_about)
|
|
top_bar.qr_pressed.connect(show_qr)
|
|
top_bar.settings_pressed.connect(settings_popup.open)
|
|
top_bar.update_pressed.connect(update_popup.show_update)
|
|
update_popup.restarting.connect(quiz.save_now)
|
|
settings_popup.server_changed.connect(quiz.on_server_changed)
|
|
settings_popup.characters_changed.connect(quiz.character_select_popup.load_characters)
|
|
settings_popup.clear_cache_requested.connect(clear_cache)
|
|
settings_popup.visibility_changed.connect(_on_settings_popup_visibility_changed)
|
|
|
|
sync_popup.sync_started.connect(_on_sync_started)
|
|
sync_popup.sync_finished.connect(_on_sync_finished)
|
|
quiz.server_changed.connect(search_popup.get_list_of_soundtracks)
|
|
quiz.server_changed.connect(_on_music_source_changed)
|
|
quiz.event_logged.connect(log_popup.add_log_row)
|
|
statistics_view.soundtrack_selected.connect(soundtrack_stats_popup.show_soundtrack)
|
|
soundtrack_stats_popup.covers = statistics_view.covers
|
|
quiz.now_playing.covers = statistics_view.covers
|
|
search_popup.soundtracks_loaded.connect(_remember_cover_times)
|
|
# New alternative names are found by the statistics search and the Search popup
|
|
soundtrack_stats_popup.alternative_names_changed.connect(
|
|
statistics_view.update_alternative_names)
|
|
soundtrack_stats_popup.alternative_names_changed.connect(
|
|
func(_soundtrack: Soundtrack) -> void: search_popup.get_list_of_soundtracks())
|
|
soundtrack_stats_popup.cover_changed.connect(statistics_view.update_cover)
|
|
|
|
# An update leaves the old version next to the game, to delete once the new one runs
|
|
if !OS.has_feature("editor"):
|
|
Updater.remove_old_files(OS.get_executable_path())
|
|
# A saved quiz may have been played from a music folder
|
|
top_bar.update_offline_state()
|
|
search_popup.get_list_of_soundtracks()
|
|
show_about_if_new_version()
|
|
|
|
|
|
## Deletes the cached character pictures and covers. The characters are loaded again at
|
|
## once, so the character select has its pictures; covers come when they are shown.
|
|
func clear_cache() -> void:
|
|
quiz.character_select_popup.character_cache.clear()
|
|
statistics_view.covers.clear()
|
|
quiz.character_select_popup.load_characters()
|
|
|
|
|
|
# The quiz finds a soundtrack's cover by the cover times in the soundtrack list
|
|
func _remember_cover_times(soundtracks: Array[Soundtrack]) -> void:
|
|
var times: Dictionary = {}
|
|
for soundtrack: Soundtrack in soundtracks:
|
|
times[soundtrack.uuid] = soundtrack.cover_modified
|
|
statistics_view.covers.set_cover_times(times)
|
|
|
|
|
|
# After another server or a music folder was picked. Statistics need the server.
|
|
func _on_music_source_changed() -> void:
|
|
top_bar.update_offline_state()
|
|
top_bar.check_for_update()
|
|
if Settings.is_offline() && statistics_view.visible:
|
|
show_tab(&"quiz")
|
|
|
|
|
|
## Opens the About popup, with what is new, the first time this version starts.
|
|
func show_about_if_new_version() -> void:
|
|
if Settings.last_seen_version == Settings.version:
|
|
return
|
|
Settings.last_seen_version = Settings.version
|
|
Settings.save_settings()
|
|
show_about()
|
|
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event is InputEventKey and event.pressed:
|
|
if event.alt_pressed && event.keycode == KEY_ENTER:
|
|
GameLog.debug("Alt + Enter pressed")
|
|
Settings.set_fullscreen(!Settings.fullscreen)
|
|
if event.alt_pressed && event.keycode == KEY_K:
|
|
shortcuts_popup.toggle()
|
|
if event.alt_pressed && event.keycode == KEY_L:
|
|
log_popup.toggle()
|
|
|
|
|
|
func _popups() -> Array[BasePopup]:
|
|
return [search_popup, sync_popup, qr_popup, shortcuts_popup, about_popup, log_popup,
|
|
soundtrack_stats_popup, settings_popup, update_popup]
|
|
|
|
|
|
# How many songs to download ahead can be changed in the settings. Waiting until the
|
|
# settings are closed avoids starting downloads while the number is clicked up and down.
|
|
func _on_settings_popup_visibility_changed() -> void:
|
|
if !settings_popup.visible:
|
|
quiz.song_loader.fill_cache()
|
|
|
|
|
|
func show_search() -> void:
|
|
GameLog.debug("show_search")
|
|
search_popup.toggle()
|
|
|
|
|
|
func show_about() -> void:
|
|
GameLog.debug("show_about")
|
|
about_popup.open()
|
|
|
|
|
|
func show_shortcuts() -> void:
|
|
GameLog.debug("show_shortcuts")
|
|
shortcuts_popup.open()
|
|
|
|
|
|
func show_qr() -> void:
|
|
GameLog.debug("show_qr")
|
|
qr_popup.open()
|
|
|
|
|
|
## Shows the quiz for [code]&"quiz"[/code] or the statistics for [code]&"statistics"[/code].
|
|
## A hidden quiz keeps playing its song.
|
|
func show_tab(tab: StringName) -> void:
|
|
GameLog.debug("show_tab ", tab)
|
|
top_bar.select_tab(tab)
|
|
var was_statistics: bool = statistics_view.visible
|
|
statistics_view.visible = tab == &"statistics"
|
|
quiz.visible = !statistics_view.visible
|
|
# The tab that comes in slides from its side: statistics from the right
|
|
if statistics_view.visible && !was_statistics:
|
|
Anim.slide_in(statistics_view, Vector2(TAB_SLIDE, 0))
|
|
elif quiz.visible && was_statistics:
|
|
Anim.slide_in(quiz, Vector2(-TAB_SLIDE, 0))
|
|
if statistics_view.visible:
|
|
statistics_view.refresh()
|
|
|
|
|
|
func sync_soundtracks() -> void:
|
|
GameLog.debug("sync_soundtracks")
|
|
sync_popup.start_sync()
|
|
|
|
|
|
func _on_sync_started() -> void:
|
|
GameLog.debug("_on_sync_started")
|
|
top_bar.sync_button.disabled = false
|
|
quiz.lock_for_sync()
|
|
|
|
|
|
func _on_sync_finished() -> void:
|
|
GameLog.debug("_on_sync_finished")
|
|
search_popup.get_list_of_soundtracks()
|
|
quiz.on_sync_finished()
|
|
if statistics_view.visible:
|
|
statistics_view.refresh()
|