class_name Quiz extends Control ## The quiz: the song that is playing, the playlist, the players and their points, and ## the popups opened from here (settings, character select, winner and log). ## ## The main window shows the quiz below its top bar. Pictures and buttons keep the ## positions they had in the main window, so the quiz fills the whole window and lets ## clicks through where it has nothing. ## Emitted when another MusicServer is picked in the settings, after the quiz has ## reloaded from it. signal server_changed ## Emitted with a line for the game log, e.g. when a player gets a point. signal event_logged(text: String) var songs: Array = [] var current_player_row: PlayerRow ## True while statistics are off because a player won, until points are reset. var stats_paused_by_win: bool = false ## Dims the window behind an open popup and keeps clicks from reaching the buttons under it. var popup_backdrop: PopupBackdrop @onready var open_button: Button = $Open @onready var file_dialog: FileDialog = $FileDialog @onready var inspiration_list: InspirationList = $InspirationList @onready var now_playing: NowPlaying = $NowPlaying @onready var players_panel: PlayersPanel = $PlayersPanel @onready var toolbar: QuizToolbar = $QuizToolbar @onready var settings_popup: SettingsPopup = $SettingsPopup @onready var winner_popup: WinnerPopup = %WinnerPopup @onready var song_controls: SongControls = $SongControls @onready var song_loader: SongLoader = $SongLoader @onready var music_list_panel: MusicListPanel = $MusicListPanel @onready var character_select_popup: CharacterSelectPopup = %CharacterSelectPopup @onready var music_player: MusicPlayer = $MusicPlayer @onready var debug_label: Label = $DebugLabel func _ready() -> void: popup_backdrop = PopupBackdrop.add_to(self, _popups()) if OS.has_feature("debug"): GameLog.debug("is_debug") debug_label.visible = true Settings.is_debug = true settings_popup.set_winning_score(5) settings_popup.set_selected_server(4) song_controls.next_pressed.connect(play_next_song) song_controls.show_answer_pressed.connect(show_answer_pressed) toolbar.sound_test_pressed.connect(music_player.get_sound_test_song) toolbar.settings_pressed.connect(show_settings) toolbar.reset_playlist_pressed.connect(reset_playlist) toolbar.reset_points_pressed.connect(reset_points) song_loader.song_list_loaded.connect(update_song_list) song_loader.song_added.connect(_on_song_added) character_select_popup.character_selected.connect(_on_new_character_selected) music_list_panel.song_clicked.connect(song_object_clicked) players_panel.player_added.connect(_on_player_added) players_panel.player_removed.connect(_on_player_removed) players_panel.change_character_requested.connect(_on_change_character_requested) music_player.play_next_song.connect(play_next_song) music_player.update_song_list.connect(update_song_list) settings_popup.server_changed.connect(_on_server_changed) settings_popup.visibility_changed.connect(_on_settings_popup_visibility_changed) open_button.pressed.connect(open) inspiration_list.load_from_server() song_loader.load_song_list() character_select_popup.load_characters() func _input(event: InputEvent) -> void: if event is InputEventKey and event.pressed: if event.alt_pressed && event.keycode == KEY_UP: GameLog.debug("Alt + UP pressed") music_player.change_volume(0.05) if event.alt_pressed && event.keycode == KEY_DOWN: GameLog.debug("Alt + DOWN pressed") music_player.change_volume(-0.05) if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_LEFT: GameLog.debug("Ctrl + Alt + LEFT pressed") music_player.restart() elif event.alt_pressed && event.keycode == KEY_LEFT: GameLog.debug("Alt + LEFT pressed") music_player.seek(-5) if event.alt_pressed && event.keycode == KEY_RIGHT: GameLog.debug("Alt + RIGHT pressed") music_player.seek(5) ## Disables the buttons that use the song list while the server syncs it. func lock_for_sync() -> void: toolbar.set_locked(true) song_controls.set_locked(true) ## Reloads from the server after a sync and starts a new game. func on_sync_finished() -> void: refresh_from_server() toolbar.set_locked(false) song_controls.set_locked(false) reset_points() ## Reloads the soundtracks, playlist and characters from the server. func refresh_from_server() -> void: GameLog.debug("refresh_from_server") inspiration_list.load_from_server() reset_playlist() character_select_popup.load_characters() func _on_server_changed() -> void: GameLog.debug("_on_server_changed") refresh_from_server() reset_points() server_changed.emit() func show_answer_pressed() -> void: GameLog.debug("show_answer_pressed") Playlist.song_is_answered() update_song_list() func play_next_song() -> void: GameLog.debug("play_next_song ", Playlist.latest_played_song) if Playlist.first_song_played: Playlist.set_latest_played_song() Playlist.first_song_played = true music_player.play_song_object(Playlist.latest_played_song) if !(Playlist.get_preloaded_songs() > 0): song_controls.set_next_enabled(false) song_loader.fetch_song_if_idle() func _popups() -> Array[BasePopup]: return [settings_popup, character_select_popup, winner_popup] # The cache size can be changed in the settings. Waiting until the settings are closed # avoids starting downloads while the user is still clicking the number up and down. func _on_settings_popup_visibility_changed() -> void: if !settings_popup.visible: song_loader.fill_cache() func _on_song_added() -> void: song_controls.set_next_enabled(true) if Settings.is_debug: update_song_list() func update_song_list() -> void: GameLog.debug("update_song_list") if Playlist.currently_playing_song >= 0: now_playing.show_song(Playlist.get_current_soundtrack_title(), Playlist.get_current_song_title()) music_list_panel.refresh() func song_object_clicked(song_no: int) -> void: GameLog.debug("Clicked Song Object: ", Playlist.song_object_array[song_no].to_string()) if !Settings.character_select_open: if Playlist.get_song(song_no) == null: GameLog.debug("has no song, need to download") var song_downloaded: Callable = func song_downloaded(body: PackedByteArray) -> void: var sound: AudioStream = AudioStreamMP3.new() sound.data = body Playlist.add_song_to_song_object(song_no, sound) music_player.play_song_object(song_no) MusicServerClient.fetch_song(song_no, song_downloaded) else: GameLog.debug("song already downloaded") music_player.play_song_object(song_no) func reset_playlist() -> void: GameLog.debug("reset_playlist") var playlist_reset_done: Callable = func playlist_reset_done() -> void: Playlist.reset_playlist() song_loader.load_song_list() MusicServerClient.reset_playlist(playlist_reset_done) func reset_points() -> void: GameLog.debug("reset_points") for player_objects: PlayerObject in Settings.player_array: player_objects.reset_points() players_panel.reload() # The song playing now belongs to the game that just ended Playlist.clear_points() Playlist.game_start_song = Playlist.currently_playing_song + 1 music_list_panel.refresh() # A new game starts, so turn statistics back on if winning turned them off if stats_paused_by_win: Settings.add_to_stats = true stats_paused_by_win = false func show_settings() -> void: GameLog.debug("show_settings") settings_popup.open() # Each new player's points reach the music player, the log and the winner popup. func _on_player_added(new_player_object: PlayerObject) -> void: new_player_object.first_point_triggered.connect(music_player._on_point_triggered.bind("first")) new_player_object.match_point_triggered.connect(music_player._on_point_triggered.bind("match")) new_player_object.winner_triggered.connect(_on_player_won.bind(new_player_object)) new_player_object.point_given_sound.connect(_on_make_point_given_sound) new_player_object.player_point_given.connect(_on_point_given.bind(new_player_object)) new_player_object.player_point_taken.connect(_on_point_taken.bind(new_player_object)) func _on_point_given(player_object: PlayerObject) -> void: GameLog.debug("_on_point_given") event_logged.emit(player_object.player_name + " got a point") if Playlist.currently_playing_song >= 0: Playlist.add_point(player_object.id) update_song_list() func _on_make_point_given_sound() -> void: music_player.play_sound_effect(preload("res://sounds/itemopen.wav")) func _on_point_taken(player_object: PlayerObject) -> void: GameLog.debug("_on_point_taken") event_logged.emit(player_object.player_name + " lost a point") music_player.play_sound_effect(preload("res://sounds/itemequip.wav")) if Playlist.currently_playing_song >= 0: Playlist.remove_point(player_object.id) update_song_list() func _on_player_won(player_object: PlayerObject) -> void: GameLog.debug("_on_player_won") winner_popup.show_winner(player_object) music_player.play_song(preload("res://sounds/winning.mp3")) # Songs played after the game is won don't count towards the statistics if Settings.add_to_stats: Settings.add_to_stats = false stats_paused_by_win = true func _on_player_removed(player_object: PlayerObject) -> void: Playlist.remove_player_from_list(player_object.id) update_song_list() func _on_change_character_requested(new_player: PlayerRow, player_name: String) -> void: GameLog.debug("_on_player_change_character_clicked") current_player_row = new_player GameLog.debug("Change character for: " + player_name) character_select_popup.show_grid(player_name) func _on_new_character_selected(character_texture: ImageTexture) -> void: GameLog.debug("_on_new_character_selected") current_player_row.new_character_selected(character_texture) ###Local var local_path: String = '/Users/sebastian/ResilioSync/Sorterat_test/Metal Gear Solid 4 - Guns of the Patriots/2-16 Metal Gear Saga.mp3' func open() -> void: file_dialog.popup() func _on_file_dialog_dir_selected(path: String) -> void: GameLog.debug(path) dir_contents(path) func dir_contents(path: String) -> void: var dir: DirAccess = DirAccess.open(path) if dir: dir.list_dir_begin() var file_name: String = dir.get_next() songs.clear() var soundtracks: Array = [] while file_name != "": if dir.current_is_dir(): #GameLog.debug("Found directory: " + file_name) soundtracks.append(file_name) else: #GameLog.debug("Found file: " + file_name) if file_name.ends_with(".mp3"): songs.append(path + "/" + file_name) file_name = dir.get_next() inspiration_list.show_soundtracks(soundtracks) else: GameLog.warning("An error occurred when trying to access the path.")