feat: implement pause menu with loadout management and rebindable input settings

This commit is contained in:
DottsGit
2026-06-04 11:33:10 -04:00
parent 8c928c2d92
commit 02c6caa0d6
5 changed files with 259 additions and 47 deletions
+147 -7
View File
@@ -4,8 +4,10 @@ var bg: ColorRect
var main_vbox: VBoxContainer
var resume_btn: Button
var loadouts_btn: Button
var settings_btn: Button
var exit_btn: Button
# Loadout UI
var loadout_editor: Control
var loadout_list_vbox: VBoxContainer
var edit_panel: PanelContainer
@@ -15,9 +17,16 @@ var primary2_opt: OptionButton
var special_opt: OptionButton
var save_loadout_btn: Button
var back_to_main_btn: Button
var editing_index: int = -1
# Settings UI
var settings_editor: Control
var settings_back_btn: Button
var keybind_vbox: VBoxContainer
var rebind_overlay: ColorRect
var rebind_label: Label
var waiting_for_input_action: String = ""
var quit_dialog: ConfirmationDialog
func _ready() -> void:
@@ -29,6 +38,17 @@ func _ready() -> void:
_connect_signals()
func _input(event: InputEvent) -> void:
if waiting_for_input_action != "":
if event is InputEventKey or event is InputEventMouseButton:
if event.is_pressed():
SettingsManager.rebind_action(waiting_for_input_action, event)
waiting_for_input_action = ""
rebind_overlay.visible = false
_populate_keybindings()
# Consume event so it doesn't trigger anything else
get_viewport().set_input_as_handled()
return
if event.is_action_pressed("ui_cancel"):
if visible:
_resume()
@@ -52,7 +72,7 @@ func _build_ui() -> void:
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(bg)
# Main Menu
# ── Main Menu ──
var main_center = CenterContainer.new()
main_center.set_anchors_preset(Control.PRESET_FULL_RECT)
bg.add_child(main_center)
@@ -77,12 +97,17 @@ func _build_ui() -> void:
loadouts_btn.custom_minimum_size = Vector2(200, 50)
main_vbox.add_child(loadouts_btn)
settings_btn = Button.new()
settings_btn.text = "Settings"
settings_btn.custom_minimum_size = Vector2(200, 50)
main_vbox.add_child(settings_btn)
exit_btn = Button.new()
exit_btn.text = "Exit Game"
exit_btn.custom_minimum_size = Vector2(200, 50)
main_vbox.add_child(exit_btn)
# Loadout Editor Root
# ── Loadout Editor Root ──
loadout_editor = Control.new()
loadout_editor.set_anchors_preset(Control.PRESET_FULL_RECT)
bg.add_child(loadout_editor)
@@ -95,7 +120,6 @@ func _build_ui() -> void:
editor_hbox.add_theme_constant_override("separation", 40)
editor_center.add_child(editor_hbox)
# Loadout List
var left_vbox = VBoxContainer.new()
editor_hbox.add_child(left_vbox)
@@ -112,7 +136,6 @@ func _build_ui() -> void:
back_to_main_btn.custom_minimum_size = Vector2(0, 40)
left_vbox.add_child(back_to_main_btn)
# Edit Panel
edit_panel = PanelContainer.new()
editor_hbox.add_child(edit_panel)
@@ -147,7 +170,74 @@ func _build_ui() -> void:
save_loadout_btn.custom_minimum_size = Vector2(0, 40)
edit_vbox.add_child(save_loadout_btn)
# Quit Dialog
# ── Settings Editor Root ──
settings_editor = Control.new()
settings_editor.set_anchors_preset(Control.PRESET_FULL_RECT)
bg.add_child(settings_editor)
var settings_center = CenterContainer.new()
settings_center.set_anchors_preset(Control.PRESET_FULL_RECT)
settings_editor.add_child(settings_center)
var settings_vbox = VBoxContainer.new()
settings_vbox.custom_minimum_size = Vector2(600, 400)
settings_center.add_child(settings_vbox)
settings_back_btn = Button.new()
settings_back_btn.text = "Back to Menu"
settings_vbox.add_child(settings_back_btn)
var tab_container = TabContainer.new()
tab_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
settings_vbox.add_child(tab_container)
# General Tab
var general_tab = VBoxContainer.new()
general_tab.name = "General"
tab_container.add_child(general_tab)
var gen_label = Label.new()
gen_label.text = "Settings coming soon..."
general_tab.add_child(gen_label)
# Keybindings Tab
var key_tab = VBoxContainer.new()
key_tab.name = "Keybindings"
tab_container.add_child(key_tab)
var reset_btn = Button.new()
reset_btn.text = "Reset to Defaults"
reset_btn.pressed.connect(func():
SettingsManager.reset_to_defaults()
_populate_keybindings()
)
key_tab.add_child(reset_btn)
var scroll = ScrollContainer.new()
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
key_tab.add_child(scroll)
keybind_vbox = VBoxContainer.new()
keybind_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
scroll.add_child(keybind_vbox)
# Rebind Overlay
rebind_overlay = ColorRect.new()
rebind_overlay.color = Color(0, 0, 0, 0.85)
rebind_overlay.set_anchors_preset(Control.PRESET_FULL_RECT)
rebind_overlay.visible = false
add_child(rebind_overlay)
var rebind_center = CenterContainer.new()
rebind_center.set_anchors_preset(Control.PRESET_FULL_RECT)
rebind_overlay.add_child(rebind_center)
rebind_label = Label.new()
rebind_label.text = "Press any key..."
rebind_label.add_theme_font_size_override("font_size", 32)
rebind_center.add_child(rebind_label)
# ── Quit Dialog ──
quit_dialog = ConfirmationDialog.new()
quit_dialog.title = "Quit Game"
quit_dialog.dialog_text = "Are you sure you want to close the game?"
@@ -161,21 +251,72 @@ func _create_label(text: String) -> Label:
func _connect_signals() -> void:
resume_btn.pressed.connect(_resume)
loadouts_btn.pressed.connect(_show_loadouts)
settings_btn.pressed.connect(_show_settings)
exit_btn.pressed.connect(_show_exit_dialog)
back_to_main_btn.pressed.connect(_show_main_menu)
settings_back_btn.pressed.connect(_show_main_menu)
save_loadout_btn.pressed.connect(_save_current_loadout)
quit_dialog.confirmed.connect(_quit_game)
func _show_main_menu() -> void:
main_vbox.visible = true
loadout_editor.visible = false
settings_editor.visible = false
func _show_loadouts() -> void:
main_vbox.visible = false
settings_editor.visible = false
loadout_editor.visible = true
edit_panel.visible = false
_populate_loadout_list()
func _show_settings() -> void:
main_vbox.visible = false
loadout_editor.visible = false
settings_editor.visible = true
_populate_keybindings()
func _populate_keybindings() -> void:
for c in keybind_vbox.get_children():
c.queue_free()
var actions = SettingsManager.default_bindings.keys()
for action in actions:
var hbox = HBoxContainer.new()
var lbl = Label.new()
lbl.text = action.capitalize()
lbl.custom_minimum_size = Vector2(200, 0)
hbox.add_child(lbl)
var btn = Button.new()
btn.text = _get_key_name(action)
btn.custom_minimum_size = Vector2(150, 0)
btn.pressed.connect(func(): _start_rebind(action))
hbox.add_child(btn)
keybind_vbox.add_child(hbox)
func _start_rebind(action: String) -> void:
waiting_for_input_action = action
rebind_label.text = "Press any key for: " + action.capitalize()
rebind_overlay.visible = true
func _get_key_name(action: String) -> String:
if not InputMap.has_action(action):
return "?"
var events = InputMap.action_get_events(action)
for e in events:
if e is InputEventKey:
var code = e.physical_keycode if e.physical_keycode != 0 else e.keycode
return OS.get_keycode_string(code)
elif e is InputEventMouseButton:
if e.button_index == MOUSE_BUTTON_LEFT: return "LClick"
elif e.button_index == MOUSE_BUTTON_RIGHT: return "RClick"
elif e.button_index == MOUSE_BUTTON_MIDDLE: return "MClick"
elif e.button_index == MOUSE_BUTTON_WHEEL_UP: return "MWheel Up"
elif e.button_index == MOUSE_BUTTON_WHEEL_DOWN: return "MWheel Down"
return "?"
func _populate_loadout_list() -> void:
for c in loadout_list_vbox.get_children():
c.queue_free()
@@ -220,7 +361,6 @@ func _populate_options(opt: OptionButton, category: String, current_id: String)
var idx = 0
var select_idx = 0
# Always add "none" as first option
opt.add_item("None", 0)
opt.set_item_metadata(0, "none")
if current_id == "none": select_idx = 0