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.
106 lines
3.6 KiB
GDScript
106 lines
3.6 KiB
GDScript
class_name SongRow
|
|
extends PanelContainer
|
|
## 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
|
|
## 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:
|
|
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):
|
|
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"
|