class_name ChatPanel extends VBoxContainer @onready var _chat_message_scene: PackedScene = preload("uid://docnx7algl78k") @export_range(0.1, 1.0, 0.05) var auto_scroll_duration: float = 0.2 @export var message_container: VBoxContainer @export var scroll_container: ScrollContainer @export var message_input: LineEdit @export var send_message_button: Button signal message_sent(message: String) func put_chat_message(sender: String, message: String) -> void: var scene: ChatMessage = _chat_message_scene.instantiate() scene.set_message("<{sender}> {message}".format({ "sender": sender, "message": message, })) message_container.add_child(scene) # Wait a short time so that ScrollLayout receives new height because of newly added child await get_tree().create_timer(0.05).timeout _scroll_to_bottom() func _scroll_to_bottom() -> void: create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT).tween_property(scroll_container, "scroll_vertical", scroll_container.get_v_scroll_bar().max_value - scroll_container.get_v_scroll_bar().size.y, auto_scroll_duration) func _send_chat_message() -> void: if message_input.text.is_empty(): return message_sent.emit(message_input.text.strip_edges()) message_input.text = "" func _on_message_input_text_changed(new_text: String) -> void: send_message_button.disabled = new_text.is_empty() func _on_message_input_gui_input(event: InputEvent) -> void: if event.is_action_pressed("send_chat_message"): _send_chat_message() func _on_send_message_button_pressed() -> void: _send_chat_message() func _on_web_client_connection_status_changed(new_status: WebClient.ConnectionStatus) -> void: if new_status == WebClient.ConnectionStatus.JOINED: message_input.editable = true send_message_button.disabled = false else: message_input.editable = false send_message_button.disabled = true