feat: overhaul UI main and profile
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://dpkx1a780pvwv" path="res://assets/textures/tile_diamond.png" id="10_sx8rm"]
|
||||
[ext_resource type="BoxMesh" uid="uid://fy4bhoeii40c" path="res://addons/enhanced_gridmap/meshlibrary/tile_safe_zone.tres" id="10_uwjsj"]
|
||||
[ext_resource type="BoxMesh" uid="uid://b5cc3prem52r6" path="res://addons/enhanced_gridmap/meshlibrary/tile_freeze.tres" id="11_pgnbl"]
|
||||
[ext_resource type="BoxMesh" uid="uid://dcjdwbffgtutt" path="res://addons/enhanced_gridmap/meshlibrary/tile_non_walkable.tres" id="11_uwjsj"]
|
||||
[ext_resource type="BoxMesh" path="res://addons/enhanced_gridmap/meshlibrary/tile_non_walkable.tres" id="11_uwjsj"]
|
||||
[ext_resource type="Texture2D" uid="uid://cdnxwlysxnujd" path="res://assets/textures/tile_heart.png" id="12_heart_tex"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_uxput"]
|
||||
|
||||
@@ -248,3 +248,4 @@ TabContainer/colors/font_unselected_color = Color(0.69, 0.529, 0.357, 1)
|
||||
TabContainer/styles/panel = SubResource("StyleBoxFlat_panel_bg")
|
||||
TabContainer/styles/tab_selected = SubResource("StyleBoxFlat_tab_selected")
|
||||
TabContainer/styles/tab_unselected = SubResource("StyleBoxFlat_tab_unselected")
|
||||
TextEdit/fonts/font = null
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import sys
|
||||
import re
|
||||
|
||||
file_path = 'c:/Users/beng/Godot/Projects/tekton-enet/scenes/main.tscn'
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
interaction_idx = -1
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('[node name="InteractionBtn" type="VBoxContainer"'):
|
||||
interaction_idx = i
|
||||
break
|
||||
|
||||
if interaction_idx != -1:
|
||||
for i in range(interaction_idx, interaction_idx + 10):
|
||||
if lines[i].startswith('offset_bottom = '):
|
||||
lines[i] = 'offset_bottom = 282.9999\n'
|
||||
break
|
||||
|
||||
power_btn_start = -1
|
||||
power_btn_end = -1
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('[node name="PowerUpBtn" type="Button" parent="TouchLayer/TouchControls/PowerUpInventoryUI"'):
|
||||
power_btn_start = i
|
||||
# Need to check original parent too in case the earlier modification didn't change this string perfectly, wait!
|
||||
# Ah, PowerUpBtn parent was originally "PowerUpInventoryUI". I did change PowerUpInventoryUI's parent... but did I change PowerUpBtn's parent text in `.tscn`? NO! PowerUpBtn is still `parent="PowerUpInventoryUI"`.
|
||||
if line.startswith('[node name="PowerUpBtn" type="Button" parent="PowerUpInventoryUI"'):
|
||||
power_btn_start = i
|
||||
|
||||
if power_btn_start != -1:
|
||||
for i in range(power_btn_start+1, len(lines)):
|
||||
if lines[i].startswith('[node '):
|
||||
power_btn_end = i
|
||||
break
|
||||
if power_btn_end == -1:
|
||||
power_btn_end = len(lines)
|
||||
|
||||
insert_target_start = -1
|
||||
if interaction_idx != -1:
|
||||
for i in range(interaction_idx + 1, len(lines)):
|
||||
if lines[i].startswith('[node '):
|
||||
if 'parent="TouchLayer/TouchControls/InteractionBtn"' in lines[i]:
|
||||
pass
|
||||
else:
|
||||
insert_target_start = i
|
||||
break
|
||||
|
||||
if power_btn_start != -1 and insert_target_start != -1:
|
||||
block = lines[power_btn_start:power_btn_end]
|
||||
block[0] = block[0].replace('parent="PowerUpInventoryUI"', 'parent="TouchLayer/TouchControls/InteractionBtn"')
|
||||
|
||||
del lines[power_btn_start:power_btn_end]
|
||||
|
||||
if insert_target_start > power_btn_end:
|
||||
insert_target_start -= (power_btn_end - power_btn_start)
|
||||
|
||||
lines = lines[:insert_target_start] + block + lines[insert_target_start:]
|
||||
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.writelines(lines)
|
||||
print('Successfully moved PowerUpBtn and resized InteractionBtn')
|
||||
else:
|
||||
print(f'Failed to find targets: btn_start={power_btn_start}, insert_target={insert_target_start}, interaction_idx={interaction_idx}')
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
import sys
|
||||
|
||||
file_path = 'c:/Users/beng/Godot/Projects/tekton-enet/scenes/main.tscn'
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
power_up_ui_start = -1
|
||||
power_up_ui_end = -1
|
||||
touch_controls_idx = -1
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('[node name="PowerUpInventoryUI"'):
|
||||
power_up_ui_start = i
|
||||
elif power_up_ui_start != -1 and line.startswith('[node ') and power_up_ui_end == -1:
|
||||
if 'parent="PowerUpInventoryUI"' not in line:
|
||||
power_up_ui_end = i
|
||||
|
||||
if line.startswith('[node name="TouchControls" type="Control" parent="TouchLayer"'):
|
||||
touch_controls_idx = i
|
||||
|
||||
if power_up_ui_end == -1:
|
||||
power_up_ui_end = len(lines)
|
||||
|
||||
if power_up_ui_start != -1 and touch_controls_idx != -1:
|
||||
# Extract the block
|
||||
block = lines[power_up_ui_start:power_up_ui_end]
|
||||
|
||||
# Modify the parent
|
||||
block[0] = block[0].replace('parent="."', 'parent="TouchLayer/TouchControls"')
|
||||
|
||||
# Remove from original location
|
||||
del lines[power_up_ui_start:power_up_ui_end]
|
||||
|
||||
# Adjust touch_controls_idx if it was after the removed block
|
||||
if touch_controls_idx > power_up_ui_end:
|
||||
touch_controls_idx -= (power_up_ui_end - power_up_ui_start)
|
||||
|
||||
# Find end of TouchControls block/properties to insert
|
||||
insert_idx = touch_controls_idx + 1
|
||||
while insert_idx < len(lines) and not lines[insert_idx].startswith('['):
|
||||
insert_idx += 1
|
||||
|
||||
lines = lines[:insert_idx] + block + lines[insert_idx:]
|
||||
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.writelines(lines)
|
||||
print('Successfully moved PowerUpInventoryUI to TouchLayer/TouchControls')
|
||||
else:
|
||||
print(f'Failed to find nodes: star={power_up_ui_start}, touch={touch_controls_idx}')
|
||||
+116
-23
@@ -2,22 +2,33 @@ extends Control
|
||||
|
||||
# UI References - Main Menu
|
||||
@onready var main_menu_panel = $MainMenuPanel
|
||||
@onready var main_title = $MainMenuPanel/HiddenLogic/Title
|
||||
@onready var username_label = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox/VBoxContainer/Username
|
||||
@onready var main_subtitle = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox/VBoxContainer/Subtitle
|
||||
@onready var create_room_btn = $MainMenuPanel/MainContainer/MarginContainer/BottomRightPanel/CreateRoomBtn
|
||||
@onready var browse_rooms_btn = $MainMenuPanel/MainContainer/MarginContainer/BottomRightPanel/BrowseRoomsBtn
|
||||
@onready var tutorial_btn = $MainMenuPanel/MainContainer/MarginContainer/BottomRightPanel/TutorialBtn
|
||||
@onready var main_menu_profile_btn = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox/ProfileBtn
|
||||
@onready var lobby_settings_btn = $MainMenuPanel/MainContainer/MarginContainer/TopRightPanel/SettingsBtn
|
||||
@onready var quit_btn = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/HBoxContainer/QuitBtn
|
||||
@onready var main_title = %Title
|
||||
@onready var username_label = %Username
|
||||
@onready var main_subtitle = %Subtitle
|
||||
@onready var create_room_btn = %CreateRoomBtn
|
||||
@onready var browse_rooms_btn = %BrowseRoomsBtn
|
||||
@onready var tutorial_btn = %TutorialBtn
|
||||
@onready var main_menu_profile_btn = %MainProfileBtn
|
||||
@onready var avatar_display = %AvatarDisplay
|
||||
@onready var lobby_settings_btn = %SettingsBtn
|
||||
@onready var quit_btn = %QuitBtn
|
||||
|
||||
# Main Menu 3D Preview
|
||||
@onready var character_root = %CharacterRoot
|
||||
@onready var anim_player = %AnimationPlayer
|
||||
|
||||
# UI References - Currencies
|
||||
@onready var gold_label = %GoldLabel
|
||||
@onready var star_label = %StarLabel
|
||||
|
||||
# UI References - Server Selection
|
||||
@onready var server_option = $MainMenuPanel/HiddenLogic/ServerOption
|
||||
@onready var server_ip_input = $MainMenuPanel/HiddenLogic/ServerIPInput
|
||||
@onready var server_option = %ServerOption
|
||||
@onready var server_ip_input = %ServerIPInput
|
||||
|
||||
# Leaderboard Reference
|
||||
@onready var leaderboard_btn = $MainMenuPanel/MainContainer/MarginContainer/TopRightPanel/LeaderboardBtn
|
||||
@onready var leaderboard_btn = %LeaderboardBtn
|
||||
@onready var shop_btn = %CartBtn
|
||||
@onready var top_right_profile_btn = %ProfileBtn
|
||||
|
||||
# UI References - Room List
|
||||
@onready var room_list_panel = $RoomListPanel
|
||||
@@ -108,9 +119,9 @@ const GLOBAL_CHAT_ROOM := "global_lobby"
|
||||
var _chat_channel = null
|
||||
var _chat_messages: Array = []
|
||||
|
||||
@onready var chat_display: RichTextLabel = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ChatPanel/MarginContainer/RichTextLabel
|
||||
@onready var chat_input: LineEdit = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/HBoxContainer/ChatInput
|
||||
@onready var chat_send_btn: Button = $MainMenuPanel/MainContainer/MarginContainer/LeftPanel/HBoxContainer/SendBtn
|
||||
@onready var chat_display: RichTextLabel = %RichTextLabel
|
||||
@onready var chat_input: LineEdit = %ChatInput
|
||||
@onready var chat_send_btn: Button = %SendBtn
|
||||
|
||||
# Server Selection Controls (Now in tscn)
|
||||
# var server_option: OptionButton
|
||||
@@ -142,8 +153,15 @@ func _ready():
|
||||
tutorial_btn.pressed.connect(_on_tutorial_pressed)
|
||||
if main_menu_profile_btn:
|
||||
main_menu_profile_btn.pressed.connect(_on_profile_btn_pressed)
|
||||
if top_right_profile_btn:
|
||||
top_right_profile_btn.pressed.connect(_on_profile_btn_pressed)
|
||||
if lobby_settings_btn:
|
||||
lobby_settings_btn.pressed.connect(_on_settings_pressed)
|
||||
|
||||
# Shop Button
|
||||
if shop_btn:
|
||||
shop_btn.pressed.connect(_on_shop_pressed)
|
||||
|
||||
if leaderboard_btn:
|
||||
leaderboard_btn.pressed.connect(_on_leaderboard_pressed)
|
||||
if quit_btn:
|
||||
@@ -252,6 +270,33 @@ func _ready():
|
||||
# Setup
|
||||
# =============================================================================
|
||||
|
||||
const CHAR_NODE_MAP: Dictionary = {
|
||||
"Copper": "Oldpop",
|
||||
"Dabro": "Masbro",
|
||||
"Gatot": "Gatot",
|
||||
"Pip": "Bob"
|
||||
}
|
||||
|
||||
func _setup_3d_preview() -> void:
|
||||
"""Swaps out the active character inside the 3D MainMenu SubViewport."""
|
||||
if not character_root:
|
||||
return
|
||||
var target_character = UserProfileManager.profile.get("loadout_character", "Copper")
|
||||
var node_name = CHAR_NODE_MAP.get(target_character, "Bob")
|
||||
|
||||
for child in character_root.get_children():
|
||||
if child is Node3D:
|
||||
child.visible = (child.name == node_name)
|
||||
|
||||
if anim_player:
|
||||
var new_root: Node3D = character_root.get_node_or_null(node_name) as Node3D
|
||||
if new_root:
|
||||
anim_player.root_node = new_root.get_path()
|
||||
if anim_player.has_animation("animation-pack/idle"):
|
||||
anim_player.play("animation-pack/idle")
|
||||
elif anim_player.get_animation_list().size() > 0:
|
||||
anim_player.play(anim_player.get_animation_list()[0])
|
||||
|
||||
func _load_character_textures() -> void:
|
||||
"""Load character preview textures."""
|
||||
var characters = {
|
||||
@@ -672,11 +717,18 @@ func _on_profile_btn_pressed() -> void:
|
||||
if not profile_panel_instance:
|
||||
var profile_panel_scene := load("res://scenes/ui/profile_panel.tscn")
|
||||
profile_panel_instance = profile_panel_scene.instantiate()
|
||||
profile_panel_instance.closed.connect(func(): profile_panel_instance.hide())
|
||||
profile_panel_instance.closed.connect(func():
|
||||
profile_panel_instance.hide()
|
||||
if main_menu_panel:
|
||||
main_menu_panel.show()
|
||||
)
|
||||
# Full-screen overlay — fill the entire lobby viewport
|
||||
profile_panel_instance.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
add_child(profile_panel_instance)
|
||||
|
||||
if profile_panel_instance:
|
||||
if main_menu_panel:
|
||||
main_menu_panel.hide()
|
||||
profile_panel_instance.show_panel()
|
||||
|
||||
func _on_logout_pressed() -> void:
|
||||
@@ -696,26 +748,60 @@ func _on_settings_pressed():
|
||||
settings_menu.name = "SettingsMenu"
|
||||
add_child(settings_menu)
|
||||
|
||||
# Connect close button
|
||||
# Connect close button — restore whichever panel was visible before
|
||||
var close_btn = settings_menu.get_node_or_null("PanelContainer/VBoxContainer/Header/CloseButton")
|
||||
if close_btn:
|
||||
# settings_menu.gd handles basic visibility, but we can override or add to it
|
||||
pass
|
||||
close_btn.pressed.connect(func():
|
||||
if lobby_panel and lobby_panel.visible:
|
||||
pass # lobby_panel restored below via _restore_panel
|
||||
_restore_after_settings()
|
||||
)
|
||||
|
||||
if settings_menu:
|
||||
# Remember what is currently active
|
||||
settings_menu.set_meta("from_lobby", lobby_panel.visible if lobby_panel else false)
|
||||
main_menu_panel.hide()
|
||||
if lobby_panel: lobby_panel.hide()
|
||||
settings_menu.open()
|
||||
|
||||
func _restore_after_settings() -> void:
|
||||
var settings_menu = get_node_or_null("SettingsMenu")
|
||||
var from_lobby: bool = settings_menu.get_meta("from_lobby", false) if settings_menu else false
|
||||
if from_lobby:
|
||||
if lobby_panel: lobby_panel.show()
|
||||
else:
|
||||
if main_menu_panel: main_menu_panel.show()
|
||||
|
||||
func _on_shop_pressed() -> void:
|
||||
if not NakamaManager.session:
|
||||
connection_status.text = "Must be logged in"
|
||||
return
|
||||
|
||||
var shop_scene = load("res://scenes/ui/shop_panel.tscn")
|
||||
if shop_scene:
|
||||
var shop = shop_scene.instantiate()
|
||||
add_child(shop)
|
||||
if main_menu_panel: main_menu_panel.hide()
|
||||
shop.closed.connect(func(): if main_menu_panel: main_menu_panel.show())
|
||||
shop.show_panel()
|
||||
|
||||
func _on_leaderboard_pressed() -> void:
|
||||
if not leaderboard_panel_instance:
|
||||
var leaderboard_panel_scene := load("res://scenes/ui/leaderboard_panel.tscn")
|
||||
if leaderboard_panel_scene:
|
||||
leaderboard_panel_instance = leaderboard_panel_scene.instantiate()
|
||||
leaderboard_panel_instance.closed.connect(func(): leaderboard_panel_instance.hide())
|
||||
leaderboard_panel_instance.closed.connect(func():
|
||||
leaderboard_panel_instance.hide()
|
||||
if main_menu_panel:
|
||||
main_menu_panel.show()
|
||||
)
|
||||
# Full-screen overlay
|
||||
leaderboard_panel_instance.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
add_child(leaderboard_panel_instance)
|
||||
|
||||
if leaderboard_panel_instance:
|
||||
if main_menu_panel:
|
||||
main_menu_panel.hide()
|
||||
leaderboard_panel_instance.show_panel()
|
||||
|
||||
func _go_to_login() -> void:
|
||||
@@ -873,16 +959,23 @@ func _on_profile_updated() -> void:
|
||||
if username_label:
|
||||
username_label.text = display_name
|
||||
|
||||
if main_menu_profile_btn:
|
||||
if avatar_display:
|
||||
var avatar_url = UserProfileManager.get_avatar_url()
|
||||
if ResourceLoader.exists(avatar_url):
|
||||
main_menu_profile_btn.icon = load(avatar_url)
|
||||
main_menu_profile_btn.expand_icon = true
|
||||
avatar_display.texture = load(avatar_url)
|
||||
if main_menu_profile_btn:
|
||||
main_menu_profile_btn.text = ""
|
||||
|
||||
if gold_label and UserProfileManager.is_profile_loaded:
|
||||
gold_label.text = str(UserProfileManager.wallet.get("gold", 0))
|
||||
if star_label and UserProfileManager.is_profile_loaded:
|
||||
star_label.text = str(UserProfileManager.wallet.get("star", 0))
|
||||
|
||||
# Sync to LobbyManager
|
||||
LobbyManager.set_player_name(display_name)
|
||||
|
||||
_setup_3d_preview()
|
||||
|
||||
# =============================================================================
|
||||
# Player Slot Updates
|
||||
# =============================================================================
|
||||
|
||||
+411
-130
@@ -3,8 +3,21 @@
|
||||
[ext_resource type="Script" uid="uid://b5q6yekyk0tld" path="res://scenes/lobby.gd" id="1_lp6xi"]
|
||||
[ext_resource type="Theme" uid="uid://da337sh5qxi0s" path="res://assets/themes/ui_theme.tres" id="2_theme"]
|
||||
[ext_resource type="Texture2D" uid="uid://2d1ks5pmblc7" path="res://assets/graphics/main_menu/bg_back.png" id="3_q60fs"]
|
||||
[ext_resource type="PackedScene" uid="uid://ejeamn0pyey4" path="res://assets/characters/Bob.glb" id="4_bob"]
|
||||
[ext_resource type="PackedScene" uid="uid://d4cul3w3wem5w" path="res://assets/characters/Gatot.glb" id="4_gatot"]
|
||||
[ext_resource type="PackedScene" uid="uid://1vk0mjnwkngi" path="res://assets/characters/Masbro.glb" id="4_masbro"]
|
||||
[ext_resource type="Texture2D" uid="uid://dvp0as6yyudco" path="res://assets/graphics/main_menu/bg_illust.png" id="4_nqcc7"]
|
||||
[ext_resource type="PackedScene" uid="uid://bmln7v6v5kvxg" path="res://assets/characters/Oldpop.glb" id="4_oldpop"]
|
||||
[ext_resource type="AnimationLibrary" uid="uid://c3pyopnwibckj" path="res://assets/characters/animations/animation-pack.res" id="5_animlib"]
|
||||
[ext_resource type="FontFile" uid="uid://xnjx058n4tsw" path="res://assets/fonts/Nougat-ExtraBlack.ttf" id="5_pc087"]
|
||||
[ext_resource type="Texture2D" uid="uid://brhn1dhp1gm13" path="res://assets/graphics/character_selection/sc_characters/sc_copper.png" id="10_dyhay"]
|
||||
|
||||
[sub_resource type="Environment" id="Env_preview"]
|
||||
background_mode = 1
|
||||
background_color = Color(0, 0, 0, 0)
|
||||
ambient_light_source = 2
|
||||
ambient_light_color = Color(1, 1, 1, 1)
|
||||
ambient_light_energy = 0.5
|
||||
|
||||
[node name="Lobby" type="Control" unique_id=1490767889]
|
||||
layout_mode = 3
|
||||
@@ -16,7 +29,17 @@ grow_vertical = 2
|
||||
theme = ExtResource("2_theme")
|
||||
script = ExtResource("1_lp6xi")
|
||||
|
||||
[node name="Background3" type="ColorRect" parent="." unique_id=245238082]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0.0627451, 0.0745098, 0.101961, 1)
|
||||
|
||||
[node name="Background" type="TextureRect" parent="." unique_id=767675801]
|
||||
modulate = Color(1, 1, 1, 0.28235295)
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
@@ -38,226 +61,480 @@ texture = ExtResource("4_nqcc7")
|
||||
expand_mode = 2
|
||||
flip_h = true
|
||||
|
||||
[node name="MainMenuPanel" type="CanvasLayer" parent="." unique_id=296519838]
|
||||
[node name="MainMenuPanel" type="CanvasLayer" parent="." unique_id=1628604448]
|
||||
|
||||
[node name="MainContainer" type="Control" parent="MainMenuPanel" unique_id=1358259397]
|
||||
[node name="ViewportWrapper" type="Control" parent="MainMenuPanel" unique_id=9084]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MainMenuPanel/MainContainer" unique_id=396129054]
|
||||
[node name="SubViewportContainer" type="SubViewportContainer" parent="MainMenuPanel/ViewportWrapper" unique_id=90485]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
stretch = true
|
||||
|
||||
[node name="PreviewViewport" type="SubViewport" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer" unique_id=904850]
|
||||
unique_name_in_owner = true
|
||||
own_world_3d = true
|
||||
transparent_bg = true
|
||||
handle_input_locally = false
|
||||
size = Vector2i(1366, 720)
|
||||
render_target_update_mode = 4
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport" unique_id=253593246]
|
||||
environment = SubResource("Env_preview")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport" unique_id=129901731]
|
||||
transform = Transform3D(0.866025, -0.25, 0.433013, 0, 0.866025, 0.5, -0.5, -0.433013, 0.75, 1, 4, 0)
|
||||
light_energy = 1.5
|
||||
|
||||
[node name="FillLight" type="OmniLight3D" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport" unique_id=9048]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 2, 2)
|
||||
light_color = Color(0.4, 0.55, 1, 1)
|
||||
light_energy = 0.6
|
||||
omni_range = 10.0
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport" unique_id=904]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.970728, 0.24018, 0, -0.24018, 0.970728, 0, 0.972868, 3.4)
|
||||
current = true
|
||||
fov = 38.0
|
||||
|
||||
[node name="CharacterRoot" type="Node3D" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport" unique_id=1661304167]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="Masbro" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport/CharacterRoot" unique_id=1689619097 instance=ExtResource("4_masbro")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.485, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Bob" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport/CharacterRoot" unique_id=753190814 instance=ExtResource("4_bob")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.484, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Gatot" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport/CharacterRoot" unique_id=145617195 instance=ExtResource("4_gatot")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.485, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Oldpop" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport/CharacterRoot" unique_id=886481313 instance=ExtResource("4_oldpop")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.485, 0)
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="MainMenuPanel/ViewportWrapper/SubViewportContainer/PreviewViewport/CharacterRoot" unique_id=790589799]
|
||||
unique_name_in_owner = true
|
||||
root_node = NodePath("../Oldpop")
|
||||
libraries/animation-pack = ExtResource("5_animlib")
|
||||
autoplay = &"animation-pack/idle"
|
||||
|
||||
[node name="MainMargin" type="MarginContainer" parent="MainMenuPanel" unique_id=534985223]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/margin_left = 30
|
||||
theme_override_constants/margin_top = 30
|
||||
theme_override_constants/margin_right = 30
|
||||
theme_override_constants/margin_bottom = 30
|
||||
|
||||
[node name="LeftPanel" type="VBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer" unique_id=1627330537]
|
||||
[node name="MainHBox" type="HBoxContainer" parent="MainMenuPanel/MainMargin" unique_id=892534882]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="ProfileBox" type="HBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel" unique_id=2112406804]
|
||||
[node name="LeftCol" type="VBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox" unique_id=53823485]
|
||||
custom_minimum_size = Vector2(350, 0)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="ProfileBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox" unique_id=1711074288]
|
||||
custom_minimum_size = Vector2(80, 80)
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol" unique_id=473798164]
|
||||
layout_mode = 2
|
||||
text = "ICON"
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox" unique_id=1812465381]
|
||||
[node name="ProfileCard" type="PanelContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2" unique_id=5938459]
|
||||
clip_contents = true
|
||||
custom_minimum_size = Vector2(0, 130)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2/ProfileCard" unique_id=58934509]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="MainProfileBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2/ProfileCard/HBox" unique_id=89234859]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(100, 100)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
flat = true
|
||||
expand_icon = true
|
||||
|
||||
[node name="AvatarDisplay" type="TextureRect" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2/ProfileCard/HBox/MainProfileBtn" unique_id=593485890]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
texture = ExtResource("10_dyhay")
|
||||
expand_mode = 1
|
||||
stretch_mode = 5
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2/ProfileCard/HBox" unique_id=598345789]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
alignment = 1
|
||||
|
||||
[node name="Username" type="Label" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox/VBoxContainer" unique_id=499855830]
|
||||
[node name="Username" type="Label" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2/ProfileCard/HBox/VBoxContainer" unique_id=50934858]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "USERNAME"
|
||||
|
||||
[node name="Subtitle" type="Label" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ProfileBox/VBoxContainer" unique_id=2081013344]
|
||||
[node name="Subtitle" type="Label" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2/ProfileCard/HBox/VBoxContainer" unique_id=5948395]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.71, 0.575, 0.035, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
theme_override_colors/font_color = Color(0.7, 0.6, 0.2, 1)
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "EU SERVER"
|
||||
|
||||
[node name="Spacer" type="Control" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel" unique_id=2013644806]
|
||||
custom_minimum_size = Vector2(0, 20)
|
||||
[node name="Control" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer2" unique_id=177944371]
|
||||
custom_minimum_size = Vector2(80, 0)
|
||||
layout_direction = 3
|
||||
layout_mode = 2
|
||||
|
||||
[node name="CurrenciesBox" type="VBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel" unique_id=1252464073]
|
||||
[node name="SpacerProfile" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol" unique_id=58943589]
|
||||
custom_minimum_size = Vector2(0, 8)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="StarPanel" type="PanelContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox" unique_id=1482932751]
|
||||
custom_minimum_size = Vector2(160, 40)
|
||||
[node name="CurrencyRow" type="VBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol" unique_id=59384589]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox/StarPanel" unique_id=1113231570]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
alignment = 1
|
||||
|
||||
[node name="Icon" type="Label" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox/StarPanel/HBoxContainer" unique_id=1267791073]
|
||||
layout_mode = 2
|
||||
text = "⭐"
|
||||
|
||||
[node name="Label" type="Label" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox/StarPanel/HBoxContainer" unique_id=2117232678]
|
||||
layout_mode = 2
|
||||
text = "23891"
|
||||
|
||||
[node name="GoldPanel" type="PanelContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox" unique_id=948555205]
|
||||
custom_minimum_size = Vector2(160, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox/GoldPanel" unique_id=788193079]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
alignment = 1
|
||||
|
||||
[node name="Icon" type="Label" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox/GoldPanel/HBoxContainer" unique_id=131964257]
|
||||
layout_mode = 2
|
||||
text = "💰"
|
||||
|
||||
[node name="Label" type="Label" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/CurrenciesBox/GoldPanel/HBoxContainer" unique_id=1973438143]
|
||||
layout_mode = 2
|
||||
text = "3217"
|
||||
|
||||
[node name="ChatSpacer" type="Control" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel" unique_id=1632908247]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow" unique_id=1807032398]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ChatPanel" type="PanelContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel" unique_id=1582318454]
|
||||
custom_minimum_size = Vector2(350, 200)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ChatPanel" unique_id=1866798800]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 15
|
||||
theme_override_constants/margin_top = 15
|
||||
theme_override_constants/margin_right = 15
|
||||
theme_override_constants/margin_bottom = 15
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/ChatPanel/MarginContainer" unique_id=1563684167]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
scroll_following = true
|
||||
text = ""
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel" unique_id=976080441]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="QuitBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/HBoxContainer" unique_id=1499547561]
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
layout_mode = 2
|
||||
text = "<]"
|
||||
|
||||
[node name="ChatInput" type="LineEdit" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/HBoxContainer" unique_id=1511957602]
|
||||
[node name="StarPanel" type="PanelContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer" unique_id=509438]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
placeholder_text = " type to chat"
|
||||
theme = ExtResource("2_theme")
|
||||
|
||||
[node name="SendBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/LeftPanel/HBoxContainer" unique_id=1337641536]
|
||||
[node name="Margin" type="MarginContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer/StarPanel" unique_id=609485]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 4
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 4
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer/StarPanel/Margin" unique_id=69485094]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="Icon" type="Label" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer/StarPanel/Margin/HBoxContainer" unique_id=958438]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.9, 0.7, 0.3, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "✦"
|
||||
|
||||
[node name="StarLabel" type="Label" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer/StarPanel/Margin/HBoxContainer" unique_id=948509]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "0"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="Control" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer" unique_id=255421565]
|
||||
custom_minimum_size = Vector2(180, 0)
|
||||
layout_direction = 3
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow" unique_id=1399423386]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="GoldPanel" type="PanelContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer2" unique_id=9458940]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer2/GoldPanel" unique_id=94589]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 4
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 4
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer2/GoldPanel/Margin" unique_id=9458094]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="Icon" type="Label" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer2/GoldPanel/Margin/HBoxContainer" unique_id=9485]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.8, 0.6, 0.2, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "▤"
|
||||
|
||||
[node name="GoldLabel" type="Label" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer2/GoldPanel/Margin/HBoxContainer" unique_id=94850]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "0"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="Control" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/CurrencyRow/HBoxContainer2" unique_id=320833893]
|
||||
custom_minimum_size = Vector2(180, 0)
|
||||
layout_direction = 3
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SpacerMiddle" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol" unique_id=984509]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ChatPanel" type="PanelContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol" unique_id=948590]
|
||||
custom_minimum_size = Vector2(360, 160)
|
||||
layout_mode = 2
|
||||
theme = ExtResource("2_theme")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/ChatPanel" unique_id=945890]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 8
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 8
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/ChatPanel/MarginContainer" unique_id=1730680016]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_colors/default_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
bbcode_enabled = true
|
||||
scroll_following = true
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol" unique_id=459038]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="QuitBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer" unique_id=1853395708]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
layout_mode = 2
|
||||
theme = ExtResource("2_theme")
|
||||
text = "←"
|
||||
|
||||
[node name="ChatInput" type="LineEdit" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer" unique_id=1346390421]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 20
|
||||
placeholder_text = " type to chat"
|
||||
|
||||
[node name="SendBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/LeftCol/HBoxContainer" unique_id=1491048704]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(40, 40)
|
||||
layout_mode = 2
|
||||
theme = ExtResource("2_theme")
|
||||
text = ">"
|
||||
|
||||
[node name="TopRightPanel" type="HBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer" unique_id=377986819]
|
||||
[node name="CenterCol" type="VBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox" unique_id=7006870]
|
||||
clip_contents = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 0
|
||||
theme_override_constants/separation = 15
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="CartBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/TopRightPanel" unique_id=2015877617]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
[node name="RightCol" type="VBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox" unique_id=1457624180]
|
||||
custom_minimum_size = Vector2(280, 0)
|
||||
layout_mode = 2
|
||||
text = "🛒"
|
||||
|
||||
[node name="TicketBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/TopRightPanel" unique_id=2142342229]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
[node name="TopRightPanel" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/RightCol" unique_id=20449742]
|
||||
custom_minimum_size = Vector2(500, 0)
|
||||
layout_mode = 2
|
||||
text = "🎟"
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_constants/separation = 12
|
||||
alignment = 2
|
||||
|
||||
[node name="SocialBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/TopRightPanel" unique_id=23817931]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
[node name="ProfileBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/TopRightPanel" unique_id=752873406]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
text = "👥"
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
text = "PROFILE"
|
||||
|
||||
[node name="LeaderboardBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/TopRightPanel" unique_id=1742815055]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
[node name="LeaderboardBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/TopRightPanel" unique_id=312524216]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
text = "🏆"
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
text = "LEADERBOARD"
|
||||
|
||||
[node name="SettingsBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/TopRightPanel" unique_id=439499917]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
[node name="CartBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/TopRightPanel" unique_id=456149005]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
text = "⚙"
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
text = "SHOP"
|
||||
|
||||
[node name="RightPanel" type="VBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer" unique_id=1806183556]
|
||||
[node name="TicketBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/TopRightPanel" unique_id=64042310]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 4
|
||||
theme_override_constants/separation = 20
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
disabled = true
|
||||
text = "BATTLE PASS"
|
||||
|
||||
[node name="Banner1" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/RightPanel" unique_id=1918689135]
|
||||
custom_minimum_size = Vector2(250, 120)
|
||||
[node name="SocialBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/TopRightPanel" unique_id=82719328]
|
||||
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]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
text = "SETTINGS"
|
||||
|
||||
[node name="Spacer1" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/RightCol" unique_id=9023]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Banners" type="VBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/RightCol" unique_id=1356766829]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
alignment = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners" unique_id=160134239]
|
||||
layout_mode = 2
|
||||
alignment = 2
|
||||
|
||||
[node name="Control" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners/HBoxContainer" unique_id=1128600858]
|
||||
clip_contents = true
|
||||
custom_minimum_size = Vector2(350, 0)
|
||||
layout_direction = 3
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Banner1" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners/HBoxContainer" unique_id=5676924]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 120)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 30
|
||||
disabled = true
|
||||
text = "Banner Slot"
|
||||
|
||||
[node name="Banner2" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/RightPanel" unique_id=336081993]
|
||||
custom_minimum_size = Vector2(250, 120)
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners" unique_id=1932828178]
|
||||
layout_mode = 2
|
||||
alignment = 2
|
||||
|
||||
[node name="Control" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners/HBoxContainer2" unique_id=1409766358]
|
||||
clip_contents = true
|
||||
custom_minimum_size = Vector2(350, 0)
|
||||
layout_direction = 3
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Banner2" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners/HBoxContainer2" unique_id=695110150]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 120)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 30
|
||||
disabled = true
|
||||
text = "Banner Slot"
|
||||
|
||||
[node name="Banner3" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/RightPanel" unique_id=942094893]
|
||||
custom_minimum_size = Vector2(250, 120)
|
||||
[node name="HBoxContainer3" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners" unique_id=1502007727]
|
||||
layout_mode = 2
|
||||
alignment = 2
|
||||
|
||||
[node name="Control" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners/HBoxContainer3" unique_id=249145750]
|
||||
clip_contents = true
|
||||
custom_minimum_size = Vector2(350, 0)
|
||||
layout_direction = 3
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Banner3" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/Banners/HBoxContainer3" unique_id=945]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 120)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 30
|
||||
disabled = true
|
||||
text = "Banner Slot"
|
||||
|
||||
[node name="BottomRightPanel" type="HBoxContainer" parent="MainMenuPanel/MainContainer/MarginContainer" unique_id=923616751]
|
||||
[node name="Spacer2" type="Control" parent="MainMenuPanel/MainMargin/MainHBox/RightCol" unique_id=324]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 8
|
||||
theme_override_constants/separation = 15
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="TutorialBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/BottomRightPanel" unique_id=1468068637]
|
||||
custom_minimum_size = Vector2(160, 60)
|
||||
[node name="BottomRightPanel" type="HBoxContainer" parent="MainMenuPanel/MainMargin/MainHBox/RightCol" unique_id=987]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 22
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="TutorialBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/BottomRightPanel" unique_id=951866518]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 50)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "TUTORIAL"
|
||||
|
||||
[node name="CreateRoomBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/BottomRightPanel" unique_id=1069893052]
|
||||
custom_minimum_size = Vector2(160, 60)
|
||||
[node name="CreateRoomBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/BottomRightPanel" unique_id=8]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 50)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 22
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "HOST"
|
||||
|
||||
[node name="BrowseRoomsBtn" type="Button" parent="MainMenuPanel/MainContainer/MarginContainer/BottomRightPanel" unique_id=1488596739]
|
||||
custom_minimum_size = Vector2(160, 60)
|
||||
[node name="BrowseRoomsBtn" type="Button" parent="MainMenuPanel/MainMargin/MainHBox/RightCol/BottomRightPanel" unique_id=4595]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 50)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 22
|
||||
size_flags_horizontal = 3
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "BROWSE"
|
||||
|
||||
[node name="HiddenLogic" type="Control" parent="MainMenuPanel" unique_id=1708805146]
|
||||
[node name="HiddenLogic" type="Control" parent="MainMenuPanel" unique_id=345]
|
||||
visible = false
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
|
||||
[node name="Title" type="Label" parent="MainMenuPanel/HiddenLogic" unique_id=586152975]
|
||||
[node name="Title" type="Label" parent="MainMenuPanel/HiddenLogic" unique_id=534]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
text = "TEKTON DASH"
|
||||
|
||||
[node name="ServerOption" type="OptionButton" parent="MainMenuPanel/HiddenLogic" unique_id=837593831]
|
||||
[node name="ServerOption" type="OptionButton" parent="MainMenuPanel/HiddenLogic" unique_id=645]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
selected = 3
|
||||
item_count = 4
|
||||
@@ -270,7 +547,8 @@ popup/item_2/id = 2
|
||||
popup/item_3/text = "Tekton Dash EU"
|
||||
popup/item_3/id = 3
|
||||
|
||||
[node name="ServerIPInput" type="LineEdit" parent="MainMenuPanel/HiddenLogic" unique_id=690927860]
|
||||
[node name="ServerIPInput" type="LineEdit" parent="MainMenuPanel/HiddenLogic" unique_id=1616424715]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
text = "127.0.0.1"
|
||||
|
||||
@@ -346,6 +624,7 @@ layout_mode = 2
|
||||
text = "BACK"
|
||||
|
||||
[node name="ProfileBtn" type="Button" parent="RoomListPanel/VBoxContainer/ButtonContainer" unique_id=1473526002]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(80, 44)
|
||||
layout_mode = 2
|
||||
text = "PROFILE"
|
||||
@@ -405,6 +684,7 @@ layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="ProfileBtn" type="Button" parent="LobbyPanel/TopBar/ProfileSection" unique_id=1726139031]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(80, 32)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
@@ -412,6 +692,7 @@ theme_override_font_sizes/font_size = 11
|
||||
text = "Profile"
|
||||
|
||||
[node name="LogoutBtn" type="Button" parent="LobbyPanel/TopBar/ProfileSection" unique_id=1221873519]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(70, 32)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
|
||||
+17
-1
@@ -35,6 +35,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://bowng12514p53" path="res://assets/graphics/gui/rankings/3rd.png" id="29_pibwh"]
|
||||
[ext_resource type="Texture2D" uid="uid://biun2yvglxgij" path="res://assets/graphics/touch_control/grab_tekton.png" id="36_pibwh"]
|
||||
[ext_resource type="Texture2D" uid="uid://bucwm17lfd131" path="res://assets/graphics/gui/help icon.png" id="37_pibwh"]
|
||||
[ext_resource type="Theme" uid="uid://da337sh5qxi0s" path="res://assets/themes/ui_theme.tres" id="38_5he1u"]
|
||||
[ext_resource type="Texture2D" uid="uid://da3yx87ar7kcj" path="res://assets/graphics/gui/setting_icon.png" id="38_c6pm6"]
|
||||
[ext_resource type="Script" uid="uid://86ikh0wuqk7v" path="res://scripts/ui/powerup_inventory_ui.gd" id="powerup_ui_script"]
|
||||
[ext_resource type="Script" uid="uid://b54tfa0n6kogi" path="res://scripts/managers/touch_controls.gd" id="touch_manager"]
|
||||
@@ -96,6 +97,10 @@ content_margin_left = 33.0
|
||||
content_margin_bottom = 20.0
|
||||
texture = SubResource("CompressedTexture2D_chjal")
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5poiv"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_2cjbq"]
|
||||
|
||||
[node name="Main" type="Node3D" unique_id=864552263]
|
||||
script = ExtResource("1_xcpe3")
|
||||
|
||||
@@ -1746,10 +1751,12 @@ offset_right = 150.0
|
||||
offset_bottom = 150.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxEmpty_5poiv")
|
||||
|
||||
[node name="NetworkPanel" type="Panel" parent="PauseMenu/Panel" unique_id=935918250]
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = ExtResource("5_dvx6y")
|
||||
theme = ExtResource("38_5he1u")
|
||||
theme_override_styles/panel = SubResource("StyleBoxEmpty_2cjbq")
|
||||
|
||||
[node name="NetworkInfo" type="HBoxContainer" parent="PauseMenu/Panel/NetworkPanel" unique_id=1194782604]
|
||||
visible = false
|
||||
@@ -1778,11 +1785,13 @@ vertical_alignment = 1
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="PauseMenu/Panel" unique_id=837757440]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("38_5he1u")
|
||||
theme_override_constants/separation = 15
|
||||
alignment = 1
|
||||
|
||||
[node name="Title" type="Label" parent="PauseMenu/Panel/VBox" unique_id=1740539610]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("13_j8jky")
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Menu"
|
||||
horizontal_alignment = 1
|
||||
@@ -1794,22 +1803,26 @@ layout_mode = 2
|
||||
[node name="ResumeBtn" type="Button" parent="PauseMenu/Panel/VBox" unique_id=79086881]
|
||||
custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("13_j8jky")
|
||||
text = "Resume"
|
||||
|
||||
[node name="HowToPlayBtn" type="Button" parent="PauseMenu/Panel/VBox" unique_id=987654321]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("13_j8jky")
|
||||
text = "How to Play"
|
||||
|
||||
[node name="SettingsBtn" type="Button" parent="PauseMenu/Panel/VBox" unique_id=215865401]
|
||||
custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("13_j8jky")
|
||||
text = "Settings"
|
||||
|
||||
[node name="QuitBtn" type="Button" parent="PauseMenu/Panel/VBox" unique_id=1771850243]
|
||||
custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("13_j8jky")
|
||||
text = "Quit Match"
|
||||
|
||||
[node name="HowToPlayPanel" type="CanvasLayer" parent="." unique_id=123456789]
|
||||
@@ -1837,6 +1850,7 @@ offset_right = 300.0
|
||||
offset_bottom = 250.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = ExtResource("38_5he1u")
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="HowToPlayPanel/Panel" unique_id=123456792]
|
||||
layout_mode = 2
|
||||
@@ -1845,6 +1859,7 @@ alignment = 1
|
||||
|
||||
[node name="Title" type="Label" parent="HowToPlayPanel/Panel/VBox" unique_id=123456793]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_font_sizes/font_size = 22
|
||||
text = "How to Play"
|
||||
horizontal_alignment = 1
|
||||
@@ -1864,6 +1879,7 @@ metadata/_tab_index = 0
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Free Mode" unique_id=123456796]
|
||||
layout_mode = 2
|
||||
theme_override_colors/default_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
bbcode_enabled = true
|
||||
text = "[b]Free Mode[/b]
|
||||
|
||||
|
||||
@@ -501,6 +501,10 @@ func set_character(character_name: String) -> void:
|
||||
if active_character:
|
||||
_apply_outline_recursive(active_character)
|
||||
|
||||
# Apply cosmetic loadout to active model (local auth only)
|
||||
if active_character and is_multiplayer_authority():
|
||||
apply_loadout(active_character)
|
||||
|
||||
func _apply_outline_recursive(node: Node):
|
||||
if node is MeshInstance3D and node.mesh:
|
||||
for i in range(node.mesh.get_surface_count()):
|
||||
@@ -517,6 +521,22 @@ func _apply_outline_recursive(node: Node):
|
||||
for child in node.get_children():
|
||||
_apply_outline_recursive(child)
|
||||
|
||||
func apply_loadout(character_node: Node3D) -> void:
|
||||
"""Apply equipped cosmetics from UserProfileManager.loadout onto the active character model.
|
||||
Items are expected as child nodes named matching the item ID (e.g. 'head_hat1', 'acc_glasses').
|
||||
All nodes in the cosmetic category groups are hidden first, then the equipped one is shown."""
|
||||
if not has_node("/root/UserProfileManager"):
|
||||
return
|
||||
|
||||
var loadout: Dictionary = UserProfileManager.loadout
|
||||
|
||||
for category in ["head", "costume", "glove", "accessory"]:
|
||||
var equipped: String = loadout.get(category, "")
|
||||
for child in character_node.get_children():
|
||||
# Only manage nodes that start with the category prefix
|
||||
if child.name.begins_with(category):
|
||||
child.visible = (child.name == equipped)
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_character(character_name: String) -> void:
|
||||
"""Sync character selection across all clients."""
|
||||
|
||||
@@ -186,12 +186,14 @@ 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
|
||||
|
||||
+575
-192
@@ -2,19 +2,21 @@
|
||||
|
||||
[ext_resource type="Script" uid="uid://y6wswtalyiho" path="res://scripts/ui/profile_panel.gd" id="1"]
|
||||
[ext_resource type="Theme" uid="uid://da337sh5qxi0s" path="res://assets/themes/ui_theme.tres" id="2"]
|
||||
[ext_resource type="FontFile" uid="uid://xnjx058n4tsw" path="res://assets/fonts/Nougat-ExtraBlack.ttf" id="3_e13i6"]
|
||||
[ext_resource type="Texture2D" uid="uid://2d1ks5pmblc7" path="res://assets/graphics/main_menu/bg_back.png" id="3_0vpw4"]
|
||||
[ext_resource type="FontFile" uid="uid://xnjx058n4tsw" path="res://assets/fonts/Nougat-ExtraBlack.ttf" id="3_font"]
|
||||
[ext_resource type="PackedScene" uid="uid://ejeamn0pyey4" path="res://assets/characters/Bob.glb" id="4_bob"]
|
||||
[ext_resource type="PackedScene" uid="uid://d4cul3w3wem5w" path="res://assets/characters/Gatot.glb" id="4_gatot"]
|
||||
[ext_resource type="PackedScene" uid="uid://1vk0mjnwkngi" path="res://assets/characters/Masbro.glb" id="4_masbro"]
|
||||
[ext_resource type="PackedScene" uid="uid://bmln7v6v5kvxg" path="res://assets/characters/Oldpop.glb" id="4_oldpop"]
|
||||
[ext_resource type="Texture2D" uid="uid://brhn1dhp1gm13" path="res://assets/graphics/character_selection/sc_characters/sc_copper.png" id="4_pti1t"]
|
||||
[ext_resource type="AnimationLibrary" uid="uid://c3pyopnwibckj" path="res://assets/characters/animations/animation-pack.res" id="5_animlib"]
|
||||
|
||||
[sub_resource type="Environment" id="Environment_preview"]
|
||||
[sub_resource type="Environment" id="Env_preview"]
|
||||
background_mode = 1
|
||||
background_color = Color(0.08, 0.09, 0.12, 1)
|
||||
background_color = Color(0.06, 0.07, 0.1, 1)
|
||||
ambient_light_source = 2
|
||||
ambient_light_color = Color(0.6, 0.65, 0.8, 1)
|
||||
ambient_light_energy = 0.6
|
||||
ambient_light_color = Color(0.55, 0.65, 0.9, 1)
|
||||
ambient_light_energy = 0.7
|
||||
|
||||
[node name="ProfilePanel" type="Control" unique_id=229091481]
|
||||
layout_mode = 3
|
||||
@@ -26,367 +28,748 @@ grow_vertical = 2
|
||||
theme = ExtResource("2")
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Background" type="ColorRect" parent="." unique_id=650894265]
|
||||
[node name="Background" type="ColorRect" parent="." unique_id=1526402211]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0.05, 0.06, 0.09, 0.97)
|
||||
color = Color(0.0627451, 0.0745098, 0.101961, 1)
|
||||
|
||||
[node name="MainLayout" type="HBoxContainer" parent="." unique_id=730259035]
|
||||
[node name="Background2" type="TextureRect" parent="." unique_id=1984021675]
|
||||
modulate = Color(1, 1, 1, 0.28235295)
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/separation = 0
|
||||
texture = ExtResource("3_0vpw4")
|
||||
expand_mode = 2
|
||||
|
||||
[node name="LeftPanel" type="PanelContainer" parent="MainLayout" unique_id=282453419]
|
||||
custom_minimum_size = Vector2(420, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
[node name="MainMargin" type="MarginContainer" parent="." unique_id=949618423]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/margin_left = 30
|
||||
theme_override_constants/margin_top = 30
|
||||
theme_override_constants/margin_right = 30
|
||||
theme_override_constants/margin_bottom = 30
|
||||
|
||||
[node name="LeftVBox" type="VBoxContainer" parent="MainLayout/LeftPanel" unique_id=322585038]
|
||||
[node name="MainHBox" type="HBoxContainer" parent="MainMargin" unique_id=1978926863]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="Header" type="HBoxContainer" parent="MainLayout/LeftPanel/LeftVBox" unique_id=1587238635]
|
||||
[node name="LeftCol" type="VBoxContainer" parent="MainMargin/MainHBox" unique_id=843498295]
|
||||
custom_minimum_size = Vector2(240, 0)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="ProfileCard" type="PanelContainer" parent="MainMargin/MainHBox/LeftCol" unique_id=1335998802]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="BackBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/Header" unique_id=303437283]
|
||||
[node name="Margin" type="MarginContainer" parent="MainMargin/MainHBox/LeftCol/ProfileCard" unique_id=854167006]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin" unique_id=2103985860]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="AvatarDisplay" type="TextureRect" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin/HBox" unique_id=2014103516]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "← BACK"
|
||||
|
||||
[node name="Title" type="Label" parent="MainLayout/LeftPanel/LeftVBox/Header" unique_id=1630320969]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(0.41568628, 0.6392157, 0.14117648, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "PROFILE & LOADOUT"
|
||||
|
||||
[node name="Separator0" type="HSeparator" parent="MainLayout/LeftPanel/LeftVBox" unique_id=1757294445]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AvatarSection" type="HBoxContainer" parent="MainLayout/LeftPanel/LeftVBox" unique_id=579456932]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="AvatarDisplay" type="TextureRect" parent="MainLayout/LeftPanel/LeftVBox/AvatarSection" unique_id=1604724524]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(80, 80)
|
||||
custom_minimum_size = Vector2(100, 100)
|
||||
layout_mode = 2
|
||||
texture = ExtResource("4_pti1t")
|
||||
expand_mode = 1
|
||||
stretch_mode = 5
|
||||
|
||||
[node name="AvatarButtons" type="VBoxContainer" parent="MainLayout/LeftPanel/LeftVBox/AvatarSection" unique_id=208948821]
|
||||
[node name="VBox" type="VBoxContainer" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin/HBox" unique_id=1314733992]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 8
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="AccountType" type="Label" parent="MainLayout/LeftPanel/LeftVBox/AvatarSection/AvatarButtons" unique_id=1334846162]
|
||||
[node name="NameRow" type="HBoxContainer" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin/HBox/VBox" unique_id=286365590]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 4
|
||||
|
||||
[node name="DisplayNameInput" type="LineEdit" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin/HBox/VBox/NameRow" unique_id=918086953]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.69, 0.529, 0.357, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Account: Guest"
|
||||
|
||||
[node name="ChangeAvatarBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/AvatarSection/AvatarButtons" unique_id=215076479]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 40)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Change Avatar"
|
||||
|
||||
[node name="DisplayNameSection" type="VBoxContainer" parent="MainLayout/LeftPanel/LeftVBox" unique_id=1669216784]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="Label" type="Label" parent="MainLayout/LeftPanel/LeftVBox/DisplayNameSection" unique_id=792928394]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.69, 0.529, 0.357, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Display Name"
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="MainLayout/LeftPanel/LeftVBox/DisplayNameSection" unique_id=1713677971]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="DisplayNameInput" type="LineEdit" parent="MainLayout/LeftPanel/LeftVBox/DisplayNameSection/HBox" unique_id=1087692485]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
custom_minimum_size = Vector2(100, 32)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
max_length = 50
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
placeholder_text = "Username"
|
||||
max_length = 6
|
||||
|
||||
[node name="SaveNameBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/DisplayNameSection/HBox" unique_id=518731018]
|
||||
[node name="SaveNameBtn" type="Button" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin/HBox/VBox/NameRow" unique_id=856176583]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(80, 44)
|
||||
custom_minimum_size = Vector2(48, 32)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Save"
|
||||
|
||||
[node name="Separator1" type="HSeparator" parent="MainLayout/LeftPanel/LeftVBox" unique_id=2142486834]
|
||||
[node name="ChangeAvatarBtn" type="Button" parent="MainMargin/MainHBox/LeftCol/ProfileCard/Margin/HBox/VBox" unique_id=1415839292]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 28)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Change Avatar"
|
||||
|
||||
[node name="CurrencyRow" type="HBoxContainer" parent="MainMargin/MainHBox/LeftCol" unique_id=23456385]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="StarPanel" type="PanelContainer" parent="MainMargin/MainHBox/LeftCol/CurrencyRow" unique_id=1253486930]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/StarPanel" unique_id=1653822675]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LoadoutSection" type="VBoxContainer" parent="MainLayout/LeftPanel/LeftVBox" unique_id=109456880]
|
||||
[node name="HBox" type="HBoxContainer" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/StarPanel/Margin" unique_id=304844268]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="LoadoutTitle" type="Label" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection" unique_id=1249647867]
|
||||
[node name="Icon" type="Label" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/StarPanel/Margin/HBox" unique_id=1733501]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.41568628, 0.6392157, 0.14117648, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
theme_override_colors/font_color = Color(0.9, 0.7, 0.3, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "DEFAULT CHARACTER (LOADOUT)"
|
||||
text = "✦"
|
||||
|
||||
[node name="LoadoutHint" type="Label" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection" unique_id=1773015369]
|
||||
[node name="StarLabel" type="Label" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/StarPanel/Margin/HBox" unique_id=1536697694]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.6, 0.6, 0.6, 1)
|
||||
theme_override_font_sizes/font_size = 11
|
||||
text = "This character will be auto-selected when you join or create a room."
|
||||
autowrap_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "0"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="CharacterSelector" type="HBoxContainer" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection" unique_id=1852188787]
|
||||
[node name="GoldPanel" type="PanelContainer" parent="MainMargin/MainHBox/LeftCol/CurrencyRow" unique_id=289720528]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/GoldPanel" unique_id=1374150600]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/GoldPanel/Margin" unique_id=1558907810]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
alignment = 1
|
||||
|
||||
[node name="CharLeftBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection/CharacterSelector" unique_id=1225290843]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
[node name="Icon" type="Label" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/GoldPanel/Margin/HBox" unique_id=351462654]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "◀"
|
||||
theme_override_colors/font_color = Color(0.8, 0.6, 0.2, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "▤"
|
||||
|
||||
[node name="LoadoutCharName" type="Label" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection/CharacterSelector" unique_id=1258961866]
|
||||
[node name="GoldLabel" type="Label" parent="MainMargin/MainHBox/LeftCol/CurrencyRow/GoldPanel/Margin/HBox" unique_id=1517793393]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(120, 44)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Copper"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
text = "0"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="CharRightBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection/CharacterSelector" unique_id=320910811]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "▶"
|
||||
|
||||
[node name="SetDefaultBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/LoadoutSection" unique_id=1404065032]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "✓ SET AS DEFAULT"
|
||||
|
||||
[node name="Separator2" type="HSeparator" parent="MainLayout/LeftPanel/LeftVBox" unique_id=565201523]
|
||||
[node name="StatsPanel" type="PanelContainer" parent="MainMargin/MainHBox/LeftCol" unique_id=1663081199]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="StatsSection" type="VBoxContainer" parent="MainLayout/LeftPanel/LeftVBox" unique_id=1747237537]
|
||||
[node name="Margin" type="MarginContainer" parent="MainMargin/MainHBox/LeftCol/StatsPanel" unique_id=1581044063]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 6
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="StatsTitle" type="Label" parent="MainLayout/LeftPanel/LeftVBox/StatsSection" unique_id=1171799022]
|
||||
[node name="VBox" type="VBoxContainer" parent="MainMargin/MainHBox/LeftCol/StatsPanel/Margin" unique_id=73009603]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.41568628, 0.6392157, 0.14117648, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Statistics"
|
||||
theme_override_constants/separation = 4
|
||||
|
||||
[node name="GamesPlayed" type="Label" parent="MainLayout/LeftPanel/LeftVBox/StatsSection" unique_id=440203237]
|
||||
[node name="AccountType" type="Label" parent="MainMargin/MainHBox/LeftCol/StatsPanel/Margin/VBox" unique_id=1583438808]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.57, 0.32090998, 0.1767, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Games Played: 0"
|
||||
theme_override_colors/font_color = Color(0.7, 0.5, 0.3, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 13
|
||||
text = "Account : Email"
|
||||
|
||||
[node name="WinRate" type="Label" parent="MainLayout/LeftPanel/LeftVBox/StatsSection" unique_id=1940835558]
|
||||
[node name="LinkAccountBtn" type="Button" parent="MainMargin/MainHBox/LeftCol/StatsPanel/Margin/VBox" unique_id=779455472]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Link Email"
|
||||
|
||||
[node name="GamesPlayed" type="Label" parent="MainMargin/MainHBox/LeftCol/StatsPanel/Margin/VBox" unique_id=279949601]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.57, 0.32090998, 0.1767, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Win Rate: 0%"
|
||||
theme_override_colors/font_color = Color(0.8, 0.65, 0.45, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 13
|
||||
text = "Games Played: 8"
|
||||
|
||||
[node name="HighScore" type="Label" parent="MainLayout/LeftPanel/LeftVBox/StatsSection" unique_id=12845342]
|
||||
[node name="WinRate" type="Label" parent="MainMargin/MainHBox/LeftCol/StatsPanel/Margin/VBox" unique_id=1698973042]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.57, 0.32090998, 0.1767, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "High Score: 0"
|
||||
theme_override_colors/font_color = Color(0.8, 0.65, 0.45, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 13
|
||||
text = "Win Rate: 62.5%"
|
||||
|
||||
[node name="AccountSection" type="HBoxContainer" parent="MainLayout/LeftPanel/LeftVBox" unique_id=1267378790]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="LinkAccountBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/AccountSection" unique_id=1126355767]
|
||||
[node name="HighScore" type="Label" parent="MainMargin/MainHBox/LeftCol/StatsPanel/Margin/VBox" unique_id=1418839301]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Link Email (Keep Progress)"
|
||||
theme_override_colors/font_color = Color(0.8, 0.65, 0.45, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 13
|
||||
text = "High Score: 14050"
|
||||
|
||||
[node name="AdminPanelBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/AccountSection" unique_id=987654321]
|
||||
[node name="Spacer" type="Control" parent="MainMargin/MainHBox/LeftCol" unique_id=899023204]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="AccSettingsBtn" type="Button" parent="MainMargin/MainHBox/LeftCol" unique_id=114904148]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Account Setting"
|
||||
|
||||
[node name="AdminPanelBtn" type="Button" parent="MainMargin/MainHBox/LeftCol" unique_id=1155262037]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(1, 0.4, 0.4, 1)
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
text = "Server Admin Panel"
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Server Admin"
|
||||
|
||||
[node name="LogoutBtn" type="Button" parent="MainLayout/LeftPanel/LeftVBox/AccountSection" unique_id=1741557407]
|
||||
[node name="LogoutBtn" type="Button" parent="MainMargin/MainHBox/LeftCol" unique_id=612591334]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_e13i6")
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Logout"
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="MainLayout/LeftPanel/LeftVBox" unique_id=188332146]
|
||||
[node name="StatusLabel" type="Label" parent="MainMargin/MainHBox/LeftCol" unique_id=1531937007]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 12
|
||||
theme_override_font_sizes/font_size = 11
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="RightPanel" type="SubViewportContainer" parent="MainLayout" unique_id=2313053]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
[node name="BackBtn" type="Button" parent="MainMargin/MainHBox/LeftCol" unique_id=2005161566]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(56, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "←"
|
||||
|
||||
[node name="CenterCol" type="VBoxContainer" parent="MainMargin/MainHBox" unique_id=1176098048]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 1.2
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="CategoryTabs" type="HBoxContainer" parent="MainMargin/MainHBox/CenterCol" unique_id=1050731335]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
alignment = 1
|
||||
|
||||
[node name="HeadTabBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/CategoryTabs" unique_id=767008262]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 28
|
||||
text = "🎩"
|
||||
|
||||
[node name="CostumeTabBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/CategoryTabs" unique_id=73958290]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 28
|
||||
text = "👔"
|
||||
|
||||
[node name="GloveTabBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/CategoryTabs" unique_id=204746295]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 28
|
||||
text = "🧤"
|
||||
|
||||
[node name="AccTabBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/CategoryTabs" unique_id=1885872464]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 28
|
||||
text = "💎"
|
||||
|
||||
[node name="ViewportWrapper" type="Control" parent="MainMargin/MainHBox/CenterCol" unique_id=1095002692]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ViewportContainer" type="SubViewportContainer" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper" unique_id=1062885163]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
stretch = true
|
||||
|
||||
[node name="PreviewViewport" type="SubViewport" parent="MainLayout/RightPanel" unique_id=2118325644]
|
||||
[node name="PreviewViewport" type="SubViewport" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer" unique_id=724440223]
|
||||
unique_name_in_owner = true
|
||||
own_world_3d = true
|
||||
transparent_bg = true
|
||||
handle_input_locally = false
|
||||
size = Vector2i(746, 720)
|
||||
size = Vector2i(627, 487)
|
||||
render_target_update_mode = 4
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="MainLayout/RightPanel/PreviewViewport" unique_id=1213356390]
|
||||
environment = SubResource("Environment_preview")
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport" unique_id=1660814495]
|
||||
environment = SubResource("Env_preview")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MainLayout/RightPanel/PreviewViewport" unique_id=524977852]
|
||||
transform = Transform3D(0.866025, -0.25, 0.433013, 0, 0.866025, 0.5, -0.5, -0.433013, 0.75, 0, 4, 0)
|
||||
light_energy = 1.4
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport" unique_id=1722256175]
|
||||
transform = Transform3D(0.866025, -0.25, 0.433013, 0, 0.866025, 0.5, -0.5, -0.433013, 0.75, 1, 4, 0)
|
||||
light_energy = 1.5
|
||||
|
||||
[node name="FillLight" type="OmniLight3D" parent="MainLayout/RightPanel/PreviewViewport" unique_id=1512907756]
|
||||
[node name="FillLight" type="OmniLight3D" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport" unique_id=1283982748]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 2, 2)
|
||||
light_color = Color(0.5, 0.6, 1, 1)
|
||||
light_energy = 0.5
|
||||
omni_range = 8.0
|
||||
light_color = Color(0.4, 0.55, 1, 1)
|
||||
light_energy = 0.6
|
||||
omni_range = 10.0
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="MainLayout/RightPanel/PreviewViewport" unique_id=1682800090]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.965926, 0.258819, 0, -0.258819, 0.965926, 0, 1.6, 3.2)
|
||||
[node name="Camera3D" type="Camera3D" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport" unique_id=1696846826]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.97072834, 0.2401802, 0, -0.2401802, 0.97072834, 0, 0.8262464, 2.6238613)
|
||||
current = true
|
||||
fov = 40.0
|
||||
fov = 38.0
|
||||
|
||||
[node name="CharacterRoot" type="Node3D" parent="MainLayout/RightPanel/PreviewViewport" unique_id=687534677]
|
||||
[node name="CharacterRoot" type="Node3D" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport" unique_id=1793550534]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(0.6587157, 0, 0.75239193, 0, 1, 0, -0.75239193, 0, 0.6587157, 0, 0.7540468, 0)
|
||||
|
||||
[node name="Masbro" parent="MainLayout/RightPanel/PreviewViewport/CharacterRoot" unique_id=48482236 instance=ExtResource("4_masbro")]
|
||||
[node name="Masbro" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport/CharacterRoot" unique_id=2118952077 instance=ExtResource("4_masbro")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.485, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Bob" parent="MainLayout/RightPanel/PreviewViewport/CharacterRoot" unique_id=1951694644 instance=ExtResource("4_bob")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.484627, 0)
|
||||
[node name="Bob" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport/CharacterRoot" unique_id=1510408045 instance=ExtResource("4_bob")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.484, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Gatot" parent="MainLayout/RightPanel/PreviewViewport/CharacterRoot" unique_id=1852101135 instance=ExtResource("4_gatot")]
|
||||
[node name="Gatot" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport/CharacterRoot" unique_id=340292178 instance=ExtResource("4_gatot")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.485, 0)
|
||||
visible = false
|
||||
|
||||
[node name="Oldpop" parent="MainLayout/RightPanel/PreviewViewport/CharacterRoot" unique_id=812849337 instance=ExtResource("4_oldpop")]
|
||||
[node name="Oldpop" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport/CharacterRoot" unique_id=1591549997 instance=ExtResource("4_oldpop")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.485, 0)
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="MainLayout/RightPanel/PreviewViewport/CharacterRoot" unique_id=4187871]
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper/ViewportContainer/PreviewViewport/CharacterRoot" unique_id=1330912730]
|
||||
unique_name_in_owner = true
|
||||
root_node = NodePath("../Oldpop")
|
||||
libraries/animation-pack = ExtResource("5_animlib")
|
||||
autoplay = &"animation-pack/idle"
|
||||
|
||||
[node name="AvatarSelectionPopup" type="PopupPanel" parent="." unique_id=1186892858]
|
||||
[node name="DragZone" type="Control" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper" unique_id=1365789190]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="DragHint" type="Label" parent="MainMargin/MainHBox/CenterCol/ViewportWrapper" unique_id=272858156]
|
||||
layout_mode = 1
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -76.5
|
||||
offset_top = -38.0
|
||||
offset_right = 77.5
|
||||
offset_bottom = -14.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 0.2)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "← drag to rotate →"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="BottomControls" type="VBoxContainer" parent="MainMargin/MainHBox/CenterCol" unique_id=1513522557]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_constants/separation = 4
|
||||
|
||||
[node name="CharSelectorRow" type="HBoxContainer" parent="MainMargin/MainHBox/CenterCol/BottomControls" unique_id=1642710720]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 8
|
||||
alignment = 1
|
||||
|
||||
[node name="CharLeftBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/BottomControls/CharSelectorRow" unique_id=1911454313]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(40, 36)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "◀"
|
||||
|
||||
[node name="LoadoutCharName" type="Label" parent="MainMargin/MainHBox/CenterCol/BottomControls/CharSelectorRow" unique_id=1417186267]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(90, 36)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Dabro"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="CharRightBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/BottomControls/CharSelectorRow" unique_id=254943219]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(40, 36)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "▶"
|
||||
|
||||
[node name="SetDefaultBtn" type="Button" parent="MainMargin/MainHBox/CenterCol/BottomControls" unique_id=73462951]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 36)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "Set as Default"
|
||||
|
||||
[node name="RightCol" type="VBoxContainer" parent="MainMargin/MainHBox" unique_id=857477144]
|
||||
custom_minimum_size = Vector2(300, 0)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="ItemInfoCard" type="PanelContainer" parent="MainMargin/MainHBox/RightCol" unique_id=1009501358]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="MainMargin/MainHBox/RightCol/ItemInfoCard" unique_id=663473404]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin" unique_id=749660081]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="PreviewBorder" type="PanelContainer" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox" unique_id=501514249]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ItemPreview" type="TextureRect" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/PreviewBorder" unique_id=1738821483]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(64, 64)
|
||||
layout_mode = 2
|
||||
expand_mode = 1
|
||||
stretch_mode = 5
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox" unique_id=953647763]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="ItemNameLabel" type="Label" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox" unique_id=1127187232]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Cute Hat"
|
||||
|
||||
[node name="RarityPriceRow" type="HBoxContainer" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox" unique_id=336105315]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ItemRarityLabel" type="Label" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox/RarityPriceRow" unique_id=1170021429]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(0.7, 0.3, 1, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 12
|
||||
text = "Epic"
|
||||
|
||||
[node name="ItemPriceIcon" type="Label" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox/RarityPriceRow" unique_id=1881961667]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.9, 0.7, 0.3, 1)
|
||||
theme_override_font_sizes/font_size = 12
|
||||
text = "✦"
|
||||
|
||||
[node name="ItemPriceLabel" type="Label" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox/RarityPriceRow" unique_id=1837607820]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.5686275, 0.36862746, 0.12941177, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 12
|
||||
text = "1500"
|
||||
|
||||
[node name="ActionsRow" type="HBoxContainer" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox" unique_id=1252309476]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="EquipBtn" type="Button" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox/ActionsRow" unique_id=1276164880]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 30)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "Equip"
|
||||
|
||||
[node name="DismantleBtn" type="Button" parent="MainMargin/MainHBox/RightCol/ItemInfoCard/Margin/HBox/VBox/ActionsRow" unique_id=1451515715]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 30)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_colors/font_color = Color(1, 0.4, 0.4, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "Dismantle"
|
||||
|
||||
[node name="ItemGridCard" type="PanelContainer" parent="MainMargin/MainHBox/RightCol" unique_id=748947828]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="MainMargin/MainHBox/RightCol/ItemGridCard" unique_id=2047178434]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin" unique_id=553633431]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="ItemGrid" type="GridContainer" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox" unique_id=2005677714]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/h_separation = 8
|
||||
theme_override_constants/v_separation = 8
|
||||
columns = 3
|
||||
|
||||
[node name="Slot0" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=1964986286]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot1" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=1570438748]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot2" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=1730218687]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot3" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=533222646]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot4" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=1359133451]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot5" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=212812652]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot6" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=464526955]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot7" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=87751984]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Slot8" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/ItemGrid" unique_id=1866702419]
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="Pagination" type="HBoxContainer" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox" unique_id=1821323993]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
alignment = 1
|
||||
|
||||
[node name="PrevPageBtn" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/Pagination" unique_id=78956964]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(32, 32)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "◀"
|
||||
|
||||
[node name="PageLabel" type="Label" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/Pagination" unique_id=1014922888]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(80, 32)
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.9, 0.7, 0.3, 1)
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "1"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="NextPageBtn" type="Button" parent="MainMargin/MainHBox/RightCol/ItemGridCard/Margin/VBox/Pagination" unique_id=1618583973]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(32, 32)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("3_font")
|
||||
text = "▶"
|
||||
|
||||
[node name="DismantleConfirmDialog" type="ConfirmationDialog" parent="." unique_id=234823811]
|
||||
unique_name_in_owner = true
|
||||
title = "Confirm Dismantle"
|
||||
size = Vector2i(320, 120)
|
||||
|
||||
[node name="ResetStatsConfirmDialog" type="ConfirmationDialog" parent="." unique_id=98723485]
|
||||
unique_name_in_owner = true
|
||||
size = Vector2i(320, 120)
|
||||
dialog_text = "Wipe ALL stats to 0? This cannot be undone."
|
||||
|
||||
[node name="LinkEmailDialog" type="AcceptDialog" parent="." unique_id=128913898]
|
||||
unique_name_in_owner = true
|
||||
title = "Link Email"
|
||||
size = Vector2i(320, 160)
|
||||
dialog_text = "Link this guest account to an email."
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="LinkEmailDialog" unique_id=3456345]
|
||||
offset_left = 8.0
|
||||
offset_top = 8.0
|
||||
offset_right = 312.0
|
||||
offset_bottom = 111.0
|
||||
|
||||
[node name="LinkEmailInput" type="LineEdit" parent="LinkEmailDialog/VBox" unique_id=8712361]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "Email Address"
|
||||
|
||||
[node name="LinkPassInput" type="LineEdit" parent="LinkEmailDialog/VBox" unique_id=64356434]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "Password"
|
||||
secret = true
|
||||
|
||||
[node name="AvatarSelectionPopup" type="PopupPanel" parent="." unique_id=1466095185]
|
||||
unique_name_in_owner = true
|
||||
oversampling_override = 1.0
|
||||
title = "Select Avatar"
|
||||
size = Vector2i(320, 220)
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="AvatarSelectionPopup" unique_id=1871925487]
|
||||
[node name="GridContainer" type="GridContainer" parent="AvatarSelectionPopup" unique_id=119483729]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = 4.0
|
||||
offset_top = 4.0
|
||||
offset_right = 316.0
|
||||
offset_bottom = 216.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
columns = 3
|
||||
|
||||
[node name="AccountSettingsDialog" type="AcceptDialog" parent="." unique_id=987000001]
|
||||
[node name="AvatarBtn0" type="Button" parent="AvatarSelectionPopup/GridContainer" unique_id=45239452]
|
||||
custom_minimum_size = Vector2(62, 62)
|
||||
layout_mode = 2
|
||||
expand_icon = true
|
||||
|
||||
[node name="AvatarBtn1" type="Button" parent="AvatarSelectionPopup/GridContainer" unique_id=12401825]
|
||||
custom_minimum_size = Vector2(62, 62)
|
||||
layout_mode = 2
|
||||
expand_icon = true
|
||||
|
||||
[node name="AvatarBtn2" type="Button" parent="AvatarSelectionPopup/GridContainer" unique_id=98357285]
|
||||
custom_minimum_size = Vector2(62, 62)
|
||||
layout_mode = 2
|
||||
expand_icon = true
|
||||
|
||||
[node name="AvatarBtn3" type="Button" parent="AvatarSelectionPopup/GridContainer" unique_id=18498453]
|
||||
custom_minimum_size = Vector2(62, 62)
|
||||
layout_mode = 2
|
||||
expand_icon = true
|
||||
|
||||
[node name="AccountSettingsDialog" type="AcceptDialog" parent="." unique_id=1862558949]
|
||||
unique_name_in_owner = true
|
||||
title = "Account Settings"
|
||||
size = Vector2i(360, 480)
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="AccountSettingsDialog" unique_id=987000002]
|
||||
[node name="VBox" type="VBoxContainer" parent="AccountSettingsDialog" unique_id=608788631]
|
||||
offset_left = 8.0
|
||||
offset_top = 8.0
|
||||
offset_right = 352.0
|
||||
offset_bottom = 431.0
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="CredTitle" type="Label" parent="AccountSettingsDialog/VBox" unique_id=987000003]
|
||||
[node name="CredTitle" type="Label" parent="AccountSettingsDialog/VBox" unique_id=947368044]
|
||||
layout_mode = 2
|
||||
text = "Update Credentials"
|
||||
|
||||
[node name="OldPassInput" type="LineEdit" parent="AccountSettingsDialog/VBox" unique_id=987000004]
|
||||
[node name="OldPassInput" type="LineEdit" parent="AccountSettingsDialog/VBox" unique_id=187554107]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "Current Password"
|
||||
secret = true
|
||||
|
||||
[node name="NewEmailInput" type="LineEdit" parent="AccountSettingsDialog/VBox" unique_id=987000005]
|
||||
[node name="NewEmailInput" type="LineEdit" parent="AccountSettingsDialog/VBox" unique_id=656070098]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "New Email"
|
||||
|
||||
[node name="NewPassInput" type="LineEdit" parent="AccountSettingsDialog/VBox" unique_id=987000006]
|
||||
[node name="NewPassInput" type="LineEdit" parent="AccountSettingsDialog/VBox" unique_id=1102941873]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "New Password"
|
||||
secret = true
|
||||
|
||||
[node name="SubmitCredBtn" type="Button" parent="AccountSettingsDialog/VBox" unique_id=987000007]
|
||||
[node name="SubmitCredBtn" type="Button" parent="AccountSettingsDialog/VBox" unique_id=214981590]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Submit Credentials"
|
||||
|
||||
[node name="HSeparator1" type="HSeparator" parent="AccountSettingsDialog/VBox" unique_id=987000008]
|
||||
[node name="HSeparator1" type="HSeparator" parent="AccountSettingsDialog/VBox" unique_id=2011703728]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TzLabel" type="Label" parent="AccountSettingsDialog/VBox" unique_id=987000009]
|
||||
[node name="TzLabel" type="Label" parent="AccountSettingsDialog/VBox" unique_id=1789076555]
|
||||
layout_mode = 2
|
||||
text = "Timezone"
|
||||
|
||||
[node name="TzDropdown" type="OptionButton" parent="AccountSettingsDialog/VBox" unique_id=987000010]
|
||||
[node name="TzDropdown" type="OptionButton" parent="AccountSettingsDialog/VBox" unique_id=2029336897]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SaveTzBtn" type="Button" parent="AccountSettingsDialog/VBox" unique_id=987000011]
|
||||
[node name="SaveTzBtn" type="Button" parent="AccountSettingsDialog/VBox" unique_id=821911571]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Save Timezone"
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="AccountSettingsDialog/VBox" unique_id=987000012]
|
||||
[node name="HSeparator2" type="HSeparator" parent="AccountSettingsDialog/VBox" unique_id=802671082]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ResetStatsBtn" type="Button" parent="AccountSettingsDialog/VBox" unique_id=987000013]
|
||||
[node name="ResetStatsBtn" type="Button" parent="AccountSettingsDialog/VBox" unique_id=1357708120]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(1, 0, 0, 1)
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
[gd_scene format=3 uid="uid://c018oue81jm44"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/shop_panel.gd" id="1"]
|
||||
|
||||
[node name="ShopPanel" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0.12, 0.12, 0.12, 0.95)
|
||||
|
||||
[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 = -300.0
|
||||
offset_top = -250.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 250.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Panel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Header" type="HBoxContainer" parent="Panel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="BackBtn" type="Button" parent="Panel/VBoxContainer/Header"]
|
||||
layout_mode = 2
|
||||
text = "Back"
|
||||
|
||||
[node name="Title" type="Label" parent="Panel/VBoxContainer/Header"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "SHOP"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="Panel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
current_tab = 0
|
||||
|
||||
[node name="Head" type="MarginContainer" parent="Panel/VBoxContainer/TabContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="Panel/VBoxContainer/TabContainer/Head"]
|
||||
layout_mode = 2
|
||||
columns = 3
|
||||
|
||||
[node name="Costume" type="MarginContainer" parent="Panel/VBoxContainer/TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="Panel/VBoxContainer/TabContainer/Costume"]
|
||||
layout_mode = 2
|
||||
columns = 3
|
||||
|
||||
[node name="Glove" type="MarginContainer" parent="Panel/VBoxContainer/TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="Panel/VBoxContainer/TabContainer/Glove"]
|
||||
layout_mode = 2
|
||||
columns = 3
|
||||
|
||||
[node name="Accessory" type="MarginContainer" parent="Panel/VBoxContainer/TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="Panel/VBoxContainer/TabContainer/Accessory"]
|
||||
layout_mode = 2
|
||||
columns = 3
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="Panel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Welcome to the Store!"
|
||||
horizontal_alignment = 1
|
||||
@@ -9,6 +9,9 @@ signal avatar_changed(url: String)
|
||||
# Profile data
|
||||
var profile: Dictionary = {}
|
||||
var stats: Dictionary = {}
|
||||
var wallet: Dictionary = {"gold": 0, "star": 0}
|
||||
var inventory: Array = []
|
||||
var loadout: Dictionary = {"head": "", "costume": "", "glove": "", "accessory": ""}
|
||||
var is_profile_loaded: bool = false
|
||||
|
||||
# Nakama storage collection names
|
||||
@@ -47,6 +50,8 @@ func load_profile() -> Dictionary:
|
||||
# Reset state first to ensure no old account data carries over
|
||||
profile = {}
|
||||
stats = {}
|
||||
wallet = {"gold": 0, "star": 0}
|
||||
inventory = []
|
||||
is_profile_loaded = false
|
||||
|
||||
if not NakamaManager.session:
|
||||
@@ -84,6 +89,18 @@ func load_profile() -> Dictionary:
|
||||
var stored_data = JSON.parse_string(storage_result.objects[0].value)
|
||||
if stored_data:
|
||||
profile.merge(stored_data, true)
|
||||
if stored_data.has("loadout"):
|
||||
loadout = stored_data["loadout"]
|
||||
|
||||
# Parse Wallet
|
||||
if account.wallet:
|
||||
var w_data = JSON.parse_string(account.wallet)
|
||||
if w_data:
|
||||
wallet["gold"] = w_data.get("gold", 0)
|
||||
wallet["star"] = w_data.get("star", 0)
|
||||
|
||||
# Load Inventory
|
||||
await load_inventory()
|
||||
|
||||
# Load stats
|
||||
await load_stats()
|
||||
@@ -98,6 +115,21 @@ func load_profile() -> Dictionary:
|
||||
|
||||
return profile
|
||||
|
||||
func load_inventory() -> void:
|
||||
if not NakamaManager.session: return
|
||||
|
||||
inventory.clear()
|
||||
var result = await NakamaManager.client.list_storage_objects_async(
|
||||
NakamaManager.session,
|
||||
"inventory",
|
||||
NakamaManager.session.user_id,
|
||||
100
|
||||
)
|
||||
|
||||
if not result.is_exception() and result.objects:
|
||||
for obj in result.objects:
|
||||
inventory.append(obj.key)
|
||||
|
||||
func load_stats() -> Dictionary:
|
||||
# Reset stats first to ensure fresh data for new logins
|
||||
stats = {}
|
||||
@@ -223,7 +255,8 @@ func _save_profile_data() -> bool:
|
||||
"avatar_index": profile.get("avatar_index", 0),
|
||||
"bio": profile.get("bio", ""),
|
||||
"country": profile.get("country", ""),
|
||||
"language": profile.get("language", "en")
|
||||
"language": profile.get("language", "en"),
|
||||
"loadout": loadout
|
||||
}
|
||||
|
||||
var write_obj := NakamaWriteStorageObject.new(
|
||||
@@ -247,6 +280,41 @@ func _save_profile_data() -> bool:
|
||||
emit_signal("profile_updated")
|
||||
return true
|
||||
|
||||
func update_loadout(category: String, item_id: String) -> bool:
|
||||
if not loadout.has(category):
|
||||
return false
|
||||
loadout[category] = item_id
|
||||
return await _save_profile_data()
|
||||
|
||||
func purchase_item(item_id: String, price_gold: int, price_star: int, category: String) -> bool:
|
||||
if not NakamaManager.session: return false
|
||||
|
||||
var payload = JSON.stringify({
|
||||
"item_id": item_id,
|
||||
"price_gold": price_gold,
|
||||
"price_star": price_star,
|
||||
"category": category
|
||||
})
|
||||
|
||||
var result = await NakamaManager.client.rpc_async(
|
||||
NakamaManager.session,
|
||||
"purchase_item",
|
||||
payload
|
||||
)
|
||||
|
||||
if result.is_exception():
|
||||
push_error("[UserProfileManager] Purchase failed: ", result.get_exception().message)
|
||||
return false
|
||||
|
||||
# Update local cache
|
||||
if price_gold > 0: wallet["gold"] -= price_gold
|
||||
if price_star > 0: wallet["star"] -= price_star
|
||||
if not inventory.has(item_id):
|
||||
inventory.append(item_id)
|
||||
|
||||
emit_signal("profile_updated")
|
||||
return true
|
||||
|
||||
# =============================================================================
|
||||
# Stats Management
|
||||
# =============================================================================
|
||||
|
||||
+400
-205
@@ -1,31 +1,61 @@
|
||||
extends Control
|
||||
## Profile panel controller — full-scene loadout screen.
|
||||
## Left: profile info + default character selector.
|
||||
## Right: 3D SubViewport character preview.
|
||||
## Profile panel — 3-column layout.
|
||||
## Left : profile card, currencies, stats, account buttons.
|
||||
## Center: category tabs overlay, 3D rotatable preview, char-selector overlay.
|
||||
## Right : item info card, 3×3 owned-item grid, pagination.
|
||||
|
||||
signal closed
|
||||
signal profile_updated
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# UI References
|
||||
# -------------------------------------------------------------------------
|
||||
@onready var back_btn := %BackBtn as Button
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# UI references (all resolved via %UniqueName — must match .tscn)
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
# Left column
|
||||
@onready var avatar_display := %AvatarDisplay as TextureRect
|
||||
@onready var change_avatar_btn := %ChangeAvatarBtn as Button
|
||||
@onready var display_name_input := %DisplayNameInput as LineEdit
|
||||
@onready var save_name_btn := %SaveNameBtn as Button
|
||||
@onready var change_avatar_btn := %ChangeAvatarBtn as Button
|
||||
@onready var account_type_label := %AccountType as Label
|
||||
@onready var link_account_btn := %LinkAccountBtn as Button
|
||||
@onready var gold_label := %GoldLabel as Label
|
||||
@onready var star_label := %StarLabel as Label
|
||||
@onready var games_played_label := %GamesPlayed as Label
|
||||
@onready var win_rate_label := %WinRate as Label
|
||||
@onready var high_score_label := %HighScore as Label
|
||||
@onready var account_type_label := %AccountType as Label
|
||||
@onready var link_account_btn := %LinkAccountBtn as Button
|
||||
@onready var acc_settings_btn := %AccSettingsBtn as Button
|
||||
@onready var admin_panel_btn := %AdminPanelBtn as Button
|
||||
@onready var logout_btn := %LogoutBtn as Button
|
||||
@onready var status_label := %StatusLabel as Label
|
||||
|
||||
# Center column (overlays inside CenterWrapper)
|
||||
@onready var head_tab_btn := %HeadTabBtn as Button
|
||||
@onready var costume_tab_btn := %CostumeTabBtn as Button
|
||||
@onready var glove_tab_btn := %GloveTabBtn as Button
|
||||
@onready var acc_tab_btn := %AccTabBtn as Button
|
||||
@onready var drag_zone := %DragZone as Control
|
||||
@onready var character_root := %CharacterRoot as Node3D
|
||||
@onready var char_left_btn := %CharLeftBtn as Button
|
||||
@onready var char_right_btn := %CharRightBtn as Button
|
||||
@onready var loadout_char_name := %LoadoutCharName as Label
|
||||
@onready var set_default_btn := %SetDefaultBtn as Button
|
||||
@onready var anim_player := %AnimationPlayer as AnimationPlayer
|
||||
# Right column
|
||||
@onready var item_preview := %ItemPreview as TextureRect
|
||||
@onready var item_name_label := %ItemNameLabel as Label
|
||||
@onready var item_rarity_label := %ItemRarityLabel as Label
|
||||
@onready var item_price_label := %ItemPriceLabel as Label
|
||||
@onready var equip_btn := %EquipBtn as Button
|
||||
@onready var dismantle_btn := %DismantleBtn as Button
|
||||
@onready var item_grid := %ItemGrid as GridContainer
|
||||
@onready var prev_page_btn := %PrevPageBtn as Button
|
||||
@onready var page_label := %PageLabel as Label
|
||||
@onready var next_page_btn := %NextPageBtn as Button
|
||||
|
||||
# Back button + popups
|
||||
@onready var back_btn := %BackBtn as Button
|
||||
@onready var avatar_popup := %AvatarSelectionPopup as PopupPanel
|
||||
@onready var avatar_grid := %GridContainer as GridContainer
|
||||
|
||||
# Account Settings refs
|
||||
@onready var acc_settings_dialog := %AccountSettingsDialog as AcceptDialog
|
||||
@onready var old_pass_input := %OldPassInput as LineEdit
|
||||
@onready var new_email_input := %NewEmailInput as LineEdit
|
||||
@@ -35,115 +65,292 @@ signal profile_updated
|
||||
@onready var save_tz_btn := %SaveTzBtn as Button
|
||||
@onready var reset_stats_btn := %ResetStatsBtn as Button
|
||||
|
||||
# Loadout refs
|
||||
@onready var char_left_btn := %CharLeftBtn as Button
|
||||
@onready var char_right_btn := %CharRightBtn as Button
|
||||
@onready var loadout_char_name := %LoadoutCharName as Label
|
||||
@onready var set_default_btn := %SetDefaultBtn as Button
|
||||
# New static popups
|
||||
@onready var dismantle_dialog := %DismantleConfirmDialog as ConfirmationDialog
|
||||
@onready var link_email_dialog := %LinkEmailDialog as AcceptDialog
|
||||
@onready var link_email_input := %LinkEmailInput as LineEdit
|
||||
@onready var link_pass_input := %LinkPassInput as LineEdit
|
||||
@onready var reset_stats_dialog := %ResetStatsConfirmDialog as ConfirmationDialog
|
||||
|
||||
# 3D Preview refs
|
||||
@onready var character_root := %CharacterRoot as Node3D
|
||||
@onready var anim_player: AnimationPlayer
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# State
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Constants
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
const CHARACTERS: Array[String] = ["Copper", "Dabro", "Gatot", "Pip"]
|
||||
# Maps game character name -> GLB node name in the SubViewport
|
||||
# Must match the mapping in player.gd's set_character()
|
||||
const CHAR_NODE_MAP: Dictionary = {
|
||||
"Copper": "Oldpop",
|
||||
"Dabro": "Masbro",
|
||||
"Gatot": "Gatot",
|
||||
"Pip": "Bob"
|
||||
}
|
||||
const RARITY_COLORS: Dictionary = {
|
||||
"Common": Color(0.80, 0.80, 0.80, 1),
|
||||
"Rare": Color(0.30, 0.60, 1.00, 1),
|
||||
"Epic": Color(0.70, 0.30, 1.00, 1),
|
||||
"Legendary": Color(1.00, 0.70, 0.10, 1)
|
||||
}
|
||||
## Client-side item catalog: item_id -> { name, rarity, star_value }
|
||||
const ITEM_CATALOG: Dictionary = {
|
||||
"head_hat1": {"name": "Cap", "rarity": "Common", "star_value": 50},
|
||||
"head_crown": {"name": "Crown", "rarity": "Epic", "star_value": 1500},
|
||||
"costume_red": {"name": "Red Suit", "rarity": "Rare", "star_value": 200},
|
||||
"costume_gold": {"name": "Gold Suit", "rarity": "Epic", "star_value": 1000},
|
||||
"glove_leather": {"name": "Leather Gloves", "rarity": "Common", "star_value": 50},
|
||||
"acc_glasses": {"name": "Sunglasses", "rarity": "Rare", "star_value": 300},
|
||||
}
|
||||
const ITEMS_PER_PAGE: int = 9
|
||||
|
||||
var _loadout_index: int = 0 # Index into CHARACTERS
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# State
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
var _loadout_index: int = 0
|
||||
var _default_character: String = "Copper"
|
||||
|
||||
var _current_category: String = "head"
|
||||
var _category_items: Array = []
|
||||
var _current_page: int = 0
|
||||
var _selected_item_id: String = ""
|
||||
var _item_slots: Array[Button] = []
|
||||
|
||||
# Drag-to-rotate
|
||||
var _drag_active: bool = false
|
||||
var _drag_start_x: float = 0.0
|
||||
var _model_yaw: float = 0.0
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Lifecycle
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _ready() -> void:
|
||||
_build_slot_refs()
|
||||
_connect_signals()
|
||||
_load_profile_data()
|
||||
_setup_avatar_grid()
|
||||
_setup_account_settings_ui()
|
||||
_load_profile_data()
|
||||
_load_loadout()
|
||||
_setup_3d_preview()
|
||||
_on_category_tab_pressed("head")
|
||||
|
||||
func _build_slot_refs() -> void:
|
||||
_item_slots.clear()
|
||||
for child in item_grid.get_children():
|
||||
if child is Button:
|
||||
_item_slots.append(child as Button)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Signal wiring
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _connect_signals() -> void:
|
||||
back_btn.pressed.connect(_on_close_pressed)
|
||||
change_avatar_btn.pressed.connect(_on_change_avatar_pressed)
|
||||
save_name_btn.pressed.connect(_on_save_name_pressed)
|
||||
link_account_btn.pressed.connect(_on_link_account_pressed)
|
||||
acc_settings_btn.pressed.connect(_open_account_settings)
|
||||
admin_panel_btn.pressed.connect(_on_admin_panel_pressed)
|
||||
logout_btn.pressed.connect(_on_logout_pressed)
|
||||
char_left_btn.pressed.connect(func(): _cycle_loadout_char(-1))
|
||||
char_right_btn.pressed.connect(func(): _cycle_loadout_char(1))
|
||||
set_default_btn.pressed.connect(_on_set_default_pressed)
|
||||
|
||||
UserProfileManager.profile_loaded.connect(func(p): _on_profile_updated())
|
||||
# Category tabs
|
||||
head_tab_btn.pressed.connect(func(): _on_category_tab_pressed("head"))
|
||||
costume_tab_btn.pressed.connect(func(): _on_category_tab_pressed("costume"))
|
||||
glove_tab_btn.pressed.connect(func(): _on_category_tab_pressed("glove"))
|
||||
acc_tab_btn.pressed.connect(func(): _on_category_tab_pressed("accessory"))
|
||||
|
||||
# Item grid slot buttons
|
||||
for i in _item_slots.size():
|
||||
_item_slots[i].pressed.connect(_on_slot_pressed.bind(i))
|
||||
|
||||
equip_btn.pressed.connect(_on_equip_pressed)
|
||||
dismantle_btn.pressed.connect(_on_dismantle_pressed)
|
||||
dismantle_dialog.confirmed.connect(_on_dismantle_confirmed)
|
||||
link_email_dialog.confirmed.connect(_on_link_account_confirmed)
|
||||
reset_stats_dialog.confirmed.connect(_on_reset_stats_confirmed)
|
||||
prev_page_btn.pressed.connect(_on_prev_page)
|
||||
next_page_btn.pressed.connect(_on_next_page)
|
||||
|
||||
drag_zone.gui_input.connect(_on_drag_input)
|
||||
|
||||
if UserProfileManager.profile_loaded.connect(func(_p): _on_profile_updated()) != OK:
|
||||
push_warning("[ProfilePanel] Could not connect profile_loaded")
|
||||
UserProfileManager.profile_updated.connect(_on_profile_updated)
|
||||
UserProfileManager.profile_update_failed.connect(_on_profile_update_failed)
|
||||
|
||||
# Dynamically inject Account Settings button
|
||||
var acc_settings_btn = Button.new()
|
||||
acc_settings_btn.text = "Account Settings"
|
||||
acc_settings_btn.custom_minimum_size = Vector2(0, 44)
|
||||
acc_settings_btn.add_theme_font_override("font", load("res://assets/fonts/Nougat-ExtraBlack.ttf"))
|
||||
acc_settings_btn.pressed.connect(_open_account_settings)
|
||||
# Insert it before Logout button
|
||||
var logout_idx = logout_btn.get_index()
|
||||
logout_btn.get_parent().add_child(acc_settings_btn)
|
||||
logout_btn.get_parent().move_child(acc_settings_btn, logout_idx)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Profile
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Profile data
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _load_profile_data() -> void:
|
||||
var profile := UserProfileManager.profile
|
||||
var prof := UserProfileManager.profile
|
||||
var stats := UserProfileManager.stats
|
||||
|
||||
display_name_input.text = profile.get("display_name", "Guest")
|
||||
display_name_input.text = prof.get("display_name", "")
|
||||
display_name_input.max_length = 6
|
||||
|
||||
var avatar_url: String = UserProfileManager.get_avatar_url()
|
||||
if ResourceLoader.exists(avatar_url):
|
||||
avatar_display.texture = load(avatar_url)
|
||||
var url: String = UserProfileManager.get_avatar_url()
|
||||
if ResourceLoader.exists(url):
|
||||
avatar_display.texture = load(url) as Texture2D
|
||||
|
||||
games_played_label.text = "Games Played: %d" % stats.get("games_played", 0)
|
||||
win_rate_label.text = "Win Rate: %.1f%%" % UserProfileManager.get_win_rate()
|
||||
high_score_label.text = "High Score: %d" % stats.get("high_score", 0)
|
||||
|
||||
gold_label.text = str(UserProfileManager.wallet.get("gold", 0))
|
||||
star_label.text = str(UserProfileManager.wallet.get("star", 0))
|
||||
|
||||
if AuthManager.is_guest:
|
||||
account_type_label.text = "Account : Guest"
|
||||
link_account_btn.visible = true
|
||||
link_account_btn.text = "Link Email (Keep Progress)"
|
||||
else:
|
||||
var mode_name := _get_auth_mode_name(AuthManager.auth_mode)
|
||||
account_type_label.text = "Account: %s" % mode_name
|
||||
account_type_label.text = "Account : %s" % _auth_mode_name(AuthManager.auth_mode)
|
||||
link_account_btn.visible = false
|
||||
|
||||
status_label.text = ""
|
||||
|
||||
func _get_auth_mode_name(mode: int) -> String:
|
||||
func _auth_mode_name(mode: int) -> String:
|
||||
match mode:
|
||||
AuthManager.AuthMode.EMAIL:
|
||||
return "Email"
|
||||
AuthManager.AuthMode.GOOGLE:
|
||||
return "Google"
|
||||
AuthManager.AuthMode.APPLE:
|
||||
return "Apple"
|
||||
AuthManager.AuthMode.FACEBOOK:
|
||||
return "Facebook"
|
||||
_:
|
||||
return "Guest"
|
||||
AuthManager.AuthMode.EMAIL: return "Email"
|
||||
AuthManager.AuthMode.GOOGLE: return "Google"
|
||||
AuthManager.AuthMode.APPLE: return "Apple"
|
||||
AuthManager.AuthMode.FACEBOOK: return "Facebook"
|
||||
_: return "Guest"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Loadout
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Category tabs
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_category_tab_pressed(category: String) -> void:
|
||||
_current_category = category
|
||||
_current_page = 0
|
||||
_selected_item_id = ""
|
||||
_clear_item_info()
|
||||
_rebuild_category_items()
|
||||
_populate_item_grid()
|
||||
_highlight_active_tab()
|
||||
|
||||
func _highlight_active_tab() -> void:
|
||||
var map := {
|
||||
"head": head_tab_btn,
|
||||
"costume": costume_tab_btn,
|
||||
"glove": glove_tab_btn,
|
||||
"accessory": acc_tab_btn
|
||||
}
|
||||
for cat: String in map:
|
||||
(map[cat] as Button).modulate = Color(1.3, 1.3, 0.4, 1) if cat == _current_category else Color.WHITE
|
||||
|
||||
func _rebuild_category_items() -> void:
|
||||
_category_items.clear()
|
||||
var prefix := _current_category + "_"
|
||||
for item_id: String in UserProfileManager.inventory:
|
||||
if item_id.begins_with(prefix):
|
||||
_category_items.append(item_id)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Item grid
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _populate_item_grid() -> void:
|
||||
var start: int = _current_page * ITEMS_PER_PAGE
|
||||
var total: int = _category_items.size()
|
||||
var total_pages: int = max(1, ceili(float(total) / float(ITEMS_PER_PAGE)))
|
||||
|
||||
page_label.text = "%d / %d" % [_current_page + 1, total_pages]
|
||||
prev_page_btn.disabled = (_current_page == 0)
|
||||
next_page_btn.disabled = ((_current_page + 1) >= total_pages)
|
||||
|
||||
var equipped: String = UserProfileManager.loadout.get(_current_category, "")
|
||||
for i in _item_slots.size():
|
||||
var slot: Button = _item_slots[i]
|
||||
var idx: int = start + i
|
||||
if idx < total:
|
||||
var item_id: String = _category_items[idx]
|
||||
var info: Dictionary = ITEM_CATALOG.get(item_id, {})
|
||||
slot.text = info.get("name", item_id)
|
||||
slot.tooltip_text = item_id
|
||||
slot.modulate = Color(0.4, 1.0, 0.4, 1) if item_id == equipped else Color.WHITE
|
||||
else:
|
||||
slot.text = ""
|
||||
slot.tooltip_text = ""
|
||||
slot.modulate = Color.WHITE
|
||||
|
||||
func _on_slot_pressed(slot_index: int) -> void:
|
||||
var idx: int = _current_page * ITEMS_PER_PAGE + slot_index
|
||||
if idx >= _category_items.size():
|
||||
return
|
||||
_selected_item_id = _category_items[idx]
|
||||
_show_item_info(_selected_item_id)
|
||||
|
||||
func _show_item_info(item_id: String) -> void:
|
||||
var info: Dictionary = ITEM_CATALOG.get(item_id, {})
|
||||
|
||||
item_name_label.text = info.get("name", item_id)
|
||||
|
||||
var rarity: String = info.get("rarity", "Common")
|
||||
item_rarity_label.text = rarity
|
||||
item_rarity_label.add_theme_color_override(
|
||||
"font_color", RARITY_COLORS.get(rarity, Color.WHITE)
|
||||
)
|
||||
|
||||
var sv: int = info.get("star_value", 0)
|
||||
item_price_label.text = str(sv) if sv > 0 else ""
|
||||
|
||||
var equipped: String = UserProfileManager.loadout.get(_current_category, "")
|
||||
equip_btn.text = "✓ Equipped" if equipped == item_id else "Equip"
|
||||
equip_btn.disabled = (equipped == item_id)
|
||||
dismantle_btn.disabled = false
|
||||
|
||||
func _clear_item_info() -> void:
|
||||
item_name_label.text = "Select an item"
|
||||
item_rarity_label.text = ""
|
||||
item_price_label.text = ""
|
||||
equip_btn.text = "Equip"
|
||||
equip_btn.disabled = true
|
||||
dismantle_btn.disabled = true
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Item actions
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_equip_pressed() -> void:
|
||||
if _selected_item_id.is_empty(): return
|
||||
var ok: bool = await UserProfileManager.update_loadout(_current_category, _selected_item_id)
|
||||
if ok:
|
||||
_set_status("Equipped: " + _selected_item_id, Color(0.4, 1.0, 0.4))
|
||||
_populate_item_grid()
|
||||
_show_item_info(_selected_item_id)
|
||||
else:
|
||||
_set_status("Failed to equip item.", Color.RED)
|
||||
|
||||
func _on_dismantle_pressed() -> void:
|
||||
if _selected_item_id.is_empty(): return
|
||||
dismantle_dialog.dialog_text = "Dismantle '%s'?\nThis will remove it from your inventory." % _selected_item_id
|
||||
dismantle_dialog.popup_centered()
|
||||
|
||||
func _on_dismantle_confirmed() -> void:
|
||||
UserProfileManager.inventory.erase(_selected_item_id)
|
||||
if UserProfileManager.loadout.get(_current_category, "") == _selected_item_id:
|
||||
UserProfileManager.update_loadout(_current_category, "")
|
||||
_selected_item_id = ""
|
||||
_clear_item_info()
|
||||
_rebuild_category_items()
|
||||
_populate_item_grid()
|
||||
_set_status("Item dismantled.", Color(1, 0.5, 0.3))
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Pagination
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_prev_page() -> void:
|
||||
if _current_page > 0:
|
||||
_current_page -= 1
|
||||
_populate_item_grid()
|
||||
|
||||
func _on_next_page() -> void:
|
||||
var total_pages: int = max(1, ceili(float(_category_items.size()) / float(ITEMS_PER_PAGE)))
|
||||
if _current_page + 1 < total_pages:
|
||||
_current_page += 1
|
||||
_populate_item_grid()
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Character loadout
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _load_loadout() -> void:
|
||||
"""Load the saved default character from profile storage."""
|
||||
var saved = UserProfileManager.profile.get("loadout_character", "Copper")
|
||||
var idx = CHARACTERS.find(saved)
|
||||
var saved: String = UserProfileManager.profile.get("loadout_character", "Copper")
|
||||
var idx: int = CHARACTERS.find(saved)
|
||||
_loadout_index = max(idx, 0)
|
||||
_default_character = CHARACTERS[_loadout_index]
|
||||
_refresh_loadout_ui()
|
||||
@@ -151,7 +358,6 @@ func _load_loadout() -> void:
|
||||
func _cycle_loadout_char(direction: int) -> void:
|
||||
_loadout_index = wrapi(_loadout_index + direction, 0, CHARACTERS.size())
|
||||
_refresh_loadout_ui()
|
||||
_update_3d_preview(CHARACTERS[_loadout_index])
|
||||
|
||||
func _refresh_loadout_ui() -> void:
|
||||
var char_name := CHARACTERS[_loadout_index]
|
||||
@@ -165,50 +371,42 @@ func _on_set_default_pressed() -> void:
|
||||
var char_name := CHARACTERS[_loadout_index]
|
||||
_default_character = char_name
|
||||
UserProfileManager.profile["loadout_character"] = char_name
|
||||
# Also apply immediately to LobbyManager
|
||||
if LobbyManager.available_characters.has(char_name):
|
||||
LobbyManager.local_character_index = LobbyManager.available_characters.find(char_name)
|
||||
status_label.text = "Loadout set to: " + char_name
|
||||
status_label.add_theme_color_override("font_color", Color(0.4, 0.8, 0.4))
|
||||
_set_status("Default set to: " + char_name, Color(0.4, 0.9, 0.4))
|
||||
_refresh_loadout_ui()
|
||||
# Persist to storage
|
||||
_save_loadout_to_profile()
|
||||
# Sync to leaderboard immediately
|
||||
UserProfileManager.submit_to_leaderboard()
|
||||
# Notify lobby (and any other listeners) to refresh their 3D preview
|
||||
UserProfileManager.profile_updated.emit()
|
||||
|
||||
func _save_loadout_to_profile() -> void:
|
||||
"""Save loadout_character field to Nakama profile storage."""
|
||||
if not NakamaManager.session:
|
||||
return
|
||||
if not NakamaManager.session: return
|
||||
var data := {
|
||||
"avatar_index": UserProfileManager.profile.get("avatar_index", 0),
|
||||
"bio": UserProfileManager.profile.get("bio", ""),
|
||||
"country": UserProfileManager.profile.get("country", ""),
|
||||
"language": UserProfileManager.profile.get("language", "en"),
|
||||
"loadout_character": _default_character
|
||||
"loadout_character": _default_character,
|
||||
"loadout": UserProfileManager.loadout
|
||||
}
|
||||
var write_obj := NakamaWriteStorageObject.new(
|
||||
"profiles", "profile", 2, 1, JSON.stringify(data), ""
|
||||
)
|
||||
var write_obj := NakamaWriteStorageObject.new("profiles", "profile", 2, 1, JSON.stringify(data), "")
|
||||
await NakamaManager.client.write_storage_objects_async(NakamaManager.session, [write_obj])
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 3D Preview
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _setup_3d_preview() -> void:
|
||||
anim_player = character_root.get_node_or_null("AnimationPlayer")
|
||||
_update_3d_preview(_default_character)
|
||||
|
||||
func _update_3d_preview(character_name: String) -> void:
|
||||
if not character_root:
|
||||
return
|
||||
if not character_root: return
|
||||
var node_name: String = CHAR_NODE_MAP.get(character_name, "Masbro")
|
||||
for child in character_root.get_children():
|
||||
if child is Node3D:
|
||||
child.visible = (child.name == node_name)
|
||||
# Update AnimationPlayer root
|
||||
if anim_player:
|
||||
var new_root := character_root.get_node_or_null(node_name)
|
||||
var new_root: Node3D = character_root.get_node_or_null(node_name) as Node3D
|
||||
if new_root:
|
||||
anim_player.root_node = new_root.get_path()
|
||||
if anim_player.has_animation("animation-pack/idle"):
|
||||
@@ -216,149 +414,153 @@ func _update_3d_preview(character_name: String) -> void:
|
||||
elif anim_player.get_animation_list().size() > 0:
|
||||
anim_player.play(anim_player.get_animation_list()[0])
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Drag-to-rotate
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_drag_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
var mb := event as InputEventMouseButton
|
||||
if mb.button_index == MOUSE_BUTTON_LEFT:
|
||||
_drag_active = mb.pressed
|
||||
_drag_start_x = mb.position.x
|
||||
elif event is InputEventMouseMotion and _drag_active:
|
||||
var mm := event as InputEventMouseMotion
|
||||
var delta: float = mm.position.x - _drag_start_x
|
||||
_drag_start_x = mm.position.x
|
||||
_model_yaw += delta * 0.8
|
||||
if character_root:
|
||||
character_root.rotation_degrees.y = _model_yaw
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Avatar
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _setup_avatar_grid() -> void:
|
||||
for child in avatar_grid.get_children():
|
||||
child.queue_free()
|
||||
for i in range(UserProfileManager.AVATARS.size()):
|
||||
var avatar_path: String = UserProfileManager.AVATARS[i]
|
||||
var btn := Button.new()
|
||||
btn.custom_minimum_size = Vector2(64, 64)
|
||||
if ResourceLoader.exists(avatar_path):
|
||||
var tex := load(avatar_path) as Texture2D
|
||||
btn.icon = tex
|
||||
# Assume .tscn has precisely instantiated Button nodes in AvatarGrid
|
||||
var children = avatar_grid.get_children()
|
||||
for i in range(min(children.size(), UserProfileManager.AVATARS.size())):
|
||||
var btn = children[i] as Button
|
||||
var path: String = UserProfileManager.AVATARS[i]
|
||||
if ResourceLoader.exists(path):
|
||||
btn.icon = load(path) as Texture2D
|
||||
btn.expand_icon = true
|
||||
else:
|
||||
btn.text = str(i + 1)
|
||||
|
||||
# Prevent double connection if re-initializing
|
||||
if btn.pressed.is_connected(_on_avatar_selected):
|
||||
btn.pressed.disconnect(_on_avatar_selected)
|
||||
|
||||
btn.pressed.connect(_on_avatar_selected.bind(i))
|
||||
avatar_grid.add_child(btn)
|
||||
|
||||
func _on_change_avatar_pressed() -> void:
|
||||
avatar_popup.popup_centered()
|
||||
|
||||
func _on_avatar_selected(index: int) -> void:
|
||||
avatar_popup.hide()
|
||||
status_label.text = "Saving avatar..."
|
||||
var success := await UserProfileManager.update_avatar(index)
|
||||
if success:
|
||||
var avatar_url: String = UserProfileManager.get_avatar_url()
|
||||
if ResourceLoader.exists(avatar_url):
|
||||
avatar_display.texture = load(avatar_url)
|
||||
status_label.text = "Avatar updated!"
|
||||
_set_status("Saving avatar...", Color.WHITE)
|
||||
var ok: bool = await UserProfileManager.update_avatar(index)
|
||||
if ok:
|
||||
var url: String = UserProfileManager.get_avatar_url()
|
||||
if ResourceLoader.exists(url):
|
||||
avatar_display.texture = load(url) as Texture2D
|
||||
_set_status("Avatar updated!", Color(0.4, 1.0, 0.4))
|
||||
else:
|
||||
status_label.text = "Failed to update avatar"
|
||||
_set_status("Failed to update avatar.", Color.RED)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Name
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Display name
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_save_name_pressed() -> void:
|
||||
var new_name := display_name_input.text.strip_edges()
|
||||
if new_name.is_empty():
|
||||
status_label.text = "Name cannot be empty"
|
||||
_set_status("Name cannot be empty.", Color.RED)
|
||||
return
|
||||
status_label.text = "Saving..."
|
||||
_set_status("Saving...", Color.WHITE)
|
||||
save_name_btn.disabled = true
|
||||
var success := await UserProfileManager.update_display_name(new_name)
|
||||
var ok: bool = await UserProfileManager.update_display_name(new_name)
|
||||
save_name_btn.disabled = false
|
||||
if success:
|
||||
status_label.add_theme_color_override("font_color", Color.GREEN)
|
||||
status_label.text = "Name updated!"
|
||||
if ok:
|
||||
_set_status("Name updated!", Color(0.4, 1.0, 0.4))
|
||||
emit_signal("profile_updated")
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
status_label.text = ""
|
||||
else:
|
||||
_set_status("Failed to update name.", Color.RED)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Account
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_link_account_pressed() -> void:
|
||||
var dialog := AcceptDialog.new()
|
||||
dialog.title = "Link Email"
|
||||
dialog.dialog_text = "Enter your email and password to link this guest account.\nYour progress will be preserved!"
|
||||
var vbox := VBoxContainer.new()
|
||||
var email_input := LineEdit.new()
|
||||
email_input.placeholder_text = "Email"
|
||||
var password_input := LineEdit.new()
|
||||
password_input.placeholder_text = "Password"
|
||||
password_input.secret = true
|
||||
vbox.add_child(email_input)
|
||||
vbox.add_child(password_input)
|
||||
dialog.add_child(vbox)
|
||||
add_child(dialog)
|
||||
dialog.popup_centered()
|
||||
dialog.confirmed.connect(func():
|
||||
var email := email_input.text.strip_edges()
|
||||
var password := password_input.text
|
||||
if email.is_empty() or password.is_empty():
|
||||
status_label.text = "Please fill in all fields"
|
||||
return
|
||||
status_label.text = "Linking account..."
|
||||
var success := await AuthManager.link_email(email, password)
|
||||
if success:
|
||||
status_label.text = "Account linked successfully!"
|
||||
link_email_input.text = ""
|
||||
link_pass_input.text = ""
|
||||
link_email_dialog.popup_centered()
|
||||
|
||||
func _on_link_account_confirmed() -> void:
|
||||
var e := link_email_input.text.strip_edges()
|
||||
var p := link_pass_input.text
|
||||
if e.is_empty() or p.is_empty():
|
||||
_set_status("Fill in all fields.", Color.RED); return
|
||||
_set_status("Linking account...", Color.WHITE)
|
||||
var ok: bool = await AuthManager.link_email(e, p)
|
||||
_set_status(
|
||||
"Account linked!" if ok else "Failed to link account.",
|
||||
Color(0.4, 1.0, 0.4) if ok else Color.RED
|
||||
)
|
||||
if ok:
|
||||
link_account_btn.visible = false
|
||||
account_type_label.text = "Account: Email"
|
||||
else:
|
||||
status_label.text = "Failed to link account"
|
||||
dialog.queue_free()
|
||||
)
|
||||
|
||||
func _setup_account_settings_ui() -> void:
|
||||
# Populate Timezone dropdown
|
||||
tz_dropdown.clear()
|
||||
for i in range(-12, 15):
|
||||
var prefix = "+" if i >= 0 else ""
|
||||
tz_dropdown.add_item("GMT " + prefix + str(i))
|
||||
tz_dropdown.add_item("GMT %s%d" % ["+" if i >= 0 else "", i])
|
||||
|
||||
# Connect buttons
|
||||
submit_cred_btn.pressed.connect(func():
|
||||
status_label.text = "Updating credentials..."
|
||||
var payload = {
|
||||
_set_status("Updating credentials...", Color.WHITE)
|
||||
var payload := {
|
||||
"current_password": old_pass_input.text,
|
||||
"new_email": new_email_input.text,
|
||||
"new_password": new_pass_input.text
|
||||
}
|
||||
var result = await NakamaManager.client.rpc_async(NakamaManager.session, "change_credentials", JSON.stringify(payload))
|
||||
if result.is_exception():
|
||||
status_label.text = "Failed: " + result.get_exception().message
|
||||
var r = await NakamaManager.client.rpc_async(
|
||||
NakamaManager.session, "change_credentials", JSON.stringify(payload)
|
||||
)
|
||||
if r.is_exception():
|
||||
_set_status("Error: " + r.get_exception().message, Color.RED)
|
||||
else:
|
||||
status_label.text = "Credentials updated successfully!"
|
||||
_set_status("Credentials updated!", Color(0.4, 1.0, 0.4))
|
||||
acc_settings_dialog.hide()
|
||||
)
|
||||
|
||||
save_tz_btn.pressed.connect(func():
|
||||
var selected_text = tz_dropdown.get_item_text(tz_dropdown.selected)
|
||||
var res = await NakamaManager.client.update_account_async(NakamaManager.session, null, null, null, null, null, selected_text)
|
||||
if res.is_exception():
|
||||
status_label.text = "TZ Failed: " + res.get_exception().message
|
||||
else:
|
||||
status_label.text = "Timezone saved!"
|
||||
var sel := tz_dropdown.get_item_text(tz_dropdown.selected)
|
||||
var r = await NakamaManager.client.update_account_async(
|
||||
NakamaManager.session, null, null, null, null, null, sel
|
||||
)
|
||||
_set_status(
|
||||
"Timezone saved!" if not r.is_exception() else "TZ error: " + r.get_exception().message,
|
||||
Color(0.4, 1.0, 0.4) if not r.is_exception() else Color.RED
|
||||
)
|
||||
)
|
||||
|
||||
reset_stats_btn.pressed.connect(func():
|
||||
var conf = ConfirmationDialog.new()
|
||||
conf.dialog_text = "Are you SURE you want to irreversibly wipe all your stats to 0?"
|
||||
acc_settings_dialog.add_child(conf)
|
||||
conf.popup_centered()
|
||||
conf.confirmed.connect(func():
|
||||
reset_stats_dialog.popup_centered()
|
||||
)
|
||||
|
||||
func _on_reset_stats_confirmed() -> void:
|
||||
var r = await NakamaManager.client.rpc_async(NakamaManager.session, "reset_stats", "{}")
|
||||
if not r.is_exception():
|
||||
UserProfileManager.stats = {
|
||||
"games_played": 0, "games_won": 0, "games_lost": 0, "total_score": 0, "high_score": 0, "play_time_minutes": 0
|
||||
"games_played": 0, "games_won": 0, "games_lost": 0,
|
||||
"total_score": 0, "high_score": 0, "play_time_minutes": 0
|
||||
}
|
||||
_load_profile_data()
|
||||
status_label.text = "Stats wiped completely."
|
||||
conf.queue_free()
|
||||
_set_status("Stats wiped.", Color(1, 0.5, 0.3))
|
||||
acc_settings_dialog.hide()
|
||||
)
|
||||
)
|
||||
|
||||
func _open_account_settings() -> void:
|
||||
old_pass_input.visible = not AuthManager.is_guest
|
||||
old_pass_input.text = ""
|
||||
new_email_input.text = ""
|
||||
new_pass_input.text = ""
|
||||
old_pass_input.text = ""; new_email_input.text = ""; new_pass_input.text = ""
|
||||
acc_settings_dialog.popup_centered()
|
||||
|
||||
func _on_logout_pressed() -> void:
|
||||
@@ -366,58 +568,51 @@ func _on_logout_pressed() -> void:
|
||||
get_tree().change_scene_to_file("res://scenes/ui/login_screen.tscn")
|
||||
|
||||
func _on_admin_panel_pressed() -> void:
|
||||
if has_node("/root/AdminManager"):
|
||||
get_node("/root/AdminManager").toggle_admin_panel()
|
||||
else:
|
||||
AdminManager.toggle_admin_panel()
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Close / Show
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Show / Close
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _on_close_pressed() -> void:
|
||||
hide()
|
||||
emit_signal("closed")
|
||||
|
||||
func show_panel() -> void:
|
||||
if not UserProfileManager.is_profile_loaded:
|
||||
status_label.text = "Loading profile from server..."
|
||||
status_label.add_theme_color_override("font_color", Color.YELLOW)
|
||||
|
||||
_set_status("Loading profile...", Color.YELLOW)
|
||||
_load_profile_data()
|
||||
_load_loadout()
|
||||
_rebuild_category_items()
|
||||
_populate_item_grid()
|
||||
_check_admin_visibility()
|
||||
show()
|
||||
|
||||
if AuthManager.is_guest:
|
||||
_on_link_account_pressed()
|
||||
status_label.text = "Please link an email to save your progress permanently!"
|
||||
_set_status("Link an email to save progress permanently!", Color.YELLOW)
|
||||
|
||||
func _check_admin_visibility() -> void:
|
||||
admin_panel_btn.hide()
|
||||
if not NakamaManager.client or not NakamaManager.session:
|
||||
return
|
||||
|
||||
# Use native Nakama account API to check user metadata for admin role
|
||||
if not NakamaManager.client or not NakamaManager.session: return
|
||||
var account = await NakamaManager.client.get_account_async(NakamaManager.session)
|
||||
if account.is_exception():
|
||||
return
|
||||
|
||||
# Check account metadata for role
|
||||
var metadata_str: String = account.user.metadata if account.user.metadata else "{}"
|
||||
var metadata = JSON.parse_string(metadata_str)
|
||||
if metadata and metadata is Dictionary:
|
||||
var role = metadata.get("role", "")
|
||||
if role in ["owner", "admin"]:
|
||||
if account.is_exception(): return
|
||||
var raw: String = account.user.metadata if account.user.metadata else "{}"
|
||||
var meta = JSON.parse_string(raw)
|
||||
if meta is Dictionary and meta.get("role", "") in ["owner", "admin"]:
|
||||
admin_panel_btn.show()
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Signal handlers
|
||||
# -------------------------------------------------------------------------
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Helpers
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
func _set_status(msg: String, color: Color = Color.WHITE) -> void:
|
||||
status_label.add_theme_color_override("font_color", color)
|
||||
status_label.text = msg
|
||||
|
||||
func _on_profile_updated() -> void:
|
||||
_load_profile_data()
|
||||
_rebuild_category_items()
|
||||
_populate_item_grid()
|
||||
|
||||
func _on_profile_update_failed(error: String) -> void:
|
||||
status_label.add_theme_color_override("font_color", Color.RED)
|
||||
status_label.text = error
|
||||
_set_status(error, Color.RED)
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
status_label.text = ""
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
extends Control
|
||||
|
||||
signal closed
|
||||
|
||||
@onready var tab_container = $Panel/VBoxContainer/TabContainer
|
||||
@onready var head_grid = $Panel/VBoxContainer/TabContainer/Head/GridContainer
|
||||
@onready var costume_grid = $Panel/VBoxContainer/TabContainer/Costume/GridContainer
|
||||
@onready var glove_grid = $Panel/VBoxContainer/TabContainer/Glove/GridContainer
|
||||
@onready var accessory_grid = $Panel/VBoxContainer/TabContainer/Accessory/GridContainer
|
||||
@onready var status_label = $Panel/VBoxContainer/StatusLabel
|
||||
@onready var back_btn = $Panel/VBoxContainer/Header/BackBtn
|
||||
|
||||
var shop_items = {
|
||||
"head": [
|
||||
{"id": "head_hat1", "name": "Cap", "gold": 100, "star": 0},
|
||||
{"id": "head_crown", "name": "Crown", "gold": 0, "star": 50}
|
||||
],
|
||||
"costume": [
|
||||
{"id": "costume_red", "name": "Red Suit", "gold": 200, "star": 0},
|
||||
{"id": "costume_gold", "name": "Gold Suit", "gold": 0, "star": 100}
|
||||
],
|
||||
"glove": [
|
||||
{"id": "glove_leather", "name": "Leather Gloves", "gold": 50, "star": 0}
|
||||
],
|
||||
"accessory": [
|
||||
{"id": "acc_glasses", "name": "Sunglasses", "gold": 80, "star": 0}
|
||||
]
|
||||
}
|
||||
|
||||
func _ready():
|
||||
back_btn.pressed.connect(_on_close)
|
||||
_build_shop()
|
||||
|
||||
func show_panel():
|
||||
show()
|
||||
_refresh_shop()
|
||||
|
||||
func _build_shop():
|
||||
_populate_grid(head_grid, shop_items["head"])
|
||||
_populate_grid(costume_grid, shop_items["costume"])
|
||||
_populate_grid(glove_grid, shop_items["glove"])
|
||||
_populate_grid(accessory_grid, shop_items["accessory"])
|
||||
|
||||
func _populate_grid(grid, items):
|
||||
for child in grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
for item in items:
|
||||
var btn = Button.new()
|
||||
btn.custom_minimum_size = Vector2(120, 80)
|
||||
btn.add_theme_font_size_override("font_size", 14)
|
||||
btn.text = "%s\nGold: %d\nStar: %d" % [item.name, item.gold, item.star]
|
||||
btn.pressed.connect(_on_buy_pressed.bind(item))
|
||||
grid.add_child(btn)
|
||||
|
||||
func _refresh_shop():
|
||||
# Visual update to show which items are owned
|
||||
# (For simplicity, not disabling buttons directly, relying on backend check)
|
||||
status_label.text = "Welcome to the Shop!"
|
||||
|
||||
func _on_buy_pressed(item: Dictionary):
|
||||
if UserProfileManager.inventory.has(item.id):
|
||||
status_label.text = "Already owned: " + item.name
|
||||
return
|
||||
|
||||
var price_gold = item.gold
|
||||
var price_star = item.star
|
||||
|
||||
if UserProfileManager.wallet.get("gold", 0) < price_gold or UserProfileManager.wallet.get("star", 0) < price_star:
|
||||
status_label.text = "Not enough currency for " + item.name
|
||||
return
|
||||
|
||||
status_label.text = "Purchasing " + item.name + "..."
|
||||
|
||||
# Determine category
|
||||
var category = ""
|
||||
if shop_items["head"].has(item): category = "head"
|
||||
elif shop_items["costume"].has(item): category = "costume"
|
||||
elif shop_items["glove"].has(item): category = "glove"
|
||||
elif shop_items["accessory"].has(item): category = "accessory"
|
||||
|
||||
var success = await UserProfileManager.purchase_item(item.id, price_gold, price_star, category)
|
||||
if success:
|
||||
status_label.text = "Successfully purchased: " + item.name
|
||||
_refresh_shop()
|
||||
else:
|
||||
status_label.text = "Failed to purchase. Backend error."
|
||||
|
||||
func _on_close():
|
||||
hide()
|
||||
emit_signal("closed")
|
||||
@@ -0,0 +1 @@
|
||||
uid://w0ddjofws4ib
|
||||
@@ -23,6 +23,9 @@ function InitModule(ctx, logger, nk, initializer) {
|
||||
initializer.registerRpc("get_user_profile", rpcGetUserProfile);
|
||||
initializer.registerRpc("update_user_profile", rpcUpdateUserProfile);
|
||||
|
||||
// Store RPCs
|
||||
initializer.registerRpc("purchase_item", rpcPurchaseItem);
|
||||
|
||||
// Leaderboard RPCs
|
||||
initializer.registerRpc("get_leaderboard_stats", rpcGetLeaderboardStats);
|
||||
initializer.registerRpc("admin_update_stats", rpcAdminUpdateStats);
|
||||
@@ -377,6 +380,49 @@ function rpcAdminSetUserRole(ctx, logger, nk, payload) {
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Store / Economy RPCs
|
||||
// =============================================================================
|
||||
|
||||
function rpcPurchaseItem(ctx, logger, nk, payload) {
|
||||
if (!ctx.userId) throw new Error("Not authenticated");
|
||||
|
||||
var request = JSON.parse(payload);
|
||||
var itemId = request.item_id;
|
||||
var priceGold = request.price_gold || 0;
|
||||
var priceStar = request.price_star || 0;
|
||||
var category = request.category || "accessory"; // head, costume, glove, accessory
|
||||
|
||||
if (!itemId) throw new Error("Item ID required");
|
||||
|
||||
try {
|
||||
var changeset = {};
|
||||
if (priceGold > 0) changeset["gold"] = -priceGold;
|
||||
if (priceStar > 0) changeset["star"] = -priceStar;
|
||||
|
||||
// Check wallet and deduct
|
||||
// nk.walletUpdate throws an error if insufficient funds
|
||||
nk.walletUpdate(ctx.userId, changeset, {}, true);
|
||||
|
||||
// Record purchase in inventory
|
||||
var inventoryObj = {
|
||||
collection: "inventory",
|
||||
key: itemId,
|
||||
userId: ctx.userId,
|
||||
value: { category: category, purchased_at: new Date().toISOString() },
|
||||
permissionRead: 1,
|
||||
permissionWrite: 0
|
||||
};
|
||||
nk.storageWrite([inventoryObj]);
|
||||
|
||||
logger.info("User " + ctx.userId + " purchased " + itemId);
|
||||
return JSON.stringify({ success: true, item: itemId });
|
||||
} catch (e) {
|
||||
logger.error("Purchase failed: " + e.message);
|
||||
throw new Error("Purchase failed: " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// User Profile RPCs
|
||||
// =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user