class_name CharacterSelectPopup extends BasePopup ## The characters players pick from, from the server or from a folder on this computer ## (see [method Settings.characters_dir]). ## Emitted with the picture and name of the character that was picked. signal character_selected(texture: ImageTexture, character_name: String) ## Emitted when the characters come from somewhere else than before, e.g. a folder was ## picked. Characters picked before are not in the new set. signal source_changed var can_select_character: bool = false var character: PackedScene = preload("res://popups/CharacterCard.tscn") ## Keeps the pictures on disk, so only changed ones are downloaded. var character_cache: CharacterCache = CharacterCache.new() ## Where the characters shown come from: [member character_cache] or a [FolderCharacters]. var source: RefCounted = character_cache ## The folder the characters shown come from, or empty for the server. Null before the ## characters were first loaded. var source_dir: Variant = null @onready var character_panel: Panel = %CharacterPanel @onready var title_label: Label = %TitleLabel @onready var character_grid: GridContainer = %CharacterGridContainer @onready var close_timer: Timer = %CloseTimer func _ready() -> void: close_timer.timeout.connect(_on_close_timeout) func _on_close_timeout() -> void: GameLog.debug("_on_close_timeout!") Settings.character_select_open = false close_timer.stop() ## Loads the characters from where [method Settings.characters_dir] says. Emits ## [signal source_changed] when that is somewhere else than last time. func load_characters() -> void: GameLog.debug("load_characters") var dir: String = Settings.characters_dir() var changed: bool = source_dir != null && source_dir != dir source_dir = dir source = character_cache if dir.is_empty() else FolderCharacters.new(dir) var loading: RefCounted = source var list_loaded: Callable = func list_loaded(names: Array[String]) -> void: GameLog.debug("list_loaded") # The source changed again before the server answered if source != loading: return Settings.delete_children(character_grid) for character_name: String in names: GameLog.debug("character_name ", character_name) var character_box: CharacterCard = character.instantiate() character_grid.add_child(character_box) character_box.set_character_name(character_name, loading.fetch_image) character_box.new_character_selected.connect(_on_character_selected) loading.load_list(list_loaded) if changed: source_changed.emit() func show_grid(player_name: String) -> void: GameLog.debug("show_grid") title_label.text = "Select character for " + player_name close_timer.stop() open() can_select_character = true Settings.character_select_open = true func close() -> void: super() Settings.character_select_open = false func _on_character_selected(texture: ImageTexture, character_name: String) -> void: GameLog.debug("_on_character_selected") # Not close(): character_select_open stays true until close_timer fires, so the click # that picked the character does not also select a song behind it visible = false if can_select_character: character_selected.emit(texture, character_name) close_timer.start() can_select_character = false