feat: Implement powerup inventory UI, settings menu, and foundational managers for input and game settings.
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@ config/features=PackedStringArray("4.6", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
SettingsManager="*uid://c1ouaaqnn0lrc"
|
||||
Nakama="*uid://bueyqhhvxe0tx"
|
||||
NakamaManager="*res://scripts/nakama_manager.gd"
|
||||
AuthManager="*res://scripts/managers/auth_manager.gd"
|
||||
|
||||
+26
-1
@@ -6,6 +6,7 @@ extends Control
|
||||
@onready var create_room_btn = $MainMenuPanel/VBoxContainer/ButtonSection/CreateRoomBtn
|
||||
@onready var browse_rooms_btn = $MainMenuPanel/VBoxContainer/ButtonSection/BrowseRoomsBtn
|
||||
@onready var main_menu_profile_btn = $MainMenuPanel/VBoxContainer/ButtonSection/ProfileBtn
|
||||
@onready var lobby_settings_btn = $MainMenuPanel/VBoxContainer/ButtonSection/SettingsBtn
|
||||
|
||||
# UI References - Server Selection
|
||||
@onready var server_option = $MainMenuPanel/VBoxContainer/ServerSelectionSection/ServerOption
|
||||
@@ -34,6 +35,7 @@ extends Control
|
||||
@onready var copy_id_btn = $LobbyPanel/TopBar/MatchIdContainer/CopyIdBtn
|
||||
@onready var duration_option = $LobbyPanel/TopBar/SettingsSection/DurationOption
|
||||
@onready var duration_text_label = $LobbyPanel/TopBar/SettingsSection/DurationTextLabel
|
||||
@onready var lobby_top_settings_btn = $LobbyPanel/TopBar/ProfileSection/LobbySettingsBtn
|
||||
@onready var random_spawn_check = $LobbyPanel/TopBar/SettingsSection/RandomSpawnCheck
|
||||
@onready var random_spawn_label = $LobbyPanel/TopBar/SettingsSection/RandomSpawnLabel
|
||||
@onready var enable_timer_check = $LobbyPanel/TopBar/SettingsSection/EnableTimerCheck
|
||||
@@ -114,6 +116,8 @@ func _ready():
|
||||
browse_rooms_btn.pressed.connect(_on_browse_rooms_pressed)
|
||||
if main_menu_profile_btn:
|
||||
main_menu_profile_btn.pressed.connect(_on_profile_btn_pressed)
|
||||
if lobby_settings_btn:
|
||||
lobby_settings_btn.pressed.connect(_on_settings_pressed)
|
||||
|
||||
# Connect Server Selection signals
|
||||
if server_option:
|
||||
@@ -133,7 +137,10 @@ func _ready():
|
||||
|
||||
# Connect button signals - Lobby
|
||||
profile_btn.pressed.connect(_on_profile_btn_pressed)
|
||||
logout_btn.pressed.connect(_on_logout_pressed)
|
||||
if logout_btn:
|
||||
logout_btn.pressed.connect(_on_logout_pressed)
|
||||
if lobby_top_settings_btn:
|
||||
lobby_top_settings_btn.pressed.connect(_on_settings_pressed)
|
||||
copy_id_btn.pressed.connect(_on_copy_id_pressed)
|
||||
duration_option.item_selected.connect(_on_duration_selected)
|
||||
random_spawn_check.toggled.connect(_on_random_spawn_toggled)
|
||||
@@ -406,6 +413,24 @@ func _on_logout_pressed() -> void:
|
||||
AuthManager.logout()
|
||||
_go_to_login()
|
||||
|
||||
func _on_settings_pressed():
|
||||
var settings_menu = get_node_or_null("SettingsMenu")
|
||||
if not settings_menu:
|
||||
var scene = load("res://scenes/ui/settings_menu.tscn")
|
||||
if scene:
|
||||
settings_menu = scene.instantiate()
|
||||
settings_menu.name = "SettingsMenu"
|
||||
add_child(settings_menu)
|
||||
|
||||
# Connect close button
|
||||
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
|
||||
|
||||
if settings_menu:
|
||||
settings_menu.open()
|
||||
|
||||
func _go_to_login() -> void:
|
||||
if get_tree():
|
||||
get_tree().change_scene_to_file("res://scenes/ui/login_screen.tscn")
|
||||
|
||||
@@ -138,6 +138,12 @@ layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "BROWSE ROOMS"
|
||||
|
||||
[node name="SettingsBtn" type="Button" parent="MainMenuPanel/VBoxContainer/ButtonSection" unique_id=123456789]
|
||||
custom_minimum_size = Vector2(0, 48)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "SETTINGS"
|
||||
|
||||
[node name="ProfileBtn" type="Button" parent="MainMenuPanel/VBoxContainer/ButtonSection" unique_id=1640960506]
|
||||
custom_minimum_size = Vector2(0, 36)
|
||||
layout_mode = 2
|
||||
@@ -287,6 +293,13 @@ theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 11
|
||||
text = "Logout"
|
||||
|
||||
[node name="LobbySettingsBtn" type="Button" parent="LobbyPanel/TopBar/ProfileSection" unique_id=987654321]
|
||||
custom_minimum_size = Vector2(32, 32)
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("5_pc087")
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "⚙"
|
||||
|
||||
[node name="Spacer" type="Control" parent="LobbyPanel/TopBar" unique_id=379952578]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
+33
-17
@@ -60,6 +60,20 @@ func _ready():
|
||||
|
||||
# Setup global multiplayer spawners (Stands, etc.)
|
||||
_setup_multiplayer_spawners()
|
||||
|
||||
# Connect HUD Settings button to pause menu toggle
|
||||
var hud_settings = get_node_or_null("TouchControls/TouchControls/SettingsBtn")
|
||||
if hud_settings:
|
||||
if hud_settings.pressed.is_connected(_toggle_pause_menu):
|
||||
hud_settings.pressed.disconnect(_toggle_pause_menu)
|
||||
hud_settings.pressed.connect(_toggle_pause_menu)
|
||||
|
||||
# Programmatically connect Pause Menu Settings button to ensure it works
|
||||
var pause_settings = get_node_or_null("PauseMenu/Panel/VBox/SettingsBtn")
|
||||
if pause_settings:
|
||||
if pause_settings.pressed.is_connected(_on_settings_pressed):
|
||||
pause_settings.pressed.disconnect(_on_settings_pressed)
|
||||
pause_settings.pressed.connect(_on_settings_pressed)
|
||||
|
||||
func _setup_multiplayer_spawners():
|
||||
# Setup MultiplayerSpawner for Static Tekton Stands
|
||||
@@ -2317,24 +2331,26 @@ func _on_how_to_play_back_pressed():
|
||||
|
||||
func _on_settings_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
var settings_panel = get_node_or_null("SettingsPanel")
|
||||
if pause_menu:
|
||||
pause_menu.visible = false
|
||||
if settings_panel:
|
||||
settings_panel.visible = true
|
||||
|
||||
# Sync settings UI with current state
|
||||
var joystick_toggle = settings_panel.get_node_or_null("Panel/VBox/JoystickToggle")
|
||||
if joystick_toggle and touch_controls:
|
||||
joystick_toggle.set_pressed_no_signal(touch_controls.joystick_enabled)
|
||||
var settings_menu = get_node_or_null("SettingsMenu")
|
||||
if not settings_menu:
|
||||
var scene = load("res://scenes/ui/settings_menu.tscn")
|
||||
if scene:
|
||||
settings_menu = scene.instantiate()
|
||||
settings_menu.name = "SettingsMenu"
|
||||
add_child(settings_menu)
|
||||
|
||||
var size_slider = settings_panel.get_node_or_null("Panel/VBox/ButtonSizeRow/ButtonSizeSlider")
|
||||
if size_slider and touch_controls:
|
||||
size_slider.set_value_no_signal(touch_controls.button_size)
|
||||
|
||||
var opacity_slider = settings_panel.get_node_or_null("Panel/VBox/OpacityRow/OpacitySlider")
|
||||
if opacity_slider and touch_controls:
|
||||
opacity_slider.set_value_no_signal(touch_controls.button_opacity)
|
||||
# Connect close button
|
||||
var close_btn = settings_menu.get_node_or_null("PanelContainer/VBoxContainer/Header/CloseButton")
|
||||
if close_btn:
|
||||
if close_btn.pressed.is_connected(_on_settings_back_pressed):
|
||||
close_btn.pressed.disconnect(_on_settings_back_pressed)
|
||||
close_btn.pressed.connect(_on_settings_back_pressed)
|
||||
|
||||
if settings_menu:
|
||||
settings_menu.open()
|
||||
|
||||
func _on_quit_match_pressed():
|
||||
get_tree().paused = false # Ensure unpaused when returning to menu
|
||||
@@ -2345,9 +2361,9 @@ func _on_quit_match_pressed():
|
||||
|
||||
func _on_settings_back_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
var settings_panel = get_node_or_null("SettingsPanel")
|
||||
if settings_panel:
|
||||
settings_panel.visible = false
|
||||
var settings_menu = get_node_or_null("SettingsMenu")
|
||||
if settings_menu:
|
||||
settings_menu.visible = false
|
||||
if pause_menu:
|
||||
pause_menu.visible = true
|
||||
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
[gd_scene format=3 uid="uid://b1two2tvv5prx"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cdege6m8u5cp" path="res://scripts/ui/settings_menu.gd" id="1_script"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_bg"]
|
||||
bg_color = Color(0.05, 0.05, 0.08, 0.85)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.2, 0.8, 1, 0.5)
|
||||
corner_radius_top_left = 20
|
||||
corner_radius_top_right = 20
|
||||
corner_radius_bottom_right = 20
|
||||
corner_radius_bottom_left = 20
|
||||
shadow_color = Color(0, 0, 0, 0.5)
|
||||
shadow_size = 20
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_title"]
|
||||
font_size = 32
|
||||
font_color = Color(0.2, 0.9, 1, 1)
|
||||
outline_size = 8
|
||||
outline_color = Color(0, 0, 0, 1)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_tab_bg"]
|
||||
content_margin_left = 20.0
|
||||
content_margin_top = 20.0
|
||||
content_margin_right = 20.0
|
||||
content_margin_bottom = 20.0
|
||||
bg_color = Color(0.1, 0.1, 0.15, 0.6)
|
||||
corner_radius_top_left = 10
|
||||
corner_radius_top_right = 10
|
||||
corner_radius_bottom_right = 10
|
||||
corner_radius_bottom_left = 10
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_heading"]
|
||||
font_size = 24
|
||||
font_color = Color(0.9, 0.9, 0.9, 1)
|
||||
|
||||
[node name="SettingsMenu" type="CanvasLayer" unique_id=1319114632]
|
||||
layer = 100
|
||||
script = ExtResource("1_script")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="." unique_id=1754757020]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0, 0, 0, 0.4)
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="." unique_id=1635225045]
|
||||
custom_minimum_size = Vector2(800, 600)
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -400.0
|
||||
offset_top = -300.0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 300.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_bg")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer" unique_id=1608766484]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="Header" type="HBoxContainer" parent="PanelContainer/VBoxContainer" unique_id=1476625293]
|
||||
custom_minimum_size = Vector2(0, 80)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer/Header" unique_id=22122987]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/margin_left = 30
|
||||
|
||||
[node name="Title" type="Label" parent="PanelContainer/VBoxContainer/Header/MarginContainer" unique_id=1831070364]
|
||||
layout_mode = 2
|
||||
text = "SYSTEM SETTINGS"
|
||||
label_settings = SubResource("LabelSettings_title")
|
||||
|
||||
[node name="CloseButton" type="Button" parent="PanelContainer/VBoxContainer/Header" unique_id=1345773906]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "X"
|
||||
flat = true
|
||||
|
||||
[node name="ContentSection" type="MarginContainer" parent="PanelContainer/VBoxContainer" unique_id=1702280876]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/margin_left = 20
|
||||
theme_override_constants/margin_top = 0
|
||||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 30
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="PanelContainer/VBoxContainer/ContentSection" unique_id=1795678842]
|
||||
layout_mode = 2
|
||||
theme_override_constants/side_margin = 20
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_tab_bg")
|
||||
current_tab = 0
|
||||
|
||||
[node name="Video" type="ScrollContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer" unique_id=964480166]
|
||||
layout_mode = 2
|
||||
metadata/_tab_index = 0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video" unique_id=1271648419]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 15
|
||||
|
||||
[node name="Fullscreen" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video/VBox" unique_id=683482011]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video/VBox/Fullscreen" unique_id=2085318401]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Fullscreen Mode"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="FullscreenToggle" type="CheckButton" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video/VBox/Fullscreen" unique_id=1955016407]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VSync" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video/VBox" unique_id=1497653967]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video/VBox/VSync" unique_id=76372424]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "V-Sync"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="VSyncToggle" type="CheckButton" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Video/VBox/VSync" unique_id=412645188]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Audio" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer" unique_id=1585166620]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
metadata/_tab_index = 1
|
||||
|
||||
[node name="Master" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio" unique_id=2083739941]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio/Master" unique_id=526445980]
|
||||
layout_mode = 2
|
||||
text = "Master Volume"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="MasterSlider" type="HSlider" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio/Master" unique_id=1787962533]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
value = 0.8
|
||||
|
||||
[node name="Music" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio" unique_id=81064625]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio/Music" unique_id=1985407106]
|
||||
layout_mode = 2
|
||||
text = "Music Volume"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="MusicSlider" type="HSlider" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio/Music" unique_id=750703557]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
value = 0.7
|
||||
|
||||
[node name="SFX" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio" unique_id=1147135370]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio/SFX" unique_id=1539898557]
|
||||
layout_mode = 2
|
||||
text = "SFX Volume"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="SFXSlider" type="HSlider" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Audio/SFX" unique_id=1301108449]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
value = 0.9
|
||||
|
||||
[node name="Controls" type="ScrollContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer" unique_id=1553036843]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
metadata/_tab_index = 2
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls" unique_id=1592525164]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="P1" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=2065564199]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P1" unique_id=85468293]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 1 (Speed)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup1Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P1" unique_id=643351652]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "1"
|
||||
|
||||
[node name="P2" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=1529813635]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P2" unique_id=1645306219]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 2 (Freeze)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup2Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P2" unique_id=937262208]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "2"
|
||||
|
||||
[node name="P3" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=69920143]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P3" unique_id=448782584]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 3 (Wall)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup3Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P3" unique_id=1817070904]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "3"
|
||||
|
||||
[node name="P4" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=559680686]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P4" unique_id=1049586584]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 4 (Ghost)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup4Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/P4" unique_id=1027617123]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "4"
|
||||
|
||||
[node name="Attack" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=1722218076]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/Attack" unique_id=1040943113]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Attack Mode"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="AttackModeBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/Attack" unique_id=1913469674]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Q"
|
||||
|
||||
[node name="Grab" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=951480662]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/Grab" unique_id=1050214223]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Grab"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="GrabBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/Grab" unique_id=1307913086]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Space"
|
||||
|
||||
[node name="SpawnBoost" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=1495993475]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/SpawnBoost" unique_id=1933746399]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Spawn Boost"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="SpawnBoostBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/SpawnBoost" unique_id=1836762532]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "E"
|
||||
|
||||
[node name="TektonGrab" type="HBoxContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=263116515]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/TektonGrab" unique_id=1041049284]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Grab Tekton"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="TektonGrabBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/TektonGrab" unique_id=1884439337]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "G"
|
||||
@@ -3,6 +3,7 @@ extends Node
|
||||
var player: Node3D
|
||||
var movement_manager: Node
|
||||
var race_manager: Node
|
||||
@onready var SettingsManager = get_node_or_null("/root/SettingsManager")
|
||||
|
||||
func initialize(p_player: Node3D, p_movement_manager: Node, p_race_manager: Node):
|
||||
player = p_player
|
||||
@@ -87,48 +88,49 @@ func handle_unhandled_input(event):
|
||||
var mode = LobbyManager.get_game_mode()
|
||||
var is_sng = mode == GameMode.Mode.STOP_N_GO
|
||||
|
||||
match event.keycode:
|
||||
KEY_KP_1, KEY_1, KEY_KP_2, KEY_2, KEY_KP_3, KEY_3, KEY_KP_4, KEY_4:
|
||||
if is_sng:
|
||||
# Stop n Go Mapping: 1-Speed, 2-Ghost
|
||||
match event.keycode:
|
||||
KEY_KP_1, KEY_1:
|
||||
player.activate_powerup(0) # FASTER_SPEED
|
||||
KEY_KP_2, KEY_2:
|
||||
player.activate_powerup(3) # INVISIBLE_MODE
|
||||
else:
|
||||
# Unified Mapping for all modes: 1-Speed, 2-Wall, 3-Freeze, 4-Ghost
|
||||
match event.keycode:
|
||||
KEY_KP_1, KEY_1:
|
||||
player.activate_powerup(0) # FASTER_SPEED
|
||||
KEY_KP_2, KEY_2:
|
||||
player.activate_powerup(2) # BLOCK_FLOOR
|
||||
KEY_KP_3, KEY_3:
|
||||
player.activate_powerup(1) # AREA_FREEZE
|
||||
KEY_KP_4, KEY_4:
|
||||
player.activate_powerup(3) # INVISIBLE_MODE
|
||||
# KEY_R:
|
||||
# player.auto_put_item()
|
||||
KEY_Q:
|
||||
if player.powerup_manager:
|
||||
# Attack Mode (formerly Special)
|
||||
# Now we want "Straight to Attack Mode" style
|
||||
player.powerup_manager.use_special_effect()
|
||||
|
||||
# Force visual update / mutual exclusivity manually if powerup manager doesn't do it yet
|
||||
if player.is_attack_mode and player.has_method("enter_attack_mode"):
|
||||
# Re-triggering enter_attack_mode might be redundant but safely ensures visuals/Knock=False
|
||||
player.enter_attack_mode()
|
||||
# Get dynamic keybinds
|
||||
var key_p1 = SettingsManager.get_control_keycode("powerup_1")
|
||||
var key_p2 = SettingsManager.get_control_keycode("powerup_2")
|
||||
var key_p3 = SettingsManager.get_control_keycode("powerup_3")
|
||||
var key_p4 = SettingsManager.get_control_keycode("powerup_4")
|
||||
|
||||
var ek = event.keycode
|
||||
|
||||
# Unified check for PowerUp keys
|
||||
if ek == key_p1:
|
||||
player.activate_powerup(0) # FASTER_SPEED
|
||||
elif ek == key_p2:
|
||||
if is_sng:
|
||||
player.activate_powerup(3) # Ghost for SNG P2
|
||||
else:
|
||||
player.activate_powerup(2) # Wall for Normal P2
|
||||
elif ek == key_p3 and not is_sng:
|
||||
player.activate_powerup(1) # AREA_FREEZE
|
||||
elif ek == key_p4 and not is_sng:
|
||||
player.activate_powerup(3) # INVISIBLE_MODE
|
||||
|
||||
# Non-Remappable variants (Numpad) - Optional fallback
|
||||
elif ek == KEY_KP_1:
|
||||
player.activate_powerup(0)
|
||||
elif ek == KEY_KP_2:
|
||||
player.activate_powerup(3 if is_sng else 2)
|
||||
|
||||
# Action Buttons (Remappable)
|
||||
elif ek == SettingsManager.get_control_keycode("attack_mode"):
|
||||
if player.powerup_manager:
|
||||
player.powerup_manager.use_special_effect()
|
||||
if player.is_attack_mode and player.has_method("enter_attack_mode"):
|
||||
player.enter_attack_mode()
|
||||
|
||||
KEY_E:
|
||||
if player.is_carrying_tekton and player.powerup_manager:
|
||||
# Spawn Boost (Now uses Tekton)
|
||||
if player.powerup_manager.has_method("spawn_boost_reward"):
|
||||
player.powerup_manager.spawn_boost_reward()
|
||||
KEY_G:
|
||||
if not player.is_carrying_tekton and player.powerup_manager:
|
||||
if player.powerup_manager.can_use_special():
|
||||
player.grab_tekton()
|
||||
elif ek == SettingsManager.get_control_keycode("spawn_boost"):
|
||||
if player.is_carrying_tekton and player.powerup_manager:
|
||||
if player.powerup_manager.has_method("spawn_boost_reward"):
|
||||
player.powerup_manager.spawn_boost_reward()
|
||||
|
||||
elif ek == SettingsManager.get_control_keycode("tekton_grab"):
|
||||
if not player.is_carrying_tekton and player.powerup_manager:
|
||||
if player.powerup_manager.can_use_special():
|
||||
player.grab_tekton()
|
||||
|
||||
# Handle spawn point selection if not yet selected
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
extends Node
|
||||
|
||||
# SettingsManager - Global singleton for handling game settings persistence
|
||||
# Autoloaded as "SettingsManager"
|
||||
|
||||
const SETTINGS_FILE = "user://game_settings.cfg"
|
||||
|
||||
# Default values
|
||||
var settings = {
|
||||
"video": {
|
||||
"fullscreen": true,
|
||||
"vsync": true,
|
||||
"resolution_idx": 1
|
||||
},
|
||||
"audio": {
|
||||
"master_volume": 0.8,
|
||||
"music_volume": 0.7,
|
||||
"sfx_volume": 0.9
|
||||
},
|
||||
"controls": {
|
||||
"powerup_1": KEY_1,
|
||||
"powerup_2": KEY_2,
|
||||
"powerup_3": KEY_3,
|
||||
"powerup_4": KEY_4,
|
||||
"grab": KEY_SPACE,
|
||||
"put": KEY_R,
|
||||
"attack_mode": KEY_Q,
|
||||
"spawn_boost": KEY_E,
|
||||
"tekton_grab": KEY_G
|
||||
}
|
||||
}
|
||||
|
||||
signal settings_applied
|
||||
signal control_remapped(action: String, key: int)
|
||||
|
||||
func _ready():
|
||||
load_settings()
|
||||
apply_all_settings()
|
||||
|
||||
func load_settings():
|
||||
var config = ConfigFile.new()
|
||||
var err = config.load(SETTINGS_FILE)
|
||||
|
||||
if err == OK:
|
||||
for section in settings.keys():
|
||||
for key in settings[section].keys():
|
||||
settings[section][key] = config.get_value(section, key, settings[section][key])
|
||||
print("[Settings] Loaded.")
|
||||
else:
|
||||
print("[Settings] Using defaults.")
|
||||
|
||||
func save_settings():
|
||||
var config = ConfigFile.new()
|
||||
for section in settings.keys():
|
||||
for key in settings[section].keys():
|
||||
config.set_value(section, key, settings[section][key])
|
||||
config.save(SETTINGS_FILE)
|
||||
|
||||
func apply_all_settings():
|
||||
apply_video_settings()
|
||||
apply_audio_settings()
|
||||
emit_signal("settings_applied")
|
||||
|
||||
func apply_video_settings():
|
||||
var video = settings.video
|
||||
if video.fullscreen:
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||
else:
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||
|
||||
if video.vsync:
|
||||
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
|
||||
else:
|
||||
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
|
||||
|
||||
func apply_audio_settings():
|
||||
var audio = settings.audio
|
||||
set_bus_volume("Master", audio.master_volume)
|
||||
set_bus_volume("Music", audio.music_volume)
|
||||
set_bus_volume("SFX", audio.sfx_volume)
|
||||
|
||||
func set_bus_volume(bus_name: String, volume_linear: float):
|
||||
var bus_idx = AudioServer.get_bus_index(bus_name)
|
||||
if bus_idx != -1:
|
||||
AudioServer.set_bus_volume_db(bus_idx, linear_to_db(volume_linear))
|
||||
AudioServer.set_bus_mute(bus_idx, volume_linear <= 0.001)
|
||||
|
||||
func set_control(action_name: String, keycode: int):
|
||||
if settings.controls.has(action_name):
|
||||
settings.controls[action_name] = keycode
|
||||
emit_signal("control_remapped", action_name, keycode)
|
||||
save_settings()
|
||||
|
||||
func get_control_keycode(action_name: String) -> int:
|
||||
return settings.controls.get(action_name, -1)
|
||||
|
||||
func get_control_text(action_name: String) -> String:
|
||||
var code = get_control_keycode(action_name)
|
||||
if code == -1: return "Unbound"
|
||||
return OS.get_keycode_string(code)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c1ouaaqnn0lrc
|
||||
@@ -142,11 +142,26 @@ func _create_touch_ui():
|
||||
|
||||
tekton_grab_button = _find_or_create_action_button(actions_container, "TektonGrab", "👋", Vector2(-280, -80))
|
||||
|
||||
# Order: AttackMode, SpawnBoost, Grab
|
||||
if attack_mode_button: actions_container.move_child(attack_mode_button, 0)
|
||||
if spawn_boost_button: actions_container.move_child(spawn_boost_button, 1)
|
||||
if grab_button: actions_container.move_child(grab_button, 2)
|
||||
if tekton_grab_button: actions_container.move_child(tekton_grab_button, 3)
|
||||
# Order: AttackMode, SpawnBoost, Grab, TektonGrab
|
||||
if attack_mode_button:
|
||||
actions_container.move_child(attack_mode_button, 0)
|
||||
attack_mode_button.icon = load("res://assets/graphics/touch_control/attack_mode.png")
|
||||
attack_mode_button.expand_icon = true
|
||||
|
||||
if spawn_boost_button:
|
||||
actions_container.move_child(spawn_boost_button, 1)
|
||||
spawn_boost_button.icon = load("res://assets/graphics/touch_control/spawn_tile.png")
|
||||
spawn_boost_button.expand_icon = true
|
||||
|
||||
if grab_button:
|
||||
actions_container.move_child(grab_button, 2)
|
||||
grab_button.icon = load("res://assets/graphics/touch_control/take_tile.png")
|
||||
grab_button.expand_icon = true
|
||||
|
||||
if tekton_grab_button:
|
||||
actions_container.move_child(tekton_grab_button, 3)
|
||||
tekton_grab_button.icon = load("res://assets/graphics/touch_control/grab_tekton.png")
|
||||
tekton_grab_button.expand_icon = true
|
||||
|
||||
# Hide Put Button
|
||||
if put_button:
|
||||
@@ -391,6 +406,7 @@ func _load_settings():
|
||||
var err = config.load(CONFIG_PATH)
|
||||
if err != OK:
|
||||
print("[TouchControls] No saved settings found, using defaults")
|
||||
_apply_settings() # Apply default settings immediately
|
||||
return
|
||||
|
||||
# Load settings values
|
||||
@@ -439,46 +455,55 @@ func _apply_settings():
|
||||
# Apply joystick visibility
|
||||
if virtual_joystick:
|
||||
virtual_joystick.visible = joystick_enabled
|
||||
|
||||
# Apply touch buttons visibility - FORCED ON per request to "just show them"
|
||||
if actions_container:
|
||||
actions_container.visible = true
|
||||
actions_container.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
actions_container.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
|
||||
# Apply touch buttons visibility - dependent on master joystick_enabled switch
|
||||
# If joystick is disabled, ALL touch controls are hidden
|
||||
# Note: We ignore touch_buttons_enabled here to ensure "Enable Virtual Joystick" shows EVERYTHING as requested
|
||||
var buttons_visible = joystick_enabled
|
||||
var buttons_visible = true
|
||||
|
||||
print("[TouchControls] Applying settings: JoystickEnabled=", joystick_enabled, " ButtonsVisible=", buttons_visible)
|
||||
print("[TouchControls] Applying settings: ButtonsVisible=", buttons_visible)
|
||||
|
||||
if grab_button:
|
||||
grab_button.visible = buttons_visible
|
||||
grab_button.visible = false
|
||||
grab_button.scale = Vector2(button_scale, button_scale)
|
||||
# Use offsets for anchored controls, not position
|
||||
# grab_button.offset_left = button_positions.grab.x
|
||||
# grab_button.offset_top = button_positions.grab.y
|
||||
# grab_button.offset_right = button_positions.grab.x + button_size
|
||||
# grab_button.offset_bottom = button_positions.grab.y + button_size
|
||||
grab_button.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT)
|
||||
grab_button.offset_left = button_positions.grab.x
|
||||
grab_button.offset_top = button_positions.grab.y
|
||||
grab_button.offset_right = button_positions.grab.x + button_size
|
||||
grab_button.offset_bottom = button_positions.grab.y + button_size
|
||||
|
||||
if put_button:
|
||||
put_button.visible = false # Always INTENTIONALLY HIDDEN per request
|
||||
# put_button.scale = Vector2(button_scale, button_scale)
|
||||
# put_button.offset_left = button_positions.put.x
|
||||
# put_button.offset_top = button_positions.put.y
|
||||
# put_button.offset_right = button_positions.put.x + button_size
|
||||
# put_button.offset_bottom = button_positions.put.y + button_size
|
||||
|
||||
if attack_mode_button:
|
||||
attack_mode_button.visible = buttons_visible
|
||||
attack_mode_button.visible = true
|
||||
attack_mode_button.scale = Vector2(button_scale, button_scale)
|
||||
# attack_mode_button.offset_left = button_positions.attack_mode.x
|
||||
# attack_mode_button.offset_top = button_positions.attack_mode.y
|
||||
# attack_mode_button.offset_right = button_positions.attack_mode.x + button_size
|
||||
# attack_mode_button.offset_bottom = button_positions.attack_mode.y + button_size
|
||||
attack_mode_button.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT)
|
||||
attack_mode_button.offset_left = button_positions.attack_mode.x
|
||||
attack_mode_button.offset_top = button_positions.attack_mode.y
|
||||
attack_mode_button.offset_right = button_positions.attack_mode.x + button_size
|
||||
attack_mode_button.offset_bottom = button_positions.attack_mode.y + button_size
|
||||
|
||||
if spawn_boost_button:
|
||||
spawn_boost_button.visible = buttons_visible
|
||||
spawn_boost_button.visible = true
|
||||
spawn_boost_button.scale = Vector2(button_scale, button_scale)
|
||||
# spawn_boost_button.offset_left = button_positions.spawn_boost.x
|
||||
# spawn_boost_button.offset_top = button_positions.spawn_boost.y
|
||||
# spawn_boost_button.offset_right = button_positions.spawn_boost.x + button_size
|
||||
# spawn_boost_button.offset_bottom = button_positions.spawn_boost.y + button_size
|
||||
spawn_boost_button.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT)
|
||||
spawn_boost_button.offset_left = button_positions.spawn_boost.x
|
||||
spawn_boost_button.offset_top = button_positions.spawn_boost.y
|
||||
spawn_boost_button.offset_right = button_positions.spawn_boost.x + button_size
|
||||
spawn_boost_button.offset_bottom = button_positions.spawn_boost.y + button_size
|
||||
|
||||
if tekton_grab_button:
|
||||
tekton_grab_button.visible = true
|
||||
tekton_grab_button.scale = Vector2(button_scale, button_scale)
|
||||
tekton_grab_button.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT)
|
||||
tekton_grab_button.offset_left = -280
|
||||
tekton_grab_button.offset_top = -80
|
||||
tekton_grab_button.offset_right = -280 + button_size
|
||||
tekton_grab_button.offset_bottom = -80 + button_size
|
||||
|
||||
# Force layer update
|
||||
visible = true
|
||||
|
||||
@@ -8,11 +8,16 @@ var icon_containers: Dictionary = {} # { EffectEnum: Button }
|
||||
# Local State
|
||||
var selected_effect: int = -1
|
||||
var special_manager_ref: Node = null # Reference to SpecialTilesManager
|
||||
@onready var SettingsManager = get_node_or_null("/root/SettingsManager")
|
||||
|
||||
signal effect_selected(effect: int)
|
||||
|
||||
func _ready():
|
||||
print("[PowerUpUI] _ready called")
|
||||
|
||||
# Connect to SettingsManager to update labels
|
||||
if SettingsManager and not SettingsManager.control_remapped.is_connected(_on_control_remapped):
|
||||
SettingsManager.control_remapped.connect(_on_control_remapped)
|
||||
# Map Effect Enum to UI Nodes (Assumes specific names in main.tscn)
|
||||
# We try to get them immediately. If they are children, they should be accessible.
|
||||
var container = get_node_or_null("Container")
|
||||
@@ -54,8 +59,13 @@ func _ready():
|
||||
if freeze_btn: freeze_btn.visible = true
|
||||
_update_shortcuts_for_mode(false)
|
||||
|
||||
|
||||
print("[PowerUpUI] UI Initialization Complete. Mapped %d buttons." % icon_containers.size())
|
||||
|
||||
func _on_control_remapped(_action: String, _key: int):
|
||||
# Refresh all labels
|
||||
_update_shortcuts_for_mode(LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO))
|
||||
|
||||
func _setup_btn(effect_id: int, btn: Button):
|
||||
if not btn:
|
||||
print("[PowerUpUI] Warning: Button for effect %d is null" % effect_id)
|
||||
@@ -138,15 +148,15 @@ func _update_btn_shortcut(effect_id: int, btn: Button):
|
||||
var key_text = ""
|
||||
if is_sng:
|
||||
match effect_id:
|
||||
0: key_text = "1" # Speed
|
||||
3: key_text = "2" # Ghost
|
||||
_: key_text = "" # Others hidden/disabled
|
||||
0: key_text = SettingsManager.get_control_text("powerup_1")
|
||||
3: key_text = SettingsManager.get_control_text("powerup_2") # Map P2 to Slot 3 (Ghost) in SNG
|
||||
_: key_text = ""
|
||||
else:
|
||||
match effect_id:
|
||||
0: key_text = "1" # Speed
|
||||
2: key_text = "2" # Wall
|
||||
1: key_text = "3" # Freeze
|
||||
3: key_text = "4" # Ghost
|
||||
0: key_text = SettingsManager.get_control_text("powerup_1")
|
||||
2: key_text = SettingsManager.get_control_text("powerup_2")
|
||||
1: key_text = SettingsManager.get_control_text("powerup_3")
|
||||
3: key_text = SettingsManager.get_control_text("powerup_4")
|
||||
|
||||
sc_lbl.text = key_text
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
extends CanvasLayer
|
||||
|
||||
# SettingsMenu - Handles UI logic for the premium settings panel
|
||||
|
||||
@onready var tab_container = $PanelContainer/VBoxContainer/ContentSection/TabContainer
|
||||
@onready var close_button = $PanelContainer/VBoxContainer/Header/CloseButton
|
||||
|
||||
# Video Controls
|
||||
@onready var fullscreen_toggle = %FullscreenToggle
|
||||
@onready var vsync_toggle = %VSyncToggle
|
||||
|
||||
# Audio Controls
|
||||
@onready var master_slider = %MasterSlider
|
||||
@onready var music_slider = %MusicSlider
|
||||
@onready var sfx_slider = %SFXSlider
|
||||
|
||||
# Controls (Keybinds)
|
||||
@onready var SettingsManager = get_node_or_null("/root/SettingsManager")
|
||||
var listening_action: String = "" # Set when waiting for a keypress
|
||||
|
||||
func _ready():
|
||||
# Theme inheritance is broken by CanvasLayer root, no need for theme = null
|
||||
_load_ui_values()
|
||||
_connect_signals()
|
||||
|
||||
# Initial visibility
|
||||
visible = false
|
||||
|
||||
func _load_ui_values():
|
||||
if not SettingsManager:
|
||||
print("[SettingsMenu] ERROR: SettingsManager not found")
|
||||
return
|
||||
|
||||
var s = SettingsManager.settings
|
||||
|
||||
# Video
|
||||
fullscreen_toggle.button_pressed = s.video.fullscreen
|
||||
vsync_toggle.button_pressed = s.video.vsync
|
||||
|
||||
# Audio
|
||||
master_slider.value = s.audio.master_volume
|
||||
music_slider.value = s.audio.music_volume
|
||||
sfx_slider.value = s.audio.sfx_volume
|
||||
|
||||
# Controls
|
||||
_update_all_key_labels()
|
||||
|
||||
func _connect_signals():
|
||||
# Video
|
||||
fullscreen_toggle.toggled.connect(_on_video_setting_changed)
|
||||
vsync_toggle.toggled.connect(_on_video_setting_changed)
|
||||
|
||||
# Audio
|
||||
master_slider.value_changed.connect(_on_audio_setting_changed.bind("master_volume"))
|
||||
music_slider.value_changed.connect(_on_audio_setting_changed.bind("music_volume"))
|
||||
sfx_slider.value_changed.connect(_on_audio_setting_changed.bind("sfx_volume"))
|
||||
|
||||
# Close
|
||||
close_button.pressed.connect(func(): visible = false)
|
||||
|
||||
# Connect remapping buttons
|
||||
for action_name in SettingsManager.settings.controls.keys():
|
||||
var btn = get_node_or_null("%" + action_name.to_pascal_case() + "Btn")
|
||||
if btn:
|
||||
btn.pressed.connect(_on_remap_button_pressed.bind(action_name))
|
||||
|
||||
func _on_video_setting_changed(_unused = false):
|
||||
SettingsManager.settings.video.fullscreen = fullscreen_toggle.button_pressed
|
||||
SettingsManager.settings.video.vsync = vsync_toggle.button_pressed
|
||||
SettingsManager.save_settings()
|
||||
SettingsManager.apply_video_settings()
|
||||
|
||||
func _on_audio_setting_changed(key: String, value: float):
|
||||
SettingsManager.settings.audio[key] = value
|
||||
SettingsManager.save_settings()
|
||||
SettingsManager.apply_audio_settings()
|
||||
|
||||
func _on_remap_button_pressed(action_name: String):
|
||||
listening_action = action_name
|
||||
var btn = get_node_or_null("%" + action_name.to_pascal_case() + "Btn")
|
||||
if btn:
|
||||
btn.text = "..."
|
||||
btn.modulate = Color(0.5, 1.0, 0.5) # Signal "Listening"
|
||||
|
||||
func _input(event):
|
||||
if listening_action != "" and event is InputEventKey and event.pressed:
|
||||
# Capture the key
|
||||
var keycode = event.keycode
|
||||
SettingsManager.set_control(listening_action, keycode)
|
||||
|
||||
# Feedback and Reset
|
||||
_update_key_label(listening_action)
|
||||
listening_action = ""
|
||||
|
||||
# Consume event to prevent triggers
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func _update_all_key_labels():
|
||||
for action_name in SettingsManager.settings.controls.keys():
|
||||
_update_key_label(action_name)
|
||||
|
||||
func _update_key_label(action_name: String):
|
||||
var btn = get_node_or_null("%" + action_name.to_pascal_case() + "Btn")
|
||||
if btn:
|
||||
btn.text = SettingsManager.get_control_text(action_name)
|
||||
btn.modulate = Color.WHITE
|
||||
|
||||
func open():
|
||||
_load_ui_values()
|
||||
visible = true
|
||||
@@ -0,0 +1 @@
|
||||
uid://cdege6m8u5cp
|
||||
Reference in New Issue
Block a user