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 @onready var open_button: Button = $Open @onready var fileDialog: 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_window: Control = $SettingsWindow @onready var winner_window: Control = %WinnerWindow @onready var song_controls: SongControls = $SongControls @onready var song_loader: SongLoader = $SongLoader @onready var music_list_panel: MusicListPanel = $MusicListPanel @onready var new_character_select: Control = %NewCharacterSelect @onready var music_player_container: MusicPlayer = $MusicPlayer @onready var log_window: Control = %Log @onready var debug_label: Label = $DebugLabel var songs: Array= [] var current_player: Node ## 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 func _ready() -> void: popup_backdrop = PopupBackdrop.add_to(self, _popups()) if OS.has_feature("debug"): print("is_debug") debug_label.visible = true Settings.is_debug = true settings_window.set_winning_score(5) settings_window.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_container.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) new_character_select.connect("new_new_character_selected", _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_player_change_character_clicked) music_player_container.connect("play_next_song", play_next_song) music_player_container.connect("update_song_list", update_song_list) settings_window.connect("server_changed", _on_server_changed) settings_window.visibility_changed.connect(_on_settings_window_visibility_changed) open_button.pressed.connect(open) inspiration_list.load_from_server() song_loader.load_song_list() new_character_select.load_characters() func _input(event: InputEvent) -> void: if event is InputEventKey and event.pressed: if event.alt_pressed && event.keycode == KEY_UP: print("Alt + UP pressed") music_player_container.change_volume(0.05) if event.alt_pressed && event.keycode == KEY_DOWN: print("Alt + DOWN pressed") music_player_container.change_volume(-0.05) if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_LEFT: print("Ctrl + Alt + LEFT pressed") music_player_container.restart() elif event.alt_pressed && event.keycode == KEY_LEFT: print("Alt + LEFT pressed") music_player_container.seek(-5) if event.alt_pressed && event.keycode == KEY_RIGHT: print("Alt + RIGHT pressed") music_player_container.seek(5) if event.alt_pressed && event.keycode == KEY_L: log_window.toggle() ## 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: print("refresh_from_server") inspiration_list.load_from_server() reset_playlist() new_character_select.load_characters() func _on_server_changed() -> void: print("_on_server_changed") refresh_from_server() reset_points() server_changed.emit() func show_answer_pressed() -> void: print("show_answer_pressed") Playlist.song_is_answered() update_song_list() func play_next_song() -> void: print("play_next_song ", Playlist.latest_played_song) if Playlist.first_song_played: Playlist.set_latest_played_song() Playlist.first_song_played = true music_player_container.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[PopupWindow]: return [settings_window, new_character_select, winner_window, log_window] # 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_window_visibility_changed() -> void: if !settings_window.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: print("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: print("Clicked Song Object: ", Playlist.song_object_array[song_no].to_string()) if Settings.character_select_open == false: if Playlist.get_song(song_no) == null: print("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_container.play_song_object(song_no) MusicServerClient.fetch_song(song_no, song_downloaded) else: print("song already downloaded") music_player_container.play_song_object(song_no) func reset_playlist() -> void: print("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: print("reset_points") for player_objects: PlayerObject in Settings.player_array: player_objects.reset_points() players_panel.reload() # 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: print("show_settings") settings_window.open() # Each new player's points reach the music player, the log and the winner window. func _on_player_added(new_player_object: PlayerObject) -> void: new_player_object.connect("first_point_triggerd", music_player_container._on_point_triggered.bind("first")) new_player_object.connect("match_point_triggerd", music_player_container._on_point_triggered.bind("match")) new_player_object.connect("winner_triggerd", _on_player_won.bind(new_player_object)) new_player_object.connect("point_given_sound", _on_make_point_given_sound) new_player_object.connect("player_point_given", _on_point_given.bind(new_player_object)) new_player_object.connect("player_point_taken", _on_point_taken.bind(new_player_object)) func _on_point_given(player_object: PlayerObject) -> void: print("_on_point_given") log_window.add_log_row(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_container.play_sound_effect(preload("res://sounds/itemopen.wav")) func _on_point_taken(player_object: PlayerObject) -> void: print("_on_point_taken") log_window.add_log_row(player_object.player_name + " lost a point") music_player_container.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: print("_on_player_won") winner_window.show_winner(player_object) music_player_container.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_player_change_character_clicked(new_player: Player, player_name: String) -> void: print("_on_player_change_character_clicked") current_player = new_player print("Change character for: " + player_name) new_character_select.show_grid(player_name) func _on_new_character_selected(character_texture: ImageTexture) -> void: print("_on_new_character_selected") current_player.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: fileDialog.popup() func _on_file_dialog_dir_selected(path: String) -> void: print(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(): #print("Found directory: " + file_name) soundtracks.append(file_name) else: #print("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: print("An error occurred when trying to access the path.")