class_name MusicListPanel extends PanelContainer ## The list of songs in the playlist, one row per song. A song's row flashes when the ## song starts playing and when it is answered. ## Emitted when the row of song number [param song_no] is clicked. signal song_clicked(song_no: int) var _song_list_object: PackedScene = preload("res://quiz/SongRow.tscn") # Whether each song was playing and answered when the list was last shown, so a row # can flash when its song starts or is answered var _last_state: Dictionary = {} # When each flash ends, in msec, so a flash goes on when the list is shown again var _flash_ends: Dictionary = {} @onready var _rows: VBoxContainer = %MusicList ## Shows the songs in the playlist again, so it shows their latest state. func refresh() -> void: Settings.delete_children(_rows) var songs: Array[SongObject] = Playlist.get_playlist() var state: Dictionary = {} for i: int in songs.size(): var s: SongObject = songs[i] var new_song_list_object: SongRow = _song_list_object.instantiate() new_song_list_object.song_object = s new_song_list_object.index = i new_song_list_object.gui_input.connect(_on_row_input.bind(s.song_number)) _rows.add_child(new_song_list_object) state[s] = [s.is_playing, s.is_answered] # Only songs that were listed before flash, not a whole list loaded at once if _last_state.has(s) && _last_state[s] != state[s] \ && (s.is_playing || s.is_answered): _flash_ends[s] = Time.get_ticks_msec() + int(Anim.SLOW * 1000) var left: float = (_flash_ends.get(s, 0) - Time.get_ticks_msec()) / 1000.0 if left > 0: Anim.flash(new_song_list_object, get_theme_color(&"flash", &"Palette"), left) else: _flash_ends.erase(s) _last_state = state func _on_row_input(event: InputEvent, song_no: int) -> void: if event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT: song_clicked.emit(song_no)