Lay out the song list's pictures and text to fit any number of players
The players' pictures sit on the right in even lines of at most four, each ending at the row's right edge, so five pictures are 3 + 2 and seven 4 + 3. The text takes the room they leave and wraps only when it does not fit, and the row is as tall as the taller of the two, instead of a width fixed by the number of pictures. Rows are rounded and alternate like the other lists, are highlighted under the mouse, and the playing song has an orange edge. Clicking a picture clicks its song.
This commit is contained in:
1 parent
84e137e16a
commit
78e1facaf0
10 files changed
+753
-361
No files matched your search
@@ -13,6 +13,7 @@ script = ExtResource("part_script")
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="." unique_id=707750459]
|
||||
layout_mode = 2
|
||||
follow_focus = true
|
||||
horizontal_scroll_mode = 0
|
||||
script = ExtResource("7_dj026")
|
||||
|
||||
[node name="MusicList" type="VBoxContainer" parent="ScrollContainer" unique_id=373398568]
|
||||
@@ -20,4 +21,4 @@ unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 10
|
||||
theme_override_constants/separation = 4
|
||||
+9
-43
@@ -1,63 +1,29 @@
|
||||
[gd_scene 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"]
|
||||
|
||||
[node name="SongRow" type="PanelContainer"]
|
||||
custom_minimum_size = Vector2(1000, 0)
|
||||
offset_right = 1088.0
|
||||
offset_bottom = 59.0
|
||||
theme_type_variation = &"SongRow"
|
||||
script = ExtResource("1_lspki")
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
mouse_filter = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[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_type_variation = &"SongRowLabel"
|
||||
text = "Final Fantasy Dissidia 012 Duodecim (Sista Fantasin Meningsskiljaktigheter 012 Tolv) - 'Crystal Cave -arrange-'' from FINAL FANTASY III"
|
||||
autowrap_mode = 2
|
||||
vertical_alignment = 1
|
||||
autowrap_mode = 3
|
||||
|
||||
[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"]
|
||||
[node name="SongListPlayers" type="VBoxContainer" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
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
|
||||
size_flags_vertical = 4
|
||||
mouse_filter = 2
|
||||
theme_type_variation = &"SongRowPictureLines"
|
||||
@@ -14,9 +14,12 @@ var _song_list_object: PackedScene = preload("res://quiz/SongRow.tscn")
|
||||
## 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 songs: Array[SongObject] = Playlist.get_playlist()
|
||||
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)
|
||||
|
||||
|
||||
+80
-12
@@ -1,37 +1,105 @@
|
||||
class_name SongRow
|
||||
extends PanelContainer
|
||||
## One song in the music list: its number, soundtrack and title, and a marker for
|
||||
## One song in the music list: its number, soundtrack and title, and the character of
|
||||
## each player who got a point for it.
|
||||
##
|
||||
## The pictures are on the right and the text takes the room they leave, wrapping only
|
||||
## when it does not fit on one line. With many pictures they go on more lines, as even as
|
||||
## possible and at most [constant MAX_PICTURES_PER_LINE] on each, so the text keeps most
|
||||
## of the row. Every line ends at the row's right edge. The row is as tall as the taller
|
||||
## of the text and the pictures.
|
||||
|
||||
## The most pictures on one line before they go on another.
|
||||
const MAX_PICTURES_PER_LINE: int = 4
|
||||
## The size of each picture. Characters are twice as wide as they are tall.
|
||||
const PICTURE_SIZE: Vector2 = Vector2(56, 28)
|
||||
|
||||
var song_object: SongObject
|
||||
## The row's place in the list, for the alternating background.
|
||||
var index: int = 0
|
||||
|
||||
var _hovered: bool = false
|
||||
|
||||
@onready var song_list_label: Label = %SongListLabel
|
||||
@onready var song_list_players: HBoxContainer = %SongListPlayers
|
||||
## The lines of pictures, top to bottom, each an HBoxContainer.
|
||||
@onready var song_list_players: VBoxContainer = %SongListPlayers
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
mouse_entered.connect(_set_hovered.bind(true))
|
||||
mouse_exited.connect(_set_hovered.bind(false))
|
||||
set_label()
|
||||
update_players()
|
||||
|
||||
|
||||
## The pictures shown, line by line.
|
||||
func pictures() -> Array[TextureRect]:
|
||||
var shown: Array[TextureRect] = []
|
||||
for line: Node in song_list_players.get_children():
|
||||
shown.append_array(line.get_children())
|
||||
return shown
|
||||
|
||||
|
||||
## The number of pictures on a full line for [param pictures] pictures: as few lines as
|
||||
## [constant MAX_PICTURES_PER_LINE] allows, with the pictures spread evenly over them,
|
||||
## e.g. 3 and 2 for five pictures instead of 4 and 1.
|
||||
static func picture_columns(pictures: int) -> int:
|
||||
if pictures <= 0:
|
||||
return 1
|
||||
var lines: int = ceili(float(pictures) / MAX_PICTURES_PER_LINE)
|
||||
return ceili(float(pictures) / lines)
|
||||
|
||||
|
||||
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.theme_type_variation = &"SongRowLabelPlaying"
|
||||
song_list_label.theme_type_variation = &"SongRowLabelPlaying" \
|
||||
if song_object.is_playing else &"SongRowLabel"
|
||||
song_list_label.text = song_object.get_song_info()
|
||||
_update_style()
|
||||
|
||||
|
||||
func update_players() -> void:
|
||||
Settings.delete_children(song_list_players)
|
||||
var scorers: Array[PlayerObject] = []
|
||||
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)
|
||||
scorers.append(player)
|
||||
var per_line: int = picture_columns(scorers.size())
|
||||
var line: HBoxContainer = null
|
||||
for i: int in scorers.size():
|
||||
if i % per_line == 0:
|
||||
line = HBoxContainer.new()
|
||||
line.theme_type_variation = &"SongRowPictureLine"
|
||||
line.alignment = BoxContainer.ALIGNMENT_END
|
||||
line.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
song_list_players.add_child(line)
|
||||
line.add_child(_make_picture(scorers[i]))
|
||||
song_list_players.visible = !scorers.is_empty()
|
||||
|
||||
|
||||
func _make_picture(player: PlayerObject) -> TextureRect:
|
||||
var picture: TextureRect = TextureRect.new()
|
||||
picture.texture = player.character
|
||||
picture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
picture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
picture.custom_minimum_size = PICTURE_SIZE
|
||||
picture.tooltip_text = player.player_name
|
||||
# Clicks on a picture still click the row
|
||||
picture.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
return picture
|
||||
|
||||
|
||||
func _set_hovered(hovered: bool) -> void:
|
||||
_hovered = hovered
|
||||
_update_style()
|
||||
|
||||
|
||||
func _update_style() -> void:
|
||||
if _hovered:
|
||||
theme_type_variation = &"SongRowHover"
|
||||
elif song_object != null && song_object.is_playing:
|
||||
theme_type_variation = &"SongRowPlaying"
|
||||
else:
|
||||
theme_type_variation = &"SongRowOdd" if index % 2 != 0 else &"SongRow"
|
||||
Reference in new issue
Block a user