模板脚本文件
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
class_name MultiplayerChatUI
|
||||
extends Control
|
||||
|
||||
signal message_sent(message_text: String)
|
||||
|
||||
const MAX_CHAT_MESSAGES: int = 100
|
||||
const MAX_VISIBLE_MESSAGES: int = 8
|
||||
const FEED_VISIBLE_SECONDS: float = 6.0
|
||||
const FEED_FADE_SECONDS: float = 0.35
|
||||
const SAFE_AREA_MARGIN := 16.0
|
||||
const MIN_CHAT_WIDTH := 280.0
|
||||
const MAX_CHAT_WIDTH := 480.0
|
||||
const MAX_CHAT_HEIGHT := 268.0
|
||||
|
||||
var chat_visible: bool = false
|
||||
var chat_history: Array[String] = []
|
||||
var fade_tween: Tween
|
||||
|
||||
@onready var chat: RichTextLabel = $ChatLayout/Chat
|
||||
@onready var message: LineEdit = $ChatLayout/Message
|
||||
@onready var feed_timer: Timer = $FeedTimer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
message.text_submitted.connect(_on_message_submitted)
|
||||
feed_timer.timeout.connect(_on_feed_timer_timeout)
|
||||
feed_timer.wait_time = FEED_VISIBLE_SECONDS
|
||||
get_viewport().size_changed.connect(_update_responsive_layout)
|
||||
_update_responsive_layout()
|
||||
show()
|
||||
clear_chat()
|
||||
|
||||
|
||||
func _update_responsive_layout() -> void:
|
||||
var viewport_size := get_viewport().get_visible_rect().size
|
||||
var available_width := maxf(1.0, viewport_size.x - SAFE_AREA_MARGIN * 2.0)
|
||||
var preferred_width := clampf(viewport_size.x * 0.42, MIN_CHAT_WIDTH, MAX_CHAT_WIDTH)
|
||||
var target_width := minf(available_width, preferred_width)
|
||||
var target_height := minf(MAX_CHAT_HEIGHT, maxf(1.0, viewport_size.y - SAFE_AREA_MARGIN * 2.0))
|
||||
|
||||
offset_left = SAFE_AREA_MARGIN
|
||||
offset_right = SAFE_AREA_MARGIN + target_width
|
||||
offset_bottom = -SAFE_AREA_MARGIN
|
||||
offset_top = -SAFE_AREA_MARGIN - target_height
|
||||
|
||||
|
||||
func toggle_chat() -> void:
|
||||
if chat_visible:
|
||||
close_chat()
|
||||
return
|
||||
|
||||
chat_visible = true
|
||||
_stop_feed_animation()
|
||||
_show_feed()
|
||||
message.show()
|
||||
await get_tree().process_frame
|
||||
if not chat_visible:
|
||||
return
|
||||
message.grab_focus()
|
||||
|
||||
|
||||
func close_chat() -> void:
|
||||
chat_visible = false
|
||||
message.text = ""
|
||||
message.release_focus()
|
||||
message.hide()
|
||||
|
||||
if chat_history.is_empty():
|
||||
chat.hide()
|
||||
else:
|
||||
_show_feed_temporarily()
|
||||
|
||||
|
||||
func is_chat_visible() -> bool:
|
||||
return chat_visible
|
||||
|
||||
|
||||
func _on_message_submitted(_submitted_text: String) -> void:
|
||||
var message_text := message.text.strip_edges()
|
||||
if message_text.is_empty():
|
||||
return
|
||||
|
||||
close_chat()
|
||||
message_sent.emit(message_text)
|
||||
|
||||
|
||||
func add_message(nick: String, msg: String) -> void:
|
||||
var formatted_message := _escape_bbcode("%s: %s" % [nick, msg])
|
||||
chat_history.append(formatted_message)
|
||||
while chat_history.size() > MAX_CHAT_MESSAGES:
|
||||
chat_history.pop_front()
|
||||
|
||||
_render_chat_history()
|
||||
if chat_visible:
|
||||
_stop_feed_animation()
|
||||
_show_feed()
|
||||
else:
|
||||
_show_feed_temporarily()
|
||||
|
||||
|
||||
func _render_chat_history() -> void:
|
||||
chat.clear()
|
||||
var first_message := maxi(0, chat_history.size() - MAX_VISIBLE_MESSAGES)
|
||||
for index in range(first_message, chat_history.size()):
|
||||
chat.append_text(chat_history[index])
|
||||
if index < chat_history.size() - 1:
|
||||
chat.append_text("\n")
|
||||
|
||||
|
||||
func _show_feed_temporarily() -> void:
|
||||
_stop_feed_animation()
|
||||
_show_feed()
|
||||
feed_timer.start()
|
||||
|
||||
|
||||
func _show_feed() -> void:
|
||||
chat.modulate.a = 1.0
|
||||
chat.show()
|
||||
|
||||
|
||||
func _on_feed_timer_timeout() -> void:
|
||||
if chat_visible:
|
||||
return
|
||||
|
||||
_stop_fade_tween()
|
||||
fade_tween = create_tween()
|
||||
fade_tween.tween_property(chat, "modulate:a", 0.0, FEED_FADE_SECONDS)
|
||||
fade_tween.tween_callback(chat.hide)
|
||||
|
||||
|
||||
func _stop_feed_animation() -> void:
|
||||
feed_timer.stop()
|
||||
_stop_fade_tween()
|
||||
|
||||
|
||||
func _stop_fade_tween() -> void:
|
||||
if fade_tween and fade_tween.is_valid():
|
||||
fade_tween.kill()
|
||||
fade_tween = null
|
||||
|
||||
|
||||
func _escape_bbcode(text: String) -> String:
|
||||
return text.replace("[", "[lb]")
|
||||
|
||||
|
||||
func clear_chat() -> void:
|
||||
_stop_feed_animation()
|
||||
chat_history.clear()
|
||||
chat.clear()
|
||||
chat.modulate.a = 1.0
|
||||
chat.hide()
|
||||
message.text = ""
|
||||
message.release_focus()
|
||||
message.hide()
|
||||
chat_visible = false
|
||||
Reference in New Issue
Block a user