Buttons get 12 px of side padding. The top bar buttons, the quiz toolbar and Show answer/Next are laid out in rows with 12 px gaps and are all 36 px tall, and the ±1 buttons use a compact StepButton style. "Randomize new track" is now "Next song". Player rows show the name and the score apart, alternate like the other lists and highlight the character under the mouse. The name field is a LineEdit with a 10-letter limit; blank and duplicate names are refused, and a full list says "Up to 7 players". Remove buttons update when editing is switched instead of every frame, and the spacer panels are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
112 lines
4.1 KiB
GDScript
112 lines
4.1 KiB
GDScript
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 add_player_hint: Label = %AddPlayerHint
|
|
@onready var new_player_name_field: LineEdit = %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.text_submitted.connect(func(_text: String) -> void: 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 = Settings.edit_players
|
|
for row: PlayerRow in players_list_container.get_children():
|
|
row.set_editing(Settings.edit_players)
|
|
_update_add_row()
|
|
if Settings.edit_players:
|
|
new_player_name_field.grab_focus()
|
|
|
|
|
|
## Adds a player with the name in the name field. Blank names, names another player
|
|
## already has, and players beyond [constant Settings.MAX_NUMBER_OF_PLAYERS] are not
|
|
## added.
|
|
func add_player() -> void:
|
|
GameLog.debug("add_player")
|
|
var player_name: String = new_player_name_field.text.strip_edges()
|
|
if !can_add(player_name):
|
|
return
|
|
var new_player_object: PlayerObject = PlayerObject.new(player_name)
|
|
new_player_name_field.text = ""
|
|
Settings.player_array.append(new_player_object)
|
|
player_added.emit(new_player_object)
|
|
reload()
|
|
|
|
|
|
## Whether a player called [param player_name] can be added.
|
|
func can_add(player_name: String) -> bool:
|
|
if player_name.is_empty() || Settings.player_array.size() >= Settings.MAX_NUMBER_OF_PLAYERS:
|
|
return false
|
|
for player: PlayerObject in Settings.player_array:
|
|
if player.player_name.to_lower() == player_name.to_lower():
|
|
return false
|
|
return true
|
|
|
|
|
|
## 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
|
|
_update_add_row()
|
|
|
|
|
|
# A full list can't take more players, so the name field gives way to a note saying so
|
|
func _update_add_row() -> void:
|
|
var full: bool = Settings.player_array.size() >= Settings.MAX_NUMBER_OF_PLAYERS
|
|
add_player_hint.text = "Up to %d players" % Settings.MAX_NUMBER_OF_PLAYERS
|
|
add_player_hint.visible = full
|
|
new_player_name_field.visible = !full
|
|
add_player_button.visible = !full
|
|
|
|
|
|
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)
|