Short songs (#30): a quiz settings switch and a Seconds per song row (30 by default, 10-120 in steps of 5), saved with the quiz settings. Only part of each quiz song plays, from a random point 10-60% into it, picked once per song so restart and repeat play the same part. The progress bar, time and seeking stay within the part, a hidden beginning counts inside it, and its end counts as the song ending (repeat, stop or go to the next song as set). Random songs (#51): the low-played switch in Settings is now a Normal / Low played / Classic choice, stored as Settings.random_mode and not saved. fetch_random_song(mode) picks /music/rand, /music/rand/low or /music/rand/classic. Closes #30 Closes #51 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
3.2 KiB
GDScript
101 lines
3.2 KiB
GDScript
extends RefCounted
|
|
|
|
class_name SongObject
|
|
|
|
var song_number: int
|
|
var song_title: String
|
|
var soundtrack_title: String
|
|
|
|
## Ids of the players who got a point for this song.
|
|
var players_given_point: Array[String] = []
|
|
|
|
var is_answered: bool = false
|
|
var has_played: bool = false
|
|
var is_playing: bool = false
|
|
## The song's file: a download in [method Playlist.songs_folder], or a song in the music
|
|
## folder. Read the song with [method Playlist.get_song].
|
|
var song_path: String = ""
|
|
## The song itself, only when it could not be saved to a file.
|
|
var song: AudioStream
|
|
## Where the part played with Short songs starts, in seconds, or -1 before it is picked.
|
|
## Picked once, so restarting and repeating play the same part.
|
|
var short_start: float = -1.0
|
|
|
|
|
|
func get_soundtrack_title() -> String:
|
|
if is_answered:
|
|
return soundtrack_title
|
|
else:
|
|
return "????????"
|
|
|
|
|
|
func get_song_title() -> String:
|
|
if is_answered:
|
|
return song_title
|
|
else:
|
|
return "??????"
|
|
|
|
|
|
func get_song_info() -> String:
|
|
if Settings.is_debug:
|
|
return "%d. %s | played: %s | answered: %s" % [(song_number + 1), _full_title(),
|
|
has_played, is_answered]
|
|
elif is_answered:
|
|
return "%d. %s" % [(song_number + 1), _full_title()]
|
|
else:
|
|
return "??? - ???"
|
|
|
|
|
|
# "Soundtrack - Song", or only the song in a prepared quiz, which has no soundtracks
|
|
func _full_title() -> String:
|
|
if soundtrack_title.is_empty():
|
|
return song_title
|
|
return "%s - %s" % [soundtrack_title, song_title]
|
|
|
|
|
|
func add_point(player_id: String) -> void:
|
|
GameLog.debug("add_point")
|
|
if !players_given_point.has(player_id):
|
|
players_given_point.append(player_id)
|
|
|
|
|
|
func remove_point(player_id: String) -> void:
|
|
GameLog.debug("remove_point")
|
|
players_given_point.erase(player_id)
|
|
|
|
|
|
## The song as a Dictionary that can be written as JSON, for [QuizSave]. A song kept only
|
|
## in memory is saved without its file.
|
|
func to_dict() -> Dictionary:
|
|
return {
|
|
"number": song_number, "soundtrack": soundtrack_title, "song": song_title,
|
|
"points": players_given_point.duplicate(), "answered": is_answered,
|
|
"played": has_played, "playing": is_playing, "path": song_path,
|
|
}
|
|
|
|
|
|
## A song made from [param data], as given by [method to_dict], or null when [param data]
|
|
## is not a song.
|
|
static func from_dict(data: Variant) -> SongObject:
|
|
if !(data is Dictionary) || !(data.get("number") is float || data.get("number") is int):
|
|
return null
|
|
var song_object: SongObject = SongObject.new()
|
|
song_object.song_number = int(data.number)
|
|
song_object.soundtrack_title = str(data.get("soundtrack", ""))
|
|
song_object.song_title = str(data.get("song", ""))
|
|
if data.get("points") is Array:
|
|
for player_id: Variant in data.points:
|
|
song_object.add_point(str(player_id))
|
|
song_object.is_answered = bool(data.get("answered", false))
|
|
song_object.has_played = bool(data.get("played", false))
|
|
song_object.is_playing = bool(data.get("playing", false))
|
|
song_object.song_path = str(data.get("path", ""))
|
|
return song_object
|
|
|
|
|
|
func _to_string() -> String:
|
|
var format_string: String = "song_number: %d | soundtrack_title: %s | song_title: %s" \
|
|
+ " | is_answered: %s | has_played: %s | is_playing: %s"
|
|
return format_string % [song_number, soundtrack_title, song_title, is_answered, has_played,
|
|
is_playing]
|