init
This commit is contained in:
9
Scripts/UI/ChatBubble.gd
Normal file
9
Scripts/UI/ChatBubble.gd
Normal file
@@ -0,0 +1,9 @@
|
||||
extends Control
|
||||
|
||||
@onready var label = $PanelContainer/Label
|
||||
|
||||
func set_text(text):
|
||||
label.text = text
|
||||
# Destroy after 5 seconds
|
||||
await get_tree().create_timer(5.0).timeout
|
||||
queue_free()
|
||||
1
Scripts/UI/ChatBubble.gd.uid
Normal file
1
Scripts/UI/ChatBubble.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bpddnrpvlcf7l
|
||||
71
Scripts/UI/ChatHUD.gd
Normal file
71
Scripts/UI/ChatHUD.gd
Normal file
@@ -0,0 +1,71 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var chat_log = $PanelContainer/VBoxContainer/RichTextLabel
|
||||
@onready var input_field = $PanelContainer/VBoxContainer/LineEdit
|
||||
|
||||
var private_target_id: int = -1
|
||||
var private_target_name: String = ""
|
||||
|
||||
func _ready():
|
||||
NetworkManager.chat_message_received.connect(_on_chat_message_received)
|
||||
NetworkManager.private_chat_message_received.connect(_on_private_message_received)
|
||||
input_field.text_submitted.connect(_on_text_submitted)
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("ui_cancel"): # ESC
|
||||
set_private_target(-1, "")
|
||||
input_field.release_focus()
|
||||
elif event.is_action_pressed("ui_accept"): # Enter
|
||||
if not input_field.has_focus():
|
||||
input_field.grab_focus()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func set_private_target(id: int, p_name: String):
|
||||
private_target_id = id
|
||||
private_target_name = p_name
|
||||
|
||||
if id != -1:
|
||||
input_field.placeholder_text = "[Private] To " + p_name + "..."
|
||||
input_field.add_theme_color_override("font_color", Color(1, 0.5, 1)) # Pink for private
|
||||
# input_field.grab_focus() # Don't grab focus automatically, let user move
|
||||
else:
|
||||
input_field.placeholder_text = "Press Enter to chat..."
|
||||
input_field.remove_theme_color_override("font_color")
|
||||
|
||||
func _on_text_submitted(new_text):
|
||||
if new_text.strip_edges().is_empty():
|
||||
input_field.release_focus()
|
||||
return
|
||||
|
||||
if private_target_id != -1:
|
||||
NetworkManager.send_private_message(private_target_id, new_text)
|
||||
# Show my own private message in log
|
||||
chat_log.append_text("[color=#FF88FF][Private -> %s]: %s[/color]\n" % [private_target_name, new_text])
|
||||
else:
|
||||
NetworkManager.send_message(new_text)
|
||||
|
||||
input_field.clear()
|
||||
input_field.release_focus()
|
||||
|
||||
func _on_chat_message_received(sender_id, text):
|
||||
var sender_name = str(sender_id)
|
||||
|
||||
print("Chat Debug: Msg from ", sender_id, " (Type: ", typeof(sender_id), ")")
|
||||
print("Known Players: ", NetworkManager.players.keys())
|
||||
|
||||
if NetworkManager.players.has(sender_id):
|
||||
sender_name = NetworkManager.players[sender_id].get("name", str(sender_id))
|
||||
# Debug empty name
|
||||
if sender_name == "":
|
||||
sender_name = "Player_" + str(sender_id)
|
||||
else:
|
||||
print("Chat Debug: Player ID not found in NetworkManager.players")
|
||||
|
||||
chat_log.append_text("[color=yellow]%s[/color]: %s\n" % [sender_name, text])
|
||||
|
||||
func _on_private_message_received(sender_id, text):
|
||||
var sender_name = str(sender_id)
|
||||
if NetworkManager.players.has(sender_id):
|
||||
sender_name = NetworkManager.players[sender_id].get("name", str(sender_id))
|
||||
|
||||
chat_log.append_text("[color=#FF88FF][Private From %s]: %s[/color]\n" % [sender_name, text])
|
||||
1
Scripts/UI/ChatHUD.gd.uid
Normal file
1
Scripts/UI/ChatHUD.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dia2n8udb7xxq
|
||||
144
Scripts/UI/NoticeDialog.gd
Normal file
144
Scripts/UI/NoticeDialog.gd
Normal file
@@ -0,0 +1,144 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var content_label = $CenterContainer/PanelContainer/VBoxContainer/ContentContainer/TextPanel/ContentLabel
|
||||
@onready var prev_btn = $CenterContainer/PanelContainer/VBoxContainer/Footer/PrevButton
|
||||
@onready var next_btn = $CenterContainer/PanelContainer/VBoxContainer/Footer/NextButton
|
||||
@onready var dots_container = $CenterContainer/PanelContainer/VBoxContainer/Footer/DotsContainer
|
||||
@onready var content_container = $CenterContainer/PanelContainer/VBoxContainer/ContentContainer
|
||||
|
||||
# Mock Data
|
||||
var pages = [
|
||||
{
|
||||
"text": "欢迎来到 [color=#3399ff]Datawhale Town[/color]!\n\n这里是开源学习者的家园。在这里,我们一同探索知识,分享成长。\n\n[center]🐋[/center]",
|
||||
"image_color": Color(0.9, 0.9, 0.9) # Mock image placeholder
|
||||
},
|
||||
{
|
||||
"text": "最新活动:\n\n- 镇长刚刚搬进来了,就在喷泉左边。\n- 欢迎板已经设立,查看最新动态。\n- 玩家名字现在显示在头顶了!",
|
||||
"image_color": Color(0.8, 0.9, 0.8)
|
||||
},
|
||||
{
|
||||
"text": "操作提示:\n\n- 按 [color=#ffaa00]F[/color] 键可以与物体互动。\n- 在下方输入框输入文字并在气泡中显示。\n- 点击右下角按钮发送聊天。",
|
||||
"image_color": Color(0.9, 0.8, 0.8)
|
||||
}
|
||||
]
|
||||
|
||||
var current_page = 0
|
||||
var tween: Tween
|
||||
|
||||
func _ready():
|
||||
# Pause the game
|
||||
get_tree().paused = true
|
||||
|
||||
$CenterContainer/PanelContainer/VBoxContainer/Header/RightContainer/CloseButton.pressed.connect(_on_close_pressed)
|
||||
prev_btn.pressed.connect(_on_prev_pressed)
|
||||
next_btn.pressed.connect(_on_next_pressed)
|
||||
|
||||
# Network Integration
|
||||
NetworkManager.notices_received.connect(_on_notices_received)
|
||||
NetworkManager.request_notices()
|
||||
|
||||
# Initial Setup (with generic "Loading" state)
|
||||
pages = [{"text": "[center]Loading notices...[/center]", "image_color": Color(0.9, 0.9, 0.9)}]
|
||||
_setup_dots()
|
||||
_update_ui(false)
|
||||
|
||||
func _on_notices_received(data: Array):
|
||||
if data.is_empty():
|
||||
pages = [{"text": "[center]No notices available.[/center]", "image_color": Color(0.9, 0.9, 0.9)}]
|
||||
else:
|
||||
pages = data
|
||||
# Handle color strings from JSON if necessary
|
||||
for p in pages:
|
||||
if p.has("image_color") and p["image_color"] is String:
|
||||
p["image_color"] = Color(p["image_color"])
|
||||
|
||||
current_page = 0
|
||||
_setup_dots()
|
||||
_update_ui(true)
|
||||
|
||||
|
||||
func _setup_dots():
|
||||
for child in dots_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
for i in range(pages.size()):
|
||||
var dot = ColorRect.new()
|
||||
dot.custom_minimum_size = Vector2(10, 10) # Base size
|
||||
dots_container.add_child(dot)
|
||||
|
||||
func _update_ui(animate: bool = true):
|
||||
if pages.is_empty():
|
||||
return
|
||||
|
||||
# Update Buttons
|
||||
prev_btn.disabled = (current_page == 0)
|
||||
next_btn.disabled = (current_page == pages.size() - 1)
|
||||
|
||||
# Update Dots Logic
|
||||
var dots = dots_container.get_children()
|
||||
for i in range(dots.size()):
|
||||
if i == current_page:
|
||||
dots[i].color = Color(0.2, 0.2, 0.2, 1) # Dark Active
|
||||
dots[i].custom_minimum_size = Vector2(12, 12) # Active Slightly Larger
|
||||
else:
|
||||
dots[i].color = Color(0.8, 0.8, 0.8, 1) # Light Inactive
|
||||
dots[i].custom_minimum_size = Vector2(10, 10)
|
||||
|
||||
# Update Content
|
||||
if animate:
|
||||
_animate_content_change()
|
||||
else:
|
||||
_set_content_immediate()
|
||||
|
||||
@onready var image_rect = $CenterContainer/PanelContainer/VBoxContainer/ContentContainer/ImagePanel/ImageRect
|
||||
@onready var image_label = $CenterContainer/PanelContainer/VBoxContainer/ContentContainer/ImagePanel/ImageLabel
|
||||
|
||||
func _set_content_immediate():
|
||||
var page = pages[current_page]
|
||||
content_label.text = page.get("text", "")
|
||||
|
||||
if page.has("image_path") and page["image_path"] != "":
|
||||
var path = page["image_path"]
|
||||
if ResourceLoader.exists(path):
|
||||
image_rect.texture = load(path)
|
||||
image_label.visible = false
|
||||
else:
|
||||
image_rect.texture = null
|
||||
image_label.visible = true
|
||||
image_label.text = "Image Not Found"
|
||||
else:
|
||||
image_rect.texture = null
|
||||
image_label.visible = true
|
||||
image_label.text = "No Image"
|
||||
|
||||
|
||||
|
||||
func _animate_content_change():
|
||||
if tween and tween.is_valid():
|
||||
tween.kill()
|
||||
|
||||
tween = create_tween()
|
||||
|
||||
# Fade Out
|
||||
tween.tween_property(content_container, "modulate:a", 0.0, 0.15)
|
||||
|
||||
# Callback to change text
|
||||
tween.tween_callback(self._set_content_immediate)
|
||||
|
||||
# Fade In
|
||||
tween.tween_property(content_container, "modulate:a", 1.0, 0.15)
|
||||
|
||||
func _on_prev_pressed():
|
||||
if current_page > 0:
|
||||
current_page -= 1
|
||||
_update_ui()
|
||||
|
||||
func _on_next_pressed():
|
||||
if current_page < pages.size() - 1:
|
||||
current_page += 1
|
||||
_update_ui()
|
||||
|
||||
func _on_close_pressed():
|
||||
# Unpause the game
|
||||
get_tree().paused = false
|
||||
queue_free()
|
||||
1
Scripts/UI/NoticeDialog.gd.uid
Normal file
1
Scripts/UI/NoticeDialog.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cy3n8ccmeolgd
|
||||
20
Scripts/UI/WelcomeDialog.gd
Normal file
20
Scripts/UI/WelcomeDialog.gd
Normal file
@@ -0,0 +1,20 @@
|
||||
extends CanvasLayer
|
||||
|
||||
func _ready():
|
||||
# Connect close button (X)
|
||||
var header_close = find_child("CloseButton", true, false)
|
||||
if header_close:
|
||||
header_close.pressed.connect(_on_close_pressed)
|
||||
|
||||
# Connect Start button
|
||||
var start_btn = find_child("StartButton", true, false)
|
||||
if start_btn:
|
||||
start_btn.pressed.connect(_on_close_pressed)
|
||||
|
||||
func _on_close_pressed():
|
||||
queue_free()
|
||||
|
||||
func _input(event):
|
||||
# Allow ESC to close
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
queue_free()
|
||||
1
Scripts/UI/WelcomeDialog.gd.uid
Normal file
1
Scripts/UI/WelcomeDialog.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://djjy58mh6kl4o
|
||||
Reference in New Issue
Block a user