feat: update 2.1.9

This commit is contained in:
2026-04-29 01:36:49 +08:00
parent 1585b91509
commit 8a2f865ad8
76 changed files with 2628 additions and 39 deletions
+121
View File
@@ -93,8 +93,16 @@ var doors_goals_option: OptionButton
@onready var leave_btn = $LobbyPanel/BottomBar/LeaveBtn
@onready var ready_btn = $LobbyPanel/BottomBar/ReadyBtn
@onready var start_game_btn = $LobbyPanel/BottomBar/StartGameBtn
var invite_btn: Button
@onready var status_label = $LobbyPanel/StatusLabel
# Social Panel instance
var social_panel_instance: Control
# Lobby invite popup
var _invite_popup: AcceptDialog
var _pending_invite_match_id: String = ""
# UI References - Status
@onready var connection_status = $StatusBar/ConnectionStatus
@@ -175,6 +183,11 @@ func _ready():
if quit_btn:
quit_btn.pressed.connect(_on_quit_pressed)
# Social button (main menu) - connect if node exists
var social_btn = get_node_or_null("%SocialBtn")
if social_btn:
social_btn.pressed.connect(_on_social_pressed)
# Connect Server Selection signals
if server_option:
server_option.item_selected.connect(_on_server_option_selected)
@@ -258,6 +271,12 @@ func _ready():
if chat_input:
chat_input.text_submitted.connect(func(_t): _on_chat_send_pressed())
# Connect Social / Friend UI
invite_btn = get_node_or_null("LobbyPanel/BottomBar/InviteBtn")
if invite_btn:
invite_btn.pressed.connect(_on_invite_friends_pressed)
FriendManager.lobby_invite_received.connect(_on_lobby_invite_received)
# Set initial title if already loaded
_on_profile_updated()
@@ -1075,6 +1094,24 @@ func _update_player_slots() -> void:
ready_label.text = "READY ✓" if is_ready else "NOT READY"
ready_label.add_theme_color_override("font_color",
Color(0.4, 0.8, 0.4) if is_ready else Color(0.6, 0.6, 0.6))
# + Friend button — node must exist in lobby.tscn as "AddFriendBtn1", "AddFriendBtn2"...
var player_nakama_id: String = player.get("nakama_id", "")
var my_nakama_id: String = NakamaManager.session.user_id if NakamaManager.session else ""
var add_friend_btn: Button = slot.get_node_or_null("AddFriendBtn%d" % slot_num)
if add_friend_btn:
if player_nakama_id.is_empty() or player_nakama_id == my_nakama_id:
add_friend_btn.visible = false
else:
add_friend_btn.visible = true
if FriendManager.is_friend(player_nakama_id):
add_friend_btn.text = "Friend ✓"
add_friend_btn.disabled = true
else:
add_friend_btn.text = "+ Friend"
add_friend_btn.disabled = false
if not add_friend_btn.pressed.is_connected(func(): _on_add_friend_pressed(player_nakama_id)):
add_friend_btn.pressed.connect(func(): _on_add_friend_pressed(player_nakama_id))
else:
# Empty slot - show as bot placeholder
slot.visible = true
@@ -1112,6 +1149,11 @@ func _update_player_slots() -> void:
if ready_label:
ready_label.text = "WAITING..."
ready_label.add_theme_color_override("font_color", Color(0.5, 0.5, 0.7))
# Hide friend button for bots/empty slots
var add_friend_btn: Button = slot.get_node_or_null("AddFriendBtn%d" % slot_num)
if add_friend_btn:
add_friend_btn.visible = false
_update_status()
@@ -1158,6 +1200,85 @@ func _apply_loadout_character() -> void:
print("[Lobby] Loadout character applied: ", saved_char)
# =============================================================================
# Social / Friend Functions
# =============================================================================
func _on_add_friend_pressed(nakama_id: String) -> void:
var ok = await FriendManager.add_friend_by_id(nakama_id)
if ok:
_update_player_slots()
func _on_invite_friends_pressed() -> void:
"""Open the invite friends dialog (scene-based)."""
var match_id = current_match_id
if match_id.is_empty():
return
var friends = FriendManager.get_mutual_friends()
var scene = load("res://scenes/ui/invite_friends_dialog.tscn") as PackedScene
if not scene:
return
var dialog = scene.instantiate()
add_child(dialog)
dialog.open(friends, match_id)
dialog.closed.connect(dialog.queue_free)
func _on_lobby_invite_received(from_user_id: String, from_name: String, match_id: String) -> void:
"""Show invite notification popup. Only shown if not already in a game."""
if get_tree().current_scene.scene_file_path != "res://scenes/lobby.tscn":
return
if lobby_panel and lobby_panel.visible:
return
if _invite_popup:
_invite_popup.queue_free()
_pending_invite_match_id = match_id
var scene = load("res://scenes/ui/lobby_invite_popup.tscn") as PackedScene
if scene:
_invite_popup = scene.instantiate()
add_child(_invite_popup)
_invite_popup.setup(from_name)
_invite_popup.accepted.connect(_on_invite_accepted)
_invite_popup.declined.connect(func(): _invite_popup.queue_free())
_invite_popup.popup_centered()
else:
# Fallback if scene not yet added to project
var dlg := AcceptDialog.new()
dlg.title = "Lobby Invitation"
dlg.dialog_text = "%s invited you!\nJoin?" % from_name
dlg.ok_button_text = "Join"
dlg.add_cancel_button("Decline")
add_child(dlg)
dlg.confirmed.connect(_on_invite_accepted)
dlg.canceled.connect(dlg.queue_free)
dlg.popup_centered()
_invite_popup = dlg
func _on_invite_accepted() -> void:
if not _pending_invite_match_id.is_empty():
LobbyManager.join_room(_pending_invite_match_id)
if _invite_popup:
_invite_popup.queue_free()
_pending_invite_match_id = ""
func _on_social_pressed() -> void:
"""Open social / friend list panel."""
if not social_panel_instance:
var scene = load("res://scenes/ui/social_panel.tscn")
if scene:
social_panel_instance = scene.instantiate()
social_panel_instance.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
add_child(social_panel_instance)
if social_panel_instance.has_signal("closed"):
social_panel_instance.closed.connect(func():
social_panel_instance.hide()
if main_menu_panel: main_menu_panel.show()
)
if social_panel_instance:
if main_menu_panel: main_menu_panel.hide()
social_panel_instance.show()
# =============================================================================
# Global Chat System
# =============================================================================
+63 -1
View File
@@ -403,7 +403,6 @@ unique_name_in_owner = true
custom_minimum_size = Vector2(44, 44)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
disabled = true
text = "SOCIAL"
[node name="SettingsBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/TopRightPanel" unique_id=90]
@@ -967,6 +966,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn1" type="Button" parent="LobbyPanel/PlayersContainer/PlayerSlot1" unique_id=10000001]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayerSlot2" type="VBoxContainer" parent="LobbyPanel/PlayersContainer" unique_id=1012954493]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
@@ -1031,6 +1037,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn2" type="Button" parent="LobbyPanel/PlayersContainer/PlayerSlot2" unique_id=10000002]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayerSlot3" type="VBoxContainer" parent="LobbyPanel/PlayersContainer" unique_id=1033758492]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
@@ -1095,6 +1108,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn3" type="Button" parent="LobbyPanel/PlayersContainer/PlayerSlot3" unique_id=10000003]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayerSlot4" type="VBoxContainer" parent="LobbyPanel/PlayersContainer" unique_id=62963750]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
@@ -1159,6 +1179,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn4" type="Button" parent="LobbyPanel/PlayersContainer/PlayerSlot4" unique_id=10000004]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayersContainer2" type="HBoxContainer" parent="LobbyPanel" unique_id=76585227]
layout_mode = 1
anchors_preset = 3
@@ -1237,6 +1264,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn5" type="Button" parent="LobbyPanel/PlayersContainer2/PlayerSlot5" unique_id=10000006]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayerSlot6" type="VBoxContainer" parent="LobbyPanel/PlayersContainer2" unique_id=1038068961]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
@@ -1301,6 +1335,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn6" type="Button" parent="LobbyPanel/PlayersContainer2/PlayerSlot6" unique_id=10000007]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayerSlot7" type="VBoxContainer" parent="LobbyPanel/PlayersContainer2" unique_id=1161417031]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
@@ -1365,6 +1406,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn7" type="Button" parent="LobbyPanel/PlayersContainer2/PlayerSlot7" unique_id=10000008]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="PlayerSlot8" type="VBoxContainer" parent="LobbyPanel/PlayersContainer2" unique_id=2019344700]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
@@ -1429,6 +1477,13 @@ theme_override_font_sizes/font_size = 14
text = "NOT READY"
horizontal_alignment = 1
[node name="AddFriendBtn8" type="Button" parent="LobbyPanel/PlayersContainer2/PlayerSlot8" unique_id=10000009]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 12
text = "+ Friend"
[node name="AreaSelector" type="HBoxContainer" parent="LobbyPanel" unique_id=696178336]
clip_contents = true
layout_mode = 1
@@ -1498,6 +1553,13 @@ text = "LEAVE"
layout_mode = 2
size_flags_horizontal = 3
[node name="InviteBtn" type="Button" parent="LobbyPanel/BottomBar" unique_id=10000005]
custom_minimum_size = Vector2(120, 44)
layout_mode = 2
theme_override_fonts/font = ExtResource("5_pc087")
theme_override_font_sizes/font_size = 18
text = "INVITE FRIENDS"
[node name="ReadyBtn" type="Button" parent="LobbyPanel/BottomBar" unique_id=2026272478]
custom_minimum_size = Vector2(140, 50)
layout_mode = 2
+40
View File
@@ -0,0 +1,40 @@
[gd_scene format=3 uid="uid://dqfriend001"]
[ext_resource type="Script" path="res://scripts/ui/friend_row.gd" id="1_frow"]
[node name="FriendRow" type="HBoxContainer"]
script = ExtResource("1_frow")
[node name="NameLabel" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="StateLabel" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 2
visible = false
[node name="DMBtn" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
text = "Chat"
visible = false
[node name="AcceptBtn" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
text = "Accept"
visible = false
[node name="DeclineBtn" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
text = "Decline"
visible = false
[node name="RemoveBtn" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
text = "Remove"
visible = false
+43
View File
@@ -0,0 +1,43 @@
[gd_scene format=3 uid="uid://dqinvite001"]
[ext_resource type="Script" path="res://scripts/ui/invite_friends_dialog.gd" id="1_inv"]
[node name="InviteFriendsDialog" type="Window"]
title = "Invite Friends to Lobby"
size = Vector2i(360, 420)
script = ExtResource("1_inv")
[node name="VBox" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 8.0
offset_top = 8.0
offset_right = -8.0
offset_bottom = -8.0
[node name="TitleLabel" type="Label" parent="VBox"]
layout_mode = 2
text = "Select a friend to invite:"
[node name="FriendScroll" type="ScrollContainer" parent="VBox"]
layout_mode = 2
size_flags_vertical = 3
custom_minimum_size = Vector2(0, 300)
[node name="FriendRows" type="VBoxContainer" parent="VBox/FriendScroll"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="NoFriendsLabel" type="Label" parent="VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "No friends to invite yet.\nAdd friends from the Social panel!"
visible = false
[node name="CloseBtn" type="Button" parent="VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Close"
+16
View File
@@ -0,0 +1,16 @@
[gd_scene format=3 uid="uid://dqinvrow01"]
[ext_resource type="Script" path="res://scripts/ui/invite_row.gd" id="1_irow"]
[node name="InviteRow" type="HBoxContainer"]
script = ExtResource("1_irow")
[node name="NameLabel" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="InviteBtn" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
text = "Invite"
+19
View File
@@ -0,0 +1,19 @@
[gd_scene format=3 uid="uid://dqlobinv01"]
[ext_resource type="Script" path="res://scripts/ui/lobby_invite_popup.gd" id="1_lip"]
[node name="LobbyInvitePopup" type="ConfirmationDialog"]
title = "Lobby Invitation"
ok_button_text = "Join"
script = ExtResource("1_lip")
[node name="VBox" type="VBoxContainer" parent="."]
layout_mode = 0
offset_right = 280.0
offset_bottom = 80.0
[node name="MessageLabel" type="Label" parent="VBox"]
unique_name_in_owner = true
layout_mode = 2
text = "Someone invited you to their lobby!"
autowrap_mode = 3
+9 -2
View File
@@ -186,36 +186,43 @@ layout_mode = 2
text = "Sign In"
[node name="SocialLabel" type="Label" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox" unique_id=840440943]
visible = false
layout_mode = 2
theme_override_colors/font_color = Color(0.69, 0.529, 0.357, 1)
text = "─────── or continue with ───────"
horizontal_alignment = 1
[node name="SocialButtons" type="HBoxContainer" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox" unique_id=1899762021]
visible = false
layout_mode = 2
theme_override_constants/separation = 12
alignment = 1
[node name="GoogleButton" type="Button" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox/SocialButtons" unique_id=196743645]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(100, 44)
layout_mode = 2
text = "Google"
[node name="AppleButton" type="Button" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox/SocialButtons" unique_id=1174582184]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(100, 44)
layout_mode = 2
text = "Apple"
[node name="FacebookButton" type="Button" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox/SocialButtons" unique_id=1252096120]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(100, 44)
layout_mode = 2
text = "Facebook"
[node name="SteamButton" type="Button" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox/SocialButtons" unique_id=1024459784]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 44)
layout_mode = 2
text = "Steam"
[node name="StatusLabel" type="Label" parent="CenterContainer/LayoutVBox/TabContainer/Login/VBox" unique_id=1679807364]
unique_name_in_owner = true
layout_mode = 2
+1
View File
@@ -318,6 +318,7 @@ text = "💎"
[node name="FragTabBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/CategoryTabs" unique_id=1985872465]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(56, 56)
layout_mode = 2
theme_override_font_sizes/font_size = 28
+1
View File
@@ -141,6 +141,7 @@ text = "GLOVES"
[node name="TabAccessory" type="Button" parent="MainMargin/MainVBox/TopBar/TabsHBox" unique_id=228390814]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(60, 50)
layout_mode = 2
theme_override_fonts/font = ExtResource("3_udh10")
+179
View File
@@ -0,0 +1,179 @@
[gd_scene load_steps=2 format=3 uid="uid://dqsocial001"]
[ext_resource type="Script" path="res://scripts/ui/social_panel.gd" id="1_social"]
[node name="SocialPanel" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource("1_social")
[node name="BgOverlay" type="ColorRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
color = Color(0, 0, 0, 0.6)
mouse_filter = 0
[node name="Panel" type="PanelContainer" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -240.0
offset_top = -280.0
offset_right = 240.0
offset_bottom = 280.0
[node name="VBox" type="VBoxContainer" parent="Panel"]
layout_mode = 2
[node name="Header" type="HBoxContainer" parent="Panel/VBox"]
layout_mode = 2
[node name="TitleLabel" type="Label" parent="Panel/VBox/Header"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Social"
[node name="CloseBtn" type="Button" parent="Panel/VBox/Header"]
unique_name_in_owner = true
layout_mode = 2
text = "X"
[node name="HSep" type="HSeparator" parent="Panel/VBox"]
layout_mode = 2
[node name="TabBar" type="HBoxContainer" parent="Panel/VBox"]
layout_mode = 2
[node name="FriendsTabBtn" type="Button" parent="Panel/VBox/TabBar"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Friends"
[node name="GlobalTabBtn" type="Button" parent="Panel/VBox/TabBar"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Global Chat"
[node name="DMTabBtn" type="Button" parent="Panel/VBox/TabBar"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "DM"
visible = false
[node name="ContentStack" type="Control" parent="Panel/VBox"]
layout_mode = 2
size_flags_vertical = 3
custom_minimum_size = Vector2(0, 380)
[node name="FriendsView" type="VBoxContainer" parent="Panel/VBox/ContentStack"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
[node name="AddFriendRow" type="HBoxContainer" parent="Panel/VBox/ContentStack/FriendsView"]
layout_mode = 2
[node name="AddFriendInput" type="LineEdit" parent="Panel/VBox/ContentStack/FriendsView/AddFriendRow"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Username or ID..."
[node name="AddFriendBtn" type="Button" parent="Panel/VBox/ContentStack/FriendsView/AddFriendRow"]
unique_name_in_owner = true
layout_mode = 2
text = "Add"
[node name="FriendScroll" type="ScrollContainer" parent="Panel/VBox/ContentStack/FriendsView"]
layout_mode = 2
size_flags_vertical = 3
[node name="FriendList" type="VBoxContainer" parent="Panel/VBox/ContentStack/FriendsView/FriendScroll"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="GlobalView" type="VBoxContainer" parent="Panel/VBox/ContentStack"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
visible = false
[node name="GlobalLog" type="RichTextLabel" parent="Panel/VBox/ContentStack/GlobalView"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
bbcode_enabled = true
scroll_following = true
[node name="GlobalInputRow" type="HBoxContainer" parent="Panel/VBox/ContentStack/GlobalView"]
layout_mode = 2
[node name="GlobalInput" type="LineEdit" parent="Panel/VBox/ContentStack/GlobalView/GlobalInputRow"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Type a message..."
[node name="GlobalSendBtn" type="Button" parent="Panel/VBox/ContentStack/GlobalView/GlobalInputRow"]
unique_name_in_owner = true
layout_mode = 2
text = "Send"
[node name="DMView" type="VBoxContainer" parent="Panel/VBox/ContentStack"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
visible = false
[node name="DMHeader" type="HBoxContainer" parent="Panel/VBox/ContentStack/DMView"]
layout_mode = 2
[node name="DMBackBtn" type="Button" parent="Panel/VBox/ContentStack/DMView/DMHeader"]
unique_name_in_owner = true
layout_mode = 2
text = "<- Back"
[node name="DMUsernameLabel" type="Label" parent="Panel/VBox/ContentStack/DMView/DMHeader"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="DMLog" type="RichTextLabel" parent="Panel/VBox/ContentStack/DMView"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
bbcode_enabled = true
scroll_following = true
[node name="DMInputRow" type="HBoxContainer" parent="Panel/VBox/ContentStack/DMView"]
layout_mode = 2
[node name="DMInput" type="LineEdit" parent="Panel/VBox/ContentStack/DMView/DMInputRow"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Type a message..."
[node name="DMSendBtn" type="Button" parent="Panel/VBox/ContentStack/DMView/DMInputRow"]
unique_name_in_owner = true
layout_mode = 2
text = "Send"