feat: implement pause menu with loadout management and rebindable input settings
This commit is contained in:
+147
-7
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user