Initial WhaleTown V2 frontend
This commit is contained in:
19
scenes/prefabs/items/DatawhaleHonorBoard.gd
Normal file
19
scenes/prefabs/items/DatawhaleHonorBoard.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
extends Area2D
|
||||
class_name DatawhaleHonorBoard
|
||||
|
||||
const RANKING_PANEL_SCENE: PackedScene = preload("res://scenes/ui/datawhale_honor_ranking_panel.tscn")
|
||||
const RANKING_PANEL_NAME: String = "DatawhaleHonorRankingPanel"
|
||||
const INTERACTION_COLLISION_LAYER: int = 2
|
||||
|
||||
func _ready() -> void:
|
||||
collision_layer = INTERACTION_COLLISION_LAYER
|
||||
collision_mask = 0
|
||||
|
||||
func interact() -> void:
|
||||
var root: Window = get_tree().root
|
||||
if root.has_node(RANKING_PANEL_NAME):
|
||||
return
|
||||
|
||||
var panel := RANKING_PANEL_SCENE.instantiate()
|
||||
panel.name = RANKING_PANEL_NAME
|
||||
root.add_child(panel)
|
||||
1
scenes/prefabs/items/DatawhaleHonorBoard.gd.uid
Normal file
1
scenes/prefabs/items/DatawhaleHonorBoard.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://btaw7myuo7107
|
||||
19
scenes/prefabs/items/NoticeBoard.gd
Normal file
19
scenes/prefabs/items/NoticeBoard.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
extends Area2D
|
||||
class_name NoticeBoard
|
||||
|
||||
const NOTICE_DIALOG_SCENE: PackedScene = preload("res://scenes/ui/notice_dialog.tscn")
|
||||
const NOTICE_DIALOG_NAME: String = "NoticeDialog"
|
||||
const INTERACTION_COLLISION_LAYER: int = 2
|
||||
|
||||
func _ready() -> void:
|
||||
collision_layer = INTERACTION_COLLISION_LAYER
|
||||
collision_mask = 0
|
||||
|
||||
func interact() -> void:
|
||||
var root: Window = get_tree().root
|
||||
if root.has_node(NOTICE_DIALOG_NAME):
|
||||
return
|
||||
|
||||
var dialog := NOTICE_DIALOG_SCENE.instantiate()
|
||||
dialog.name = NOTICE_DIALOG_NAME
|
||||
root.add_child(dialog)
|
||||
1
scenes/prefabs/items/NoticeBoard.gd.uid
Normal file
1
scenes/prefabs/items/NoticeBoard.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bq3mpki50mt01
|
||||
19
scenes/prefabs/items/WelcomeBoard.gd
Normal file
19
scenes/prefabs/items/WelcomeBoard.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
extends Area2D
|
||||
class_name WelcomeBoard
|
||||
|
||||
const WELCOME_DIALOG_SCENE: PackedScene = preload("res://scenes/ui/welcome_dialog.tscn")
|
||||
const WELCOME_DIALOG_NAME: String = "WelcomeDialog"
|
||||
const INTERACTION_COLLISION_LAYER: int = 2
|
||||
|
||||
func _ready() -> void:
|
||||
collision_layer = INTERACTION_COLLISION_LAYER
|
||||
collision_mask = 0
|
||||
|
||||
func interact() -> void:
|
||||
var root: Window = get_tree().root
|
||||
if root.has_node(WELCOME_DIALOG_NAME):
|
||||
return
|
||||
|
||||
var dialog := WELCOME_DIALOG_SCENE.instantiate()
|
||||
dialog.name = WELCOME_DIALOG_NAME
|
||||
root.add_child(dialog)
|
||||
1
scenes/prefabs/items/WelcomeBoard.gd.uid
Normal file
1
scenes/prefabs/items/WelcomeBoard.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c3rnonmmf53u4
|
||||
369
scenes/prefabs/ui/ChatMessage.gd
Normal file
369
scenes/prefabs/ui/ChatMessage.gd
Normal file
@@ -0,0 +1,369 @@
|
||||
extends PanelContainer
|
||||
|
||||
# ============================================================================
|
||||
# ChatMessage.gd - 聊天消息气泡组件
|
||||
# ============================================================================
|
||||
# 显示单条聊天消息的 UI 组件
|
||||
#
|
||||
# 核心职责:
|
||||
# - 显示消息发送者、内容、时间戳
|
||||
# - 区分自己和他人的消息样式
|
||||
# - 自动格式化时间戳
|
||||
#
|
||||
# 使用方式:
|
||||
# var message := chat_message_scene.instantiate()
|
||||
# message.set_message("PlayerName", "Hello!", timestamp, false)
|
||||
#
|
||||
# 注意事项:
|
||||
# - 使用 @onready 缓存节点引用
|
||||
# - 最大宽度限制为 400 像素
|
||||
# ============================================================================
|
||||
|
||||
class_name ChatMessage
|
||||
|
||||
# ============================================================================
|
||||
# 导出参数
|
||||
# ============================================================================
|
||||
|
||||
# 最大宽度(像素)
|
||||
@export var max_width: int = 400
|
||||
|
||||
const MIN_BUBBLE_TEXT_WIDTH: float = 86.0
|
||||
const BUBBLE_HORIZONTAL_MARGIN: float = 28.0
|
||||
const HEADER_GAP_WIDTH: float = 8.0
|
||||
const AVATAR_SIZE: float = 40.0
|
||||
const AVATAR_CORNER_RADIUS: int = 12
|
||||
|
||||
# ============================================================================
|
||||
# 节点引用
|
||||
# ============================================================================
|
||||
|
||||
# 用户名标签
|
||||
var username_label: Label
|
||||
|
||||
# 时间戳标签
|
||||
var timestamp_label: Label
|
||||
|
||||
# 内容标签
|
||||
var content_label: RichTextLabel
|
||||
|
||||
# 用户信息容器
|
||||
var user_info_container: HBoxContainer
|
||||
|
||||
# 头像节点
|
||||
var left_avatar_panel: PanelContainer
|
||||
var right_avatar_panel: PanelContainer
|
||||
var left_avatar_label: Label
|
||||
var right_avatar_label: Label
|
||||
var message_row: HBoxContainer
|
||||
var bubble_panel: PanelContainer
|
||||
var text_container: VBoxContainer
|
||||
|
||||
# ============================================================================
|
||||
# 生命周期方法
|
||||
# ============================================================================
|
||||
|
||||
func _ready() -> void:
|
||||
_cache_node_refs()
|
||||
|
||||
func _cache_node_refs() -> void:
|
||||
if not username_label:
|
||||
username_label = get_node_or_null("MessageRow/BubblePanel/TextContainer/HeaderRow/UsernameLabel")
|
||||
if not timestamp_label:
|
||||
timestamp_label = get_node_or_null("MessageRow/BubblePanel/TextContainer/HeaderRow/TimestampLabel")
|
||||
if not content_label:
|
||||
content_label = get_node_or_null("MessageRow/BubblePanel/TextContainer/ContentLabel")
|
||||
if not user_info_container:
|
||||
user_info_container = get_node_or_null("MessageRow/BubblePanel/TextContainer/HeaderRow")
|
||||
if not left_avatar_panel:
|
||||
left_avatar_panel = get_node_or_null("MessageRow/LeftAvatarPanel")
|
||||
if not right_avatar_panel:
|
||||
right_avatar_panel = get_node_or_null("MessageRow/RightAvatarPanel")
|
||||
if not left_avatar_label:
|
||||
left_avatar_label = get_node_or_null("MessageRow/LeftAvatarPanel/AvatarLabel")
|
||||
if not right_avatar_label:
|
||||
right_avatar_label = get_node_or_null("MessageRow/RightAvatarPanel/AvatarLabel")
|
||||
if not message_row:
|
||||
message_row = get_node_or_null("MessageRow")
|
||||
if not bubble_panel:
|
||||
bubble_panel = get_node_or_null("MessageRow/BubblePanel")
|
||||
if not text_container:
|
||||
text_container = get_node_or_null("MessageRow/BubblePanel/TextContainer")
|
||||
|
||||
_configure_avatar(left_avatar_panel, left_avatar_label)
|
||||
_configure_avatar(right_avatar_panel, right_avatar_label)
|
||||
|
||||
# 内容换行与自适应高度
|
||||
if content_label:
|
||||
content_label.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
content_label.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
content_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
content_label.fit_content = true
|
||||
content_label.scroll_active = false
|
||||
|
||||
# ============================================================================
|
||||
# 成员变量
|
||||
# ============================================================================
|
||||
|
||||
# 是否为自己发送的消息
|
||||
var _is_self: bool = false
|
||||
|
||||
# ============================================================================
|
||||
# 公共 API
|
||||
# ============================================================================
|
||||
|
||||
# 设置消息内容
|
||||
#
|
||||
# 参数:
|
||||
# from_user: String - 发送者用户名
|
||||
# content: String - 消息内容
|
||||
# timestamp: float - Unix 时间戳
|
||||
# is_self: bool - 是否为自己发送的消息(默认 false)
|
||||
#
|
||||
# 使用示例:
|
||||
# message.set_message("Alice", "Hello!", 1703500800.0, false)
|
||||
func set_message(from_user: String, content: String, timestamp: float, is_self: bool = false) -> void:
|
||||
_is_self = is_self
|
||||
_cache_node_refs()
|
||||
|
||||
var safe_from_user := from_user
|
||||
if safe_from_user.strip_edges().is_empty():
|
||||
safe_from_user = "我" if is_self else "玩家"
|
||||
|
||||
# 设置用户名(带空值检查)
|
||||
if username_label:
|
||||
username_label.text = safe_from_user
|
||||
else:
|
||||
push_error("ChatMessage: username_label is null!")
|
||||
return
|
||||
|
||||
var avatar_text := _get_avatar_text(safe_from_user, is_self)
|
||||
if left_avatar_label:
|
||||
left_avatar_label.text = avatar_text
|
||||
if right_avatar_label:
|
||||
right_avatar_label.text = avatar_text
|
||||
|
||||
# 设置内容
|
||||
if content_label:
|
||||
content_label.clear() # 清除默认文本和所有内容
|
||||
content_label.append_text(content) # 作为纯文本追加,避免 BBCode 解析导致内容不显示
|
||||
else:
|
||||
push_error("ChatMessage: content_label is null!")
|
||||
return
|
||||
|
||||
# 设置时间戳
|
||||
if timestamp_label:
|
||||
timestamp_label.text = _format_timestamp(timestamp)
|
||||
else:
|
||||
push_error("ChatMessage: timestamp_label is null!")
|
||||
return
|
||||
|
||||
_update_bubble_width(safe_from_user, content)
|
||||
|
||||
# 应用样式
|
||||
_apply_style()
|
||||
|
||||
# ============================================================================
|
||||
# 内部方法 - 样式处理
|
||||
# ============================================================================
|
||||
|
||||
# 应用样式(自己和他人的消息不同)
|
||||
func _apply_style() -> void:
|
||||
if not username_label or not timestamp_label or not user_info_container:
|
||||
return
|
||||
|
||||
# 重要:设置垂直 size flags 让 Panel 适应内容高度
|
||||
size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
|
||||
if _is_self:
|
||||
if message_row:
|
||||
message_row.alignment = BoxContainer.ALIGNMENT_END
|
||||
user_info_container.alignment = BoxContainer.ALIGNMENT_END
|
||||
_set_avatar_side(true)
|
||||
|
||||
# 设置面板样式
|
||||
if bubble_panel:
|
||||
bubble_panel.add_theme_stylebox_override("panel", _get_self_style())
|
||||
if right_avatar_panel:
|
||||
right_avatar_panel.add_theme_stylebox_override("panel", _get_avatar_style(true))
|
||||
_apply_selected_avatar(right_avatar_panel, right_avatar_label, username_label.text)
|
||||
|
||||
# 设置文字颜色 - ID使用金色 #FFD700
|
||||
username_label.add_theme_color_override("font_color", Color(0.258824, 0.627451, 0.913725))
|
||||
timestamp_label.add_theme_color_override("font_color", Color(0.560784, 0.639216, 0.733333))
|
||||
if right_avatar_label:
|
||||
right_avatar_label.add_theme_color_override("font_color", Color(1, 1, 1))
|
||||
if content_label:
|
||||
content_label.add_theme_color_override("default_color", Color(0.188, 0.294, 0.424))
|
||||
else:
|
||||
if message_row:
|
||||
message_row.alignment = BoxContainer.ALIGNMENT_BEGIN
|
||||
user_info_container.alignment = BoxContainer.ALIGNMENT_BEGIN
|
||||
_set_avatar_side(false)
|
||||
|
||||
# 设置面板样式
|
||||
if bubble_panel:
|
||||
bubble_panel.add_theme_stylebox_override("panel", _get_other_style())
|
||||
if left_avatar_panel:
|
||||
left_avatar_panel.add_theme_stylebox_override("panel", _get_avatar_style(false))
|
||||
|
||||
# 设置文字颜色 - ID使用蓝色 #69c0ff
|
||||
username_label.add_theme_color_override("font_color", Color(0.207843, 0.427451, 0.686275))
|
||||
timestamp_label.add_theme_color_override("font_color", Color(0.560784, 0.639216, 0.733333))
|
||||
if left_avatar_label:
|
||||
left_avatar_label.add_theme_color_override("font_color", Color(1, 1, 1))
|
||||
if content_label:
|
||||
content_label.add_theme_color_override("default_color", Color(0.27451, 0.407843, 0.541176))
|
||||
|
||||
func _set_avatar_side(is_self: bool) -> void:
|
||||
if left_avatar_panel:
|
||||
left_avatar_panel.visible = not is_self
|
||||
if right_avatar_panel:
|
||||
right_avatar_panel.visible = is_self
|
||||
|
||||
func _configure_avatar(panel: PanelContainer, label: Label) -> void:
|
||||
if panel:
|
||||
panel.custom_minimum_size = Vector2(AVATAR_SIZE, AVATAR_SIZE)
|
||||
panel.size = Vector2(AVATAR_SIZE, AVATAR_SIZE)
|
||||
panel.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
panel.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
panel.clip_contents = true
|
||||
if label:
|
||||
label.custom_minimum_size = Vector2(AVATAR_SIZE, AVATAR_SIZE)
|
||||
label.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
label.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
|
||||
func _update_bubble_width(from_user: String, content: String) -> void:
|
||||
var maxTextWidth := float(max_width) - BUBBLE_HORIZONTAL_MARGIN
|
||||
var contentWidth := _measure_label_text_width(content_label, content, 14.0)
|
||||
var headerWidth := _measure_label_text_width(username_label, from_user, 16.0) + _measure_label_text_width(timestamp_label, timestamp_label.text, 13.0) + HEADER_GAP_WIDTH
|
||||
var textWidth: float = clamp(max(contentWidth, headerWidth, MIN_BUBBLE_TEXT_WIDTH), MIN_BUBBLE_TEXT_WIDTH, maxTextWidth)
|
||||
|
||||
if username_label:
|
||||
username_label.custom_minimum_size.x = min(_measure_label_text_width(username_label, from_user, 16.0), textWidth)
|
||||
if timestamp_label:
|
||||
timestamp_label.custom_minimum_size.x = _measure_label_text_width(timestamp_label, timestamp_label.text, 13.0)
|
||||
if content_label:
|
||||
content_label.custom_minimum_size.x = textWidth
|
||||
if bubble_panel:
|
||||
bubble_panel.custom_minimum_size.x = textWidth + BUBBLE_HORIZONTAL_MARGIN
|
||||
|
||||
func _measure_label_text_width(label: Control, text: String, fallback_width: float) -> float:
|
||||
if label != null:
|
||||
var font := label.get_theme_font("font")
|
||||
if font != null:
|
||||
var fontSize := label.get_theme_font_size("font_size")
|
||||
if fontSize <= 0:
|
||||
fontSize = int(fallback_width)
|
||||
var measured := font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1.0, fontSize).x
|
||||
if measured > 0.0:
|
||||
return measured + 2.0
|
||||
|
||||
var width := 0.0
|
||||
for index in range(text.length()):
|
||||
var code := text.unicode_at(index)
|
||||
if code <= 0x7f:
|
||||
width += fallback_width * 0.58
|
||||
else:
|
||||
width += fallback_width
|
||||
return width + 2.0
|
||||
|
||||
# 获取自己消息的样式
|
||||
func _get_self_style() -> StyleBoxFlat:
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.878431, 0.94902, 1.0, 0.96)
|
||||
style.border_width_left = 1
|
||||
style.border_width_top = 1
|
||||
style.border_width_right = 1
|
||||
style.border_width_bottom = 1
|
||||
style.border_color = Color(0.64, 0.82, 0.95, 0.78)
|
||||
style.corner_radius_top_left = 14
|
||||
style.corner_radius_top_right = 8
|
||||
style.corner_radius_bottom_left = 14
|
||||
style.corner_radius_bottom_right = 14
|
||||
style.content_margin_left = 14
|
||||
style.content_margin_right = 14
|
||||
style.content_margin_top = 9
|
||||
style.content_margin_bottom = 9
|
||||
return style
|
||||
|
||||
# 获取他人消息的样式
|
||||
func _get_other_style() -> StyleBoxFlat:
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color(1, 1, 1, 0.96)
|
||||
style.border_width_left = 1
|
||||
style.border_width_top = 1
|
||||
style.border_width_right = 1
|
||||
style.border_width_bottom = 1
|
||||
style.border_color = Color(0.78, 0.85, 0.92, 0.72)
|
||||
style.corner_radius_top_left = 8
|
||||
style.corner_radius_top_right = 14
|
||||
style.corner_radius_bottom_left = 14
|
||||
style.corner_radius_bottom_right = 14
|
||||
style.content_margin_left = 14
|
||||
style.content_margin_right = 14
|
||||
style.content_margin_top = 9
|
||||
style.content_margin_bottom = 9
|
||||
return style
|
||||
|
||||
func _get_avatar_style(is_self: bool) -> StyleBoxFlat:
|
||||
if is_self:
|
||||
var appearanceManager := get_node_or_null("/root/AppearanceManager")
|
||||
if appearanceManager != null and appearanceManager.has_method("create_avatar_style") and appearanceManager.has_method("get_selected_avatar"):
|
||||
var avatar: Variant = appearanceManager.call("get_selected_avatar")
|
||||
if avatar is Dictionary:
|
||||
return appearanceManager.call("create_avatar_style", avatar as Dictionary, AVATAR_CORNER_RADIUS)
|
||||
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.361, 0.690, 0.914) if is_self else Color(0.62, 0.75, 0.86)
|
||||
style.corner_radius_top_left = AVATAR_CORNER_RADIUS
|
||||
style.corner_radius_top_right = AVATAR_CORNER_RADIUS
|
||||
style.corner_radius_bottom_left = AVATAR_CORNER_RADIUS
|
||||
style.corner_radius_bottom_right = AVATAR_CORNER_RADIUS
|
||||
style.border_width_left = 1
|
||||
style.border_width_top = 1
|
||||
style.border_width_right = 1
|
||||
style.border_width_bottom = 1
|
||||
style.border_color = Color(1, 1, 1, 0.82)
|
||||
return style
|
||||
|
||||
func _get_avatar_text(from_user: String, is_self: bool) -> String:
|
||||
if is_self:
|
||||
var appearanceManager := get_node_or_null("/root/AppearanceManager")
|
||||
if appearanceManager != null and appearanceManager.has_method("has_custom_avatar") and bool(appearanceManager.call("has_custom_avatar")):
|
||||
return ""
|
||||
if appearanceManager != null and appearanceManager.has_method("get_avatar_label"):
|
||||
return str(appearanceManager.call("get_avatar_label"))
|
||||
return "我"
|
||||
var trimmed := from_user.strip_edges()
|
||||
if trimmed.is_empty():
|
||||
return "鲸"
|
||||
return trimmed.substr(0, 1)
|
||||
|
||||
func _apply_selected_avatar(panel: PanelContainer, label: Label, fallbackText: String) -> void:
|
||||
var appearanceManager := get_node_or_null("/root/AppearanceManager")
|
||||
if appearanceManager != null and appearanceManager.has_method("apply_avatar_to_panel"):
|
||||
appearanceManager.call("apply_avatar_to_panel", panel, label, "", fallbackText)
|
||||
|
||||
# ============================================================================
|
||||
# 内部方法 - 工具函数
|
||||
# ============================================================================
|
||||
|
||||
# 格式化时间戳
|
||||
#
|
||||
# 参数:
|
||||
# timestamp: float - Unix 时间戳
|
||||
#
|
||||
# 返回值:
|
||||
# String - 格式化的时间字符串
|
||||
func _format_timestamp(timestamp: float) -> String:
|
||||
if timestamp == 0:
|
||||
return ""
|
||||
|
||||
var datetime := Time.get_datetime_dict_from_unix_time(timestamp)
|
||||
|
||||
# 格式化为 HH:MM
|
||||
return "%02d:%02d" % [datetime.hour, datetime.minute]
|
||||
1
scenes/prefabs/ui/ChatMessage.gd.uid
Normal file
1
scenes/prefabs/ui/ChatMessage.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cyftwn8xuo8so
|
||||
82
scenes/prefabs/ui/ChatMessage.tscn
Normal file
82
scenes/prefabs/ui/ChatMessage.tscn
Normal file
@@ -0,0 +1,82 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dqx8k3n8yqjvu"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/prefabs/ui/ChatMessage.gd" id="1"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_panel"]
|
||||
|
||||
[node name="ChatMessage" type="PanelContainer"]
|
||||
custom_minimum_size = Vector2(0, 58)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
script = ExtResource("1")
|
||||
theme_override_styles/panel = SubResource("StyleBoxEmpty_panel")
|
||||
|
||||
[node name="MessageRow" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
alignment = 0
|
||||
|
||||
[node name="LeftAvatarPanel" type="PanelContainer" parent="MessageRow"]
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="AvatarLabel" type="Label" parent="MessageRow/LeftAvatarPanel"]
|
||||
layout_mode = 2
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "鲸"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="BubblePanel" type="PanelContainer" parent="MessageRow"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
|
||||
[node name="TextContainer" type="VBoxContainer" parent="MessageRow/BubblePanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 2
|
||||
|
||||
[node name="HeaderRow" type="HBoxContainer" parent="MessageRow/BubblePanel/TextContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="UsernameLabel" type="Label" parent="MessageRow/BubblePanel/TextContainer/HeaderRow"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(0.207843, 0.427451, 0.686275, 1)
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "鲸鱼居民"
|
||||
text_overrun_behavior = 3
|
||||
|
||||
[node name="TimestampLabel" type="Label" parent="MessageRow/BubblePanel/TextContainer/HeaderRow"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.560784, 0.639216, 0.733333, 1)
|
||||
theme_override_font_sizes/font_size = 13
|
||||
text = "12:34"
|
||||
|
||||
[node name="ContentLabel" type="RichTextLabel" parent="MessageRow/BubblePanel/TextContainer"]
|
||||
custom_minimum_size = Vector2(0, 26)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
fit_content = true
|
||||
scroll_active = false
|
||||
autowrap_mode = 3
|
||||
bbcode_enabled = false
|
||||
theme_override_colors/default_color = Color(0.388235, 0.478431, 0.584314, 1)
|
||||
theme_override_font_sizes/normal_font_size = 14
|
||||
|
||||
[node name="RightAvatarPanel" type="PanelContainer" parent="MessageRow"]
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="AvatarLabel" type="Label" parent="MessageRow/RightAvatarPanel"]
|
||||
layout_mode = 2
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "我"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
Reference in New Issue
Block a user