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)