feat: Implement powerup inventory UI, settings menu, and foundational managers for input and game settings.

This commit is contained in:
Yogi Wiguna
2026-03-10 12:52:53 +08:00
parent da7192ac07
commit e1e928389c
12 changed files with 723 additions and 98 deletions
+17 -7
View File
@@ -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
+110
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
uid://cdege6m8u5cp