Sort the scripts and scenes into folders

main/ holds the main window and top bar, quiz/ the quiz and its parts,
player/ the music player, popups/ every popup and what they share, data/ the
songs, players, playlist and settings, server/ the MusicServer client,
common/ the list row and GameLog, and themes/ the themes and style boxes.
This commit is contained in:
Sansan committed 2026-10-06 11:57:29 +02:00
1 parent a0428e3475
commit d77b72159d
115 files changed
+94 -84

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
[gd_scene format=3]
[ext_resource type="Script" uid="uid://elgn7gkxgagq" path="res://quiz/inspiration_list.gd" id="2_gxtxm"]
[node name="InspirationList" type="ScrollContainer" unique_id=498283761]
layout_mode = 3
horizontal_scroll_mode = 0
vertical_scroll_mode = 3
offset_right = 641.0
offset_bottom = 384.0
script = ExtResource("2_gxtxm")
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1215162949]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
+24
View File
@@ -0,0 +1,24 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://quiz/music_list_panel.gd" id="part_script"]
[ext_resource type="Script" uid="uid://gf1bk6xbe3j" path="res://quiz/scroll_to_end_container.gd" id="7_dj026"]
[ext_resource type="Theme" uid="uid://rxexo3ur85as" path="res://themes/light_gray_theme.tres" id="7_wxbv6"]
[node name="MusicListPanel" type="PanelContainer" unique_id=2011292375]
layout_mode = 3
theme = ExtResource("7_wxbv6")
offset_right = 1088.0
offset_bottom = 512.0
script = ExtResource("part_script")
[node name="ScrollContainer" type="ScrollContainer" parent="." unique_id=707750459]
layout_mode = 2
follow_focus = true
script = ExtResource("7_dj026")
[node name="MusicList" type="VBoxContainer" parent="ScrollContainer" unique_id=373398568]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 10
+29
View File
@@ -0,0 +1,29 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://quiz/now_playing.gd" id="part_script"]
[sub_resource type="LabelSettings" id="LabelSettings_qspbu"]
font_size = 50
[sub_resource type="LabelSettings" id="LabelSettings_3m52w"]
font_size = 35
[node name="NowPlaying" type="VBoxContainer" unique_id=42468498]
layout_mode = 3
offset_right = 1088.0
offset_bottom = 320.0
script = ExtResource("part_script")
[node name="SoundtrackLabel" type="Label" parent="." unique_id=173147793]
custom_minimum_size = Vector2(1, 1)
layout_mode = 2
label_settings = SubResource("LabelSettings_qspbu")
horizontal_alignment = 1
autowrap_mode = 2
[node name="SongLabel" type="Label" parent="." unique_id=1687490027]
custom_minimum_size = Vector2(1, 1)
layout_mode = 2
label_settings = SubResource("LabelSettings_3m52w")
horizontal_alignment = 1
autowrap_mode = 2
+108
View File
@@ -0,0 +1,108 @@
[gd_scene load_steps=9 format=3 uid="uid://cslogy2csnd7a"]
[ext_resource type="Script" uid="uid://dl6no2wr2c86y" path="res://quiz/player_row.gd" id="1_if4kc"]
[ext_resource type="Texture2D" uid="uid://r4as0nmtoa7p" path="res://noCharacter.png" id="2_hpj3s"]
[ext_resource type="Texture2D" uid="uid://b2kj6m8qpsgb1" path="res://icons/person_remove_light.svg" id="3_j3uxe"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_821k2"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_w10e8"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_78a8g"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_i56hb"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_b2crt"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[node name="PlayerRow" type="Control"]
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 3
anchors_preset = 0
offset_bottom = 40.0
size_flags_horizontal = 3
script = ExtResource("1_if4kc")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Panel4" type="Panel" parent="HBoxContainer"]
custom_minimum_size = Vector2(5, 40)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_821k2")
[node name="Name" type="Label" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(130, 40)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
text = ": 0"
vertical_alignment = 1
clip_text = true
text_overrun_behavior = 3
[node name="Panel3" type="Panel" parent="HBoxContainer"]
custom_minimum_size = Vector2(16, 2.08165e-12)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_w10e8")
[node name="Character" type="TextureButton" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(80, 40)
layout_mode = 2
focus_mode = 0
action_mode = 0
texture_normal = ExtResource("2_hpj3s")
ignore_texture_size = true
stretch_mode = 5
[node name="Panel2" type="Panel" parent="HBoxContainer"]
custom_minimum_size = Vector2(30, 40)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_78a8g")
[node name="AddPoint" type="Button" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
focus_mode = 0
action_mode = 0
text = "+1"
[node name="Panel5" type="Panel" parent="HBoxContainer"]
custom_minimum_size = Vector2(3, 40)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_i56hb")
[node name="RemovePoint" type="Button" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
focus_mode = 0
action_mode = 0
text = "-1"
[node name="Panel" type="Panel" parent="HBoxContainer"]
custom_minimum_size = Vector2(30, 40)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_b2crt")
[node name="RemovePlayer" type="TextureButton" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
focus_mode = 0
action_mode = 0
texture_normal = ExtResource("3_j3uxe")
stretch_mode = 0
+94
View File
@@ -0,0 +1,94 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://quiz/players_panel.gd" id="part_script"]
[ext_resource type="Texture2D" uid="uid://bcfmpd7h512ef" path="res://icons/person_add_light.svg" id="5_31tjv"]
[ext_resource type="Script" uid="uid://cgakje8gb37tf" path="res://quiz/player_name_field.gd" id="7_qsdfy"]
[sub_resource type="InputEventKey" id="InputEventKey_03bm3"]
device = -1
alt_pressed = true
keycode = 65
unicode = 63743
[sub_resource type="Shortcut" id="Shortcut_jafqj"]
events = [SubResource("InputEventKey_03bm3")]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qk7sj"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_k1ygi"]
bg_color = Color(0.180392, 0.180392, 0.180392, 1)
[node name="PlayersPanel" type="PanelContainer" unique_id=1708375945]
layout_mode = 3
offset_right = 641.0
offset_bottom = 401.0
script = ExtResource("part_script")
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=270084211]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=513047023]
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer" unique_id=1331357386]
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
text = "Players"
horizontal_alignment = 1
vertical_alignment = 1
[node name="AddPlayersButton" type="TextureButton" parent="VBoxContainer/HBoxContainer" unique_id=634410148]
unique_name_in_owner = true
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
size_flags_horizontal = 8
focus_mode = 0
action_mode = 0
shortcut = SubResource("Shortcut_jafqj")
texture_normal = ExtResource("5_31tjv")
[node name="AddPlayerContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=1371948739]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
[node name="Panel" type="Panel" parent="VBoxContainer/AddPlayerContainer" unique_id=1569854056]
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_qk7sj")
[node name="PlayerNameField" type="TextEdit" parent="VBoxContainer/AddPlayerContainer" unique_id=332535327]
unique_name_in_owner = true
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Player name"
script = ExtResource("7_qsdfy")
[node name="AddPlayerButton" type="Button" parent="VBoxContainer/AddPlayerContainer" unique_id=245001313]
unique_name_in_owner = true
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
text = "Add"
[node name="Panel2" type="Panel" parent="VBoxContainer/AddPlayerContainer" unique_id=60215448]
custom_minimum_size = Vector2(2.08165e-12, 40)
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_k1ygi")
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer" unique_id=1000000001]
layout_mode = 2
size_flags_vertical = 15
horizontal_scroll_mode = 0
[node name="PlayersListVBoxContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer" unique_id=1000000002]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 15
+135
View File
@@ -0,0 +1,135 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://quiz/quiz.gd" id="quiz_script"]
[ext_resource type="PackedScene" uid="uid://ds15cgsf8vpvc" path="res://player/MusicPlayer.tscn" id="5_emn36"]
[ext_resource type="PackedScene" uid="uid://cdy4kvemwaiom" path="res://popups/CharacterSelectPopup.tscn" id="6_dhrvg"]
[ext_resource type="PackedScene" uid="uid://dldpeo5y3l5hq" path="res://popups/SettingsPopup.tscn" id="11_k62u5"]
[ext_resource type="PackedScene" uid="uid://cxlsmxnrp0agh" path="res://popups/WinnerPopup.tscn" id="17_winner_window"]
[ext_resource type="PackedScene" path="res://quiz/MusicListPanel.tscn" id="scene_MusicListPanel"]
[ext_resource type="PackedScene" path="res://quiz/PlayersPanel.tscn" id="scene_PlayersPanel"]
[ext_resource type="PackedScene" path="res://quiz/InspirationList.tscn" id="scene_InspirationList"]
[ext_resource type="PackedScene" path="res://quiz/QuizToolbar.tscn" id="scene_QuizToolbar"]
[ext_resource type="PackedScene" path="res://quiz/SongControls.tscn" id="scene_SongControls"]
[ext_resource type="PackedScene" path="res://quiz/NowPlaying.tscn" id="scene_NowPlaying"]
[ext_resource type="Script" path="res://quiz/song_loader.gd" id="song_loader_script"]
[node name="Quiz" type="Control" unique_id=1146705218]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("quiz_script")
[node name="Open" type="Button" parent="." unique_id=165052329]
visible = false
layout_mode = 0
offset_left = 1296.0
offset_top = 66.0
offset_right = 1346.0
offset_bottom = 97.0
text = "Open"
[node name="FileDialog" type="FileDialog" parent="." unique_id=485771559]
title = "Open a Directory"
initial_position = 2
size = Vector2i(616, 400)
ok_button_text = "Select Current Folder"
file_mode = 2
access = 2
show_hidden_files = true
[node name="MusicListPanel" parent="." unique_id=2011292375 instance=ExtResource("scene_MusicListPanel")]
layout_mode = 0
offset_left = 64.0
offset_top = 384.0
offset_right = 1152.0
offset_bottom = 896.0
[node name="InspirationList" parent="." unique_id=498283761 instance=ExtResource("scene_InspirationList")]
layout_mode = 0
offset_left = 1216.0
offset_top = 128.0
offset_right = 1857.0
offset_bottom = 512.0
[node name="NowPlaying" parent="." unique_id=42468498 instance=ExtResource("scene_NowPlaying")]
layout_mode = 0
offset_left = 64.0
offset_top = 64.0
offset_right = 1152.0
offset_bottom = 384.0
[node name="MusicPlayer" parent="." unique_id=1990459832 instance=ExtResource("5_emn36")]
layout_mode = 0
offset_left = 64.0
offset_top = 992.0
offset_right = 1856.0
offset_bottom = 1063.0
[node name="PlayersPanel" parent="." unique_id=1708375945 instance=ExtResource("scene_PlayersPanel")]
layout_mode = 0
offset_left = 1216.0
offset_top = 576.0
offset_right = 1857.0
offset_bottom = 977.0
[node name="QuizToolbar" parent="." unique_id=1873301941 instance=ExtResource("scene_QuizToolbar")]
layout_mode = 0
offset_left = 1360.0
offset_top = 64.0
offset_right = 1855.0
offset_bottom = 95.0
[node name="SongControls" parent="." unique_id=1640212773 instance=ExtResource("scene_SongControls")]
layout_mode = 0
offset_left = 65.0
offset_top = 944.0
offset_right = 368.0
offset_bottom = 975.0
[node name="SettingsPopup" parent="." unique_id=1323246978 instance=ExtResource("11_k62u5")]
visible = false
layout_mode = 1
offset_left = 720.0
offset_top = 153.0
offset_right = 720.0
offset_bottom = 153.0
[node name="CharacterSelectPopup" parent="." unique_id=1679856322 instance=ExtResource("6_dhrvg")]
unique_name_in_owner = true
visible = false
layout_mode = 1
offset_left = 405.0
offset_top = 165.0
offset_right = 1557.0
offset_bottom = 805.0
[node name="WinnerPopup" parent="." unique_id=999999999 instance=ExtResource("17_winner_window")]
unique_name_in_owner = true
visible = false
layout_mode = 1
offset_left = 720.0
offset_top = 153.0
offset_right = 720.0
offset_bottom = 153.0
[node name="DebugLabel" type="Label" parent="." unique_id=1959221257]
visible = false
layout_mode = 0
offset_left = 974.0
offset_top = 904.0
offset_right = 1014.0
offset_bottom = 927.0
scale = Vector2(3, 3)
text = "DEBUG"
horizontal_alignment = 1
vertical_alignment = 1
autowrap_mode = 2
[node name="SongLoader" type="Node" parent="." unique_id=1520867349]
script = ExtResource("song_loader_script")
[connection signal="dir_selected" from="FileDialog" to="." method="_on_file_dialog_dir_selected"]
+45
View File
@@ -0,0 +1,45 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://quiz/quiz_toolbar.gd" id="part_script"]
[node name="QuizToolbar" type="Control" unique_id=1873301941]
layout_mode = 3
offset_right = 495.0
offset_bottom = 31.0
mouse_filter = 2
script = ExtResource("part_script")
[node name="ResetPlaylistButton" type="Button" parent="." unique_id=1754155620]
layout_mode = 0
offset_right = 111.0
offset_bottom = 31.0
focus_mode = 0
action_mode = 0
text = "Reset playlist"
[node name="ResetPointsButton" type="Button" parent="." unique_id=942880776]
layout_mode = 0
offset_left = 128.0
offset_right = 239.0
offset_bottom = 31.0
focus_mode = 0
action_mode = 0
text = "Reset points"
[node name="SettingsButton" type="Button" parent="." unique_id=1193400323]
layout_mode = 0
offset_left = 256.0
offset_right = 367.0
offset_bottom = 31.0
focus_mode = 0
action_mode = 0
text = "Settings"
[node name="SoundTestButton" type="Button" parent="." unique_id=1332971879]
layout_mode = 0
offset_left = 384.0
offset_right = 495.0
offset_bottom = 31.0
focus_mode = 0
action_mode = 0
text = "Sound test"
+48
View File
@@ -0,0 +1,48 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://quiz/song_controls.gd" id="part_script"]
[sub_resource type="InputEventKey" id="InputEventKey_06rl4"]
device = -1
alt_pressed = true
keycode = 86
unicode = 8249
[sub_resource type="Shortcut" id="Shortcut_a7fvb"]
events = [SubResource("InputEventKey_06rl4")]
[sub_resource type="InputEventKey" id="InputEventKey_7dnqw"]
device = -1
alt_pressed = true
keycode = 67
unicode = 231
[sub_resource type="Shortcut" id="Shortcut_d6fml"]
events = [SubResource("InputEventKey_7dnqw")]
[node name="SongControls" type="Control" unique_id=1640212773]
layout_mode = 3
offset_right = 303.0
offset_bottom = 31.0
mouse_filter = 2
script = ExtResource("part_script")
[node name="ShowAnswerButton" type="Button" parent="." unique_id=415388039]
layout_mode = 0
offset_right = 111.0
offset_bottom = 31.0
focus_mode = 0
action_mode = 0
shortcut = SubResource("Shortcut_a7fvb")
text = "Show answer"
[node name="NextButton" type="Button" parent="." unique_id=1744703488]
layout_mode = 0
offset_left = 128.0
offset_right = 303.0
offset_bottom = 31.0
focus_mode = 0
disabled = true
action_mode = 0
shortcut = SubResource("Shortcut_d6fml")
text = "Randomize new track"
+67
View File
@@ -0,0 +1,67 @@
[gd_scene load_steps=5 format=3 uid="uid://1jbtmhbqolqe"]
[ext_resource type="Texture2D" uid="uid://c8r7ykphss4c2" path="res://characters/Link.png" id="1_ll28s"]
[ext_resource type="Script" uid="uid://cjo13wixip8mq" path="res://quiz/song_row.gd" id="1_lspki"]
[ext_resource type="Theme" uid="uid://8bllart6xn1f" path="res://themes/default_theme.tres" id="1_x7fq8"]
[ext_resource type="StyleBox" uid="uid://bsv6yb0yir04l" path="res://themes/style_box_flat.tres" id="3_5h84f"]
[node name="SongRow" type="PanelContainer"]
custom_minimum_size = Vector2(1000, 0)
offset_right = 1088.0
offset_bottom = 59.0
theme = ExtResource("1_x7fq8")
script = ExtResource("1_lspki")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 0
[node name="SongListLabel" type="Label" parent="HBoxContainer"]
unique_name_in_owner = true
texture_filter = 2
custom_minimum_size = Vector2(865, 28)
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 1
theme = ExtResource("1_x7fq8")
theme_override_font_sizes/font_size = 20
theme_override_styles/normal = ExtResource("3_5h84f")
text = "Final Fantasy Dissidia 012 Duodecim (Sista Fantasin Meningsskiljaktigheter 012 Tolv) - 'Crystal Cave -arrange-'' from FINAL FANTASY III"
autowrap_mode = 2
[node name="Panel" type="Panel" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
[node name="SongListPlayers" type="HBoxContainer" parent="HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 0
[node name="TextureRect" type="TextureRect" parent="HBoxContainer/SongListPlayers"]
custom_minimum_size = Vector2(50, 25)
layout_mode = 2
texture = ExtResource("1_ll28s")
expand_mode = 1
stretch_mode = 5
[node name="TextureRect2" type="TextureRect" parent="HBoxContainer/SongListPlayers"]
custom_minimum_size = Vector2(50, 25)
layout_mode = 2
texture = ExtResource("1_ll28s")
expand_mode = 1
stretch_mode = 6
[node name="TextureRect3" type="TextureRect" parent="HBoxContainer/SongListPlayers"]
custom_minimum_size = Vector2(50, 25)
layout_mode = 2
texture = ExtResource("1_ll28s")
expand_mode = 1
[node name="TextureRect4" type="TextureRect" parent="HBoxContainer/SongListPlayers"]
custom_minimum_size = Vector2(50, 25)
layout_mode = 2
texture = ExtResource("1_ll28s")
expand_mode = 1
stretch_mode = 6
+68
View File
@@ -0,0 +1,68 @@
class_name InspirationList
extends ScrollContainer
## The list of every soundtrack, shown for inspiration. It scrolls slowly up and down
## by itself, at the speed set in the settings.
## The soundtracks shown, in order.
var soundtracks: Array = []
# Scroll direction: 1 = down, -1 = up
var scroll_direction: int = 1
@onready var _rows: VBoxContainer = $VBoxContainer
func _ready() -> void:
scroll_direction = 1
func _process(delta: float) -> void:
var speed_pixels_per_second: float = float(Settings.inspiration_list_speed) * 60.0
var scroll_amount: float = speed_pixels_per_second * delta * float(scroll_direction)
var scroll_bar: VScrollBar = get_v_scroll_bar()
# Don't scroll if list is empty or too short
if scroll_bar.max_value <= 0:
return
var current_pos: float = scroll_bar.value
if scroll_direction == 1:
# Scrolling down
if current_pos + scroll_bar.page < scroll_bar.max_value:
scroll_bar.value = minf(current_pos + scroll_amount,
scroll_bar.max_value - scroll_bar.page)
else:
# Reached bottom, reverse direction
scroll_direction = -1
scroll_bar.value = scroll_bar.max_value - scroll_bar.page
else:
# Scrolling up
if current_pos > 0:
scroll_bar.value = maxf(current_pos + scroll_amount, 0)
else:
# Reached top, reverse direction
scroll_direction = 1
scroll_bar.value = 0
## Fetches every soundtrack from the server and shows them.
func load_from_server() -> void:
GameLog.debug("load_from_server")
var populate_list: Callable = func populate_list(array: Variant) -> void:
if typeof(array) == TYPE_ARRAY:
show_soundtracks(array)
else:
GameLog.warning("Unexpected data")
MusicServerClient.fetch_all_soundtracks(populate_list)
## Shows [param list] instead of the soundtracks shown now.
func show_soundtracks(list: Array) -> void:
soundtracks = []
soundtracks.append_array(list)
Settings.delete_children(_rows)
for i: int in soundtracks.size():
_rows.add_child(ListRow.create(soundtracks[i], i, 20))
+1
View File
@@ -0,0 +1 @@
uid://elgn7gkxgagq
+26
View File
@@ -0,0 +1,26 @@
class_name MusicListPanel
extends PanelContainer
## The list of songs in the playlist, one row per song.
## 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")
@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)
for s: SongObject in Playlist.get_playlist():
var new_song_list_object: SongRow = _song_list_object.instantiate()
new_song_list_object.song_object = s
new_song_list_object.gui_input.connect(_on_row_input.bind(s.song_number))
_rows.add_child(new_song_list_object)
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)
+1
View File
@@ -0,0 +1 @@
uid://b8e27uui01tt
+10
View File
@@ -0,0 +1,10 @@
class_name NowPlaying
extends VBoxContainer
## The soundtrack and song that are playing, in large text at the top of the quiz.
## Shows [param soundtrack_title] and [param song_title]. The playlist hides them as
## question marks until the answer is shown.
func show_song(soundtrack_title: String, song_title: String) -> void:
$SoundtrackLabel.text = soundtrack_title
$SongLabel.text = song_title
+1
View File
@@ -0,0 +1 @@
uid://beoi75d4u568h
+49
View File
@@ -0,0 +1,49 @@
class_name PlayerNameField
extends TextEdit
## The field for a new player's name. It keeps to one line of at most
## [constant MAX_NAME_LENGTH] characters, and reports Enter so the player can be added.
## Emitted when Enter is pressed while the field has focus.
signal enter_key_pressed
## Emitted when Alt+A is pressed.
signal close_pressed
## The longest name a player can have.
const MAX_NAME_LENGTH: int = 10
var current_text: String = ""
var cursor_line: int = 0
var cursor_column: int = 0
func _ready() -> void:
text_changed.connect(_on_text_changed)
func _input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed:
if event.alt_pressed && event.keycode == KEY_A:
close_pressed.emit()
if has_focus():
if event.keycode == KEY_ENTER || event.keycode == KEY_KP_ENTER:
enter_key_pressed.emit()
func _on_text_changed() -> void:
if text.contains("\n"):
text = text.replace("\n", "")
var new_text: String = text
if new_text.length() > MAX_NAME_LENGTH:
text = current_text
# when replacing the text, the cursor will get moved to the beginning of the
# text, so move it back to where it was
set_caret_line(cursor_line)
set_caret_column(cursor_column)
current_text = text
# save current position of cursor for when we have reached the limit
cursor_line = get_caret_line()
cursor_column = get_caret_column()
+1
View File
@@ -0,0 +1 @@
uid://cgakje8gb37tf
+78
View File
@@ -0,0 +1,78 @@
class_name PlayerRow
extends Control
signal change_character_clicked
signal player_removed
## The player shown in this row.
var player_object: PlayerObject
## Position in Settings.player_array. Only used for the keybinds: Alt+<list_index + 1>
## gives this player a point and Ctrl+Alt+<list_index + 1> takes one away.
var list_index: int
@onready var player_name_field: Label = %Name
@onready var add_button: Button = %AddPoint
@onready var minus_button: Button = %RemovePoint
@onready var character: TextureButton = %Character
@onready var remove_player: TextureButton = %RemovePlayer
func _ready() -> void:
add_button.pressed.connect(add_point)
add_button.set_shortcut(create_button_shortcut(list_index, false))
minus_button.pressed.connect(minus_point)
minus_button.set_shortcut(create_button_shortcut(list_index, true))
character.pressed.connect(change_character)
remove_player.pressed.connect(func() -> void: player_removed.emit())
update_score()
set_player_character()
func _process(delta: float) -> void:
remove_player.visible = Settings.edit_players
func create_button_shortcut(index: int, ctrl_pressed: bool) -> Shortcut:
var button_shortcut: Shortcut = Shortcut.new()
var button_event: InputEventKey = InputEventKey.new()
button_event.keycode = KEY_1 + index
button_event.alt_pressed = true
button_event.ctrl_pressed = ctrl_pressed
button_shortcut.events.append(button_event)
return button_shortcut
func add_point() -> void:
player_object.add_point()
update_score()
func minus_point() -> void:
player_object.minus_point()
update_score()
func change_character() -> void:
change_character_clicked.emit()
func new_character_selected(character_texture: ImageTexture) -> void:
GameLog.debug("Back in player list with new")
player_object.character = character_texture
set_player_character()
func set_player_character() -> void:
character.custom_minimum_size = Vector2(80, 40)
character.ignore_texture_size = true
character.stretch_mode = TextureButton.STRETCH_KEEP_ASPECT_CENTERED
character.texture_normal = player_object.character
func update_score() -> void:
if OS.has_feature("debug"):
player_name_field.text = "%d %s: %d" % [list_index + 1, player_object.player_name,
player_object.player_score]
else:
player_name_field.text = player_object.player_name + ": " + str(player_object.player_score)
+1
View File
@@ -0,0 +1 @@
uid://dl6no2wr2c86y
+84
View File
@@ -0,0 +1,84 @@
class_name PlayersPanel
extends PanelContainer
## The players and their points, with a row for adding new players.
##
## The players themselves live in [code]Settings.player_array[/code]; this panel shows
## them and adds and removes them there.
## Emitted when a player has been added to [code]Settings.player_array[/code], before
## the list shows it.
signal player_added(player_object: PlayerObject)
## Emitted when a player has been removed from [code]Settings.player_array[/code].
signal player_removed(player_object: PlayerObject)
## Emitted when the character button in [param row] is pressed.
signal change_character_requested(row: PlayerRow, player_name: String)
var _player_row: PackedScene = preload("res://quiz/PlayerRow.tscn")
@onready var add_players_button: TextureButton = %AddPlayersButton
@onready var add_player_container: HBoxContainer = %AddPlayerContainer
@onready var add_player_button: Button = %AddPlayerButton
@onready var new_player_name_field: PlayerNameField = %PlayerNameField
@onready var players_list_container: VBoxContainer = %PlayersListVBoxContainer
func _ready() -> void:
add_players_button.pressed.connect(add_players)
add_player_button.pressed.connect(add_player)
new_player_name_field.enter_key_pressed.connect(add_player)
## Shows or hides the row for adding players, and the buttons for removing them.
func add_players() -> void:
GameLog.debug("add_players")
Settings.edit_players = !Settings.edit_players
add_player_container.visible = !add_player_container.visible
new_player_name_field.grab_focus()
## Adds a player with the name in the name field, unless it is empty or there are
## already as many players as there can be.
func add_player() -> void:
GameLog.debug("add_player")
if new_player_name_field.text != "" \
&& Settings.player_array.size() < Settings.MAX_NUMBER_OF_PLAYERS:
var new_player_object: PlayerObject = PlayerObject.new(new_player_name_field.text)
new_player_name_field.text = ""
Settings.player_array.append(new_player_object)
player_added.emit(new_player_object)
reload()
## Shows the players in [code]Settings.player_array[/code] again, e.g. after their
## points were reset.
func reload() -> void:
GameLog.debug("load_players")
Settings.delete_children(players_list_container)
var counter: int = 0
for player_object: PlayerObject in Settings.player_array:
GameLog.debug(player_object.player_name)
var new_player: PlayerRow = _player_row.instantiate()
new_player.player_object = player_object
new_player.list_index = counter
new_player.change_character_clicked.connect(
_on_change_character_clicked.bind(new_player, player_object.player_name))
new_player.player_removed.connect(_on_player_removed.bind(player_object))
players_list_container.add_child(new_player)
counter += 1
func _on_change_character_clicked(row: PlayerRow, player_name: String) -> void:
change_character_requested.emit(row, player_name)
func _on_player_removed(player_object: PlayerObject) -> void:
GameLog.debug("_on_player_removed ", player_object.player_name)
Settings.player_array.erase(player_object)
reload()
player_removed.emit(player_object)
+1
View File
@@ -0,0 +1 @@
uid://ctayn0soyatfk
+298
View File
@@ -0,0 +1,298 @@
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()
# 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.")
+1
View File
@@ -0,0 +1 @@
uid://b0od47vseenx4
+25
View File
@@ -0,0 +1,25 @@
class_name QuizToolbar
extends Control
## The row of quiz buttons under the top bar: reset playlist, reset points, settings
## and sound test.
signal reset_playlist_pressed
signal reset_points_pressed
signal settings_pressed
signal sound_test_pressed
@onready var reset_playlist_button: Button = $ResetPlaylistButton
@onready var sound_test_button: Button = $SoundTestButton
func _ready() -> void:
reset_playlist_button.pressed.connect(reset_playlist_pressed.emit)
$ResetPointsButton.pressed.connect(reset_points_pressed.emit)
$SettingsButton.pressed.connect(settings_pressed.emit)
sound_test_button.pressed.connect(sound_test_pressed.emit)
## Disables the buttons that use the song list, e.g. while the server syncs it.
func set_locked(locked: bool) -> void:
reset_playlist_button.disabled = locked
sound_test_button.disabled = locked
+1
View File
@@ -0,0 +1 @@
uid://dmsy36s1ht7x5
+12
View File
@@ -0,0 +1,12 @@
class_name ScrollToEndContainer
extends ScrollContainer
## A scroll container that scrolls to the end whenever its content grows, so the newest
## item is always in view.
var max_value: float = 0.0
func _draw() -> void:
if max_value != get_v_scroll_bar().max_value:
max_value = get_v_scroll_bar().max_value
scroll_vertical = int(max_value)
+1
View File
@@ -0,0 +1 @@
uid://gf1bk6xbe3j
+27
View File
@@ -0,0 +1,27 @@
class_name SongControls
extends Control
## The buttons for the song that is playing: show the answer, and go to the next song.
signal show_answer_pressed
signal next_pressed
@onready var show_answer_button: Button = $ShowAnswerButton
@onready var next_button: Button = $NextButton
func _ready() -> void:
show_answer_button.pressed.connect(show_answer_pressed.emit)
next_button.pressed.connect(next_pressed.emit)
## Enables Next while there is a downloaded song to play next.
func set_next_enabled(enabled: bool) -> void:
next_button.disabled = !enabled
## Disables both buttons, e.g. while the server syncs the song list. Unlocking enables
## Show answer again; Next comes back when the next song has been downloaded.
func set_locked(locked: bool) -> void:
show_answer_button.disabled = locked
if locked:
next_button.disabled = true
+1
View File
@@ -0,0 +1 @@
uid://d6nevh66yaw1
+101
View File
@@ -0,0 +1,101 @@
class_name SongLoader
extends Node
## Downloads songs from the server into the Playlist ahead of time, so the next song
## can start at once.
##
## How many songs it keeps ready is the cache size in the settings
## ([code]Playlist.number_of_tracks_to_preload[/code]).
## Emitted when the songs already in the server playlist have been loaded into the
## Playlist.
signal song_list_loaded
## Emitted when a new song has been downloaded and added to the Playlist.
signal song_added
## Seconds to wait before retrying a download step that failed.
var retry_seconds: float = 5.0
## Loads the songs already in the server playlist, then starts preloading new ones.
## Preloading waits for the list, because loading the list clears the playlist.
func load_song_list() -> void:
GameLog.debug("load_song_list")
var song_list_fetched: Callable = func song_list_fetched(data: Variant) -> void:
Playlist.clear_song_list()
if typeof(data) == TYPE_ARRAY:
for d: Dictionary in data:
var new_song_object: SongObject = SongObject.new()
new_song_object.song_number = d.SongNo
new_song_object.soundtrack_title = d.Soundtrack
new_song_object.song_title = d.Song
new_song_object.is_answered = true
new_song_object.has_played = true
Playlist.add_to_playlist(new_song_object)
elif data != null:
GameLog.warning("Unexpected data")
Playlist.update_last_played_song()
song_list_loaded.emit()
fetch_song_if_idle()
MusicServerClient.fetch_song_list(song_list_fetched, _retry_later.bind(load_song_list))
## Starts downloading one more song, which keeps downloading until the cache is full.
func fetch_song() -> void:
GameLog.debug("fetch_song")
Playlist.is_song_downloading = true
_download_random_song(SongObject.new())
## Starts downloading a song unless one is already downloading.
func fetch_song_if_idle() -> void:
if !Playlist.is_song_downloading:
fetch_song()
## Starts downloading if nothing is downloading and the cache is not full, e.g. after
## the cache size was raised.
func fill_cache() -> void:
if !Playlist.is_song_downloading && Playlist.should_preload_more_songs():
fetch_song()
# Fetching a song takes three requests. If one fails, only that step is retried, so
# the server and the game keep the same songs in their playlists.
func _download_random_song(new_song_object: SongObject) -> void:
var song_downloaded: Callable = func song_downloaded(body: PackedByteArray) -> void:
GameLog.debug("song_downloaded")
var sound: AudioStream = AudioStreamMP3.new()
sound.data = body
new_song_object.song = sound
_add_song_to_queue(new_song_object)
MusicServerClient.fetch_random_song(Settings.use_low_played_mode, song_downloaded,
_retry_later.bind(_download_random_song.bind(new_song_object)))
func _add_song_to_queue(new_song_object: SongObject) -> void:
MusicServerClient.add_to_queue(_fetch_song_info.bind(new_song_object),
_retry_later.bind(_add_song_to_queue.bind(new_song_object)))
func _fetch_song_info(new_song_object: SongObject) -> void:
var song_info_fetched: Callable = func song_info_fetched(data_received: Dictionary) -> void:
GameLog.debug("song_info_fetched")
new_song_object.song_number = data_received.SongNo
new_song_object.soundtrack_title = data_received.Soundtrack
new_song_object.song_title = data_received.Song
GameLog.debug("new_song_object: ", new_song_object.to_string())
Playlist.add_to_playlist(new_song_object)
if Playlist.should_preload_more_songs():
fetch_song()
else:
Playlist.is_song_downloading = false
song_added.emit()
MusicServerClient.fetch_song_info(song_info_fetched,
_retry_later.bind(_fetch_song_info.bind(new_song_object)))
func _retry_later(step: Callable) -> void:
GameLog.warning("Song download failed, retrying in %s seconds" % retry_seconds)
get_tree().create_timer(retry_seconds).timeout.connect(step)
+1
View File
@@ -0,0 +1 @@
uid://dwqirg7x7mmj6
+37
View File
@@ -0,0 +1,37 @@
class_name SongRow
extends PanelContainer
## One song in the music list: its number, soundtrack and title, and a marker for
## each player who got a point for it.
var song_object: SongObject
@onready var song_list_label: Label = %SongListLabel
@onready var song_list_players: HBoxContainer = %SongListPlayers
func _ready() -> void:
set_label()
update_players()
func set_label() -> void:
if song_object != null:
var size_to_change: int = song_object.players_given_point.size() * 50
song_list_label.custom_minimum_size = Vector2(1000 - size_to_change, 28)
if song_object.is_playing:
song_list_label.add_theme_color_override("font_color", Color(1, 0.5, 0))
song_list_label.text = song_object.get_song_info()
func update_players() -> void:
Settings.delete_children(song_list_players)
if song_object != null:
# Show players in the same order as the player list
for player: PlayerObject in Settings.player_array:
if song_object.players_given_point.has(player.id):
var texture: TextureRect = TextureRect.new()
texture.texture = player.character
texture.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
texture.custom_minimum_size = Vector2(50, 25)
song_list_players.add_child(texture)
+1
View File
@@ -0,0 +1 @@
uid://cjo13wixip8mq