add gamepad support to menus
This commit is contained in:
@@ -5,17 +5,22 @@ signal back_to_main_menu
|
||||
@onready var master_slider = $SettingsContainer/MasterVolumeContainer/MasterVolumeSlider
|
||||
@onready var music_slider = $SettingsContainer/MusicVolumeContainer/MusicVolumeSlider
|
||||
@onready var sfx_slider = $SettingsContainer/SFXVolumeContainer/SFXVolumeSlider
|
||||
@onready var language_selector = $SettingsContainer/LanguageContainer/LanguageSelector
|
||||
@onready var language_stepper = $SettingsContainer/LanguageContainer/LanguageStepper
|
||||
|
||||
@export var settings_manager: Node = SettingsManager
|
||||
@export var localization_manager: Node = LocalizationManager
|
||||
|
||||
var language_codes = []
|
||||
|
||||
# Navigation system variables
|
||||
var navigable_controls: Array[Control] = []
|
||||
var current_control_index: int = 0
|
||||
var original_control_scales: Array[Vector2] = []
|
||||
var original_control_modulates: Array[Color] = []
|
||||
|
||||
func _ready():
|
||||
add_to_group("localizable")
|
||||
DebugManager.log_info("SettingsMenu ready", "Settings")
|
||||
setup_language_selector()
|
||||
# Language selector is initialized automatically
|
||||
|
||||
var master_callback = _on_volume_slider_changed.bind("master_volume")
|
||||
if not master_slider.value_changed.is_connected(master_callback):
|
||||
@@ -29,21 +34,18 @@ func _ready():
|
||||
if not sfx_slider.value_changed.is_connected(sfx_callback):
|
||||
sfx_slider.value_changed.connect(sfx_callback)
|
||||
|
||||
if not language_selector.item_selected.is_connected(Callable(self, "_on_language_selector_item_selected")):
|
||||
language_selector.item_selected.connect(_on_language_selector_item_selected)
|
||||
# Language stepper connections are handled in the .tscn file
|
||||
|
||||
_update_controls_from_settings()
|
||||
update_text()
|
||||
_setup_navigation_system()
|
||||
|
||||
func _update_controls_from_settings():
|
||||
master_slider.value = settings_manager.get_setting("master_volume")
|
||||
music_slider.value = settings_manager.get_setting("music_volume")
|
||||
sfx_slider.value = settings_manager.get_setting("sfx_volume")
|
||||
|
||||
var current_lang = settings_manager.get_setting("language")
|
||||
var lang_index = language_codes.find(current_lang)
|
||||
if lang_index >= 0:
|
||||
language_selector.selected = lang_index
|
||||
# Language display is handled by the ValueStepper component
|
||||
|
||||
func _on_volume_slider_changed(value, setting_key):
|
||||
# Input validation for volume settings
|
||||
@@ -73,49 +75,35 @@ func _input(event):
|
||||
DebugManager.log_debug("Cancel/back action pressed in settings", "Settings")
|
||||
_exit_settings()
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
|
||||
# Vertical navigation between controls
|
||||
if event.is_action_pressed("move_up"):
|
||||
_navigate_controls(-1)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event.is_action_pressed("move_down"):
|
||||
_navigate_controls(1)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
# Horizontal navigation for current control
|
||||
elif event.is_action_pressed("move_left"):
|
||||
_adjust_current_control(-1)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event.is_action_pressed("move_right"):
|
||||
_adjust_current_control(1)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
# Activate current control
|
||||
elif event.is_action_pressed("action_south"):
|
||||
_activate_current_control()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func _on_back_button_pressed():
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Back button pressed", "Settings")
|
||||
_exit_settings()
|
||||
|
||||
func setup_language_selector():
|
||||
var languages_data = settings_manager.get_languages_data()
|
||||
if languages_data.has("languages"):
|
||||
language_selector.clear()
|
||||
language_codes.clear()
|
||||
|
||||
for lang_code in languages_data.languages.keys():
|
||||
language_codes.append(lang_code)
|
||||
var display_name = languages_data.languages[lang_code]["display_name"]
|
||||
language_selector.add_item(display_name)
|
||||
|
||||
var current_lang = settings_manager.get_setting("language")
|
||||
var lang_index = language_codes.find(current_lang)
|
||||
if lang_index >= 0:
|
||||
language_selector.selected = lang_index
|
||||
|
||||
func _on_language_selector_item_selected(index: int):
|
||||
# Input validation for language selection
|
||||
if index < 0:
|
||||
DebugManager.log_error("Invalid language index (negative): " + str(index), "Settings")
|
||||
return
|
||||
|
||||
if index >= language_codes.size():
|
||||
DebugManager.log_error("Language index out of bounds: %d (max: %d)" % [index, language_codes.size() - 1], "Settings")
|
||||
return
|
||||
|
||||
var selected_lang = language_codes[index]
|
||||
if not selected_lang or selected_lang.is_empty():
|
||||
DebugManager.log_error("Empty or null language code at index " + str(index), "Settings")
|
||||
return
|
||||
|
||||
if not settings_manager.set_setting("language", selected_lang):
|
||||
DebugManager.log_error("Failed to set language setting: " + selected_lang, "Settings")
|
||||
return
|
||||
|
||||
DebugManager.log_info("Language changed to: " + selected_lang, "Settings")
|
||||
localization_manager.change_language(selected_lang)
|
||||
|
||||
func update_text():
|
||||
$SettingsContainer/SettingsTitle.text = tr("settings_title")
|
||||
@@ -132,3 +120,101 @@ func _on_reset_setting_button_pressed() -> void:
|
||||
settings_manager.reset_settings_to_defaults()
|
||||
_update_controls_from_settings()
|
||||
localization_manager.change_language(settings_manager.get_setting("language"))
|
||||
|
||||
func _setup_navigation_system():
|
||||
navigable_controls.clear()
|
||||
original_control_scales.clear()
|
||||
original_control_modulates.clear()
|
||||
|
||||
# Add controls in navigation order
|
||||
navigable_controls.append(master_slider)
|
||||
navigable_controls.append(music_slider)
|
||||
navigable_controls.append(sfx_slider)
|
||||
navigable_controls.append(language_stepper) # Use the ValueStepper component
|
||||
navigable_controls.append($BackButtonContainer/BackButton)
|
||||
navigable_controls.append($ResetSettingsContainer/ResetSettingButton)
|
||||
|
||||
# Store original visual properties
|
||||
for control in navigable_controls:
|
||||
original_control_scales.append(control.scale)
|
||||
original_control_modulates.append(control.modulate)
|
||||
|
||||
_update_visual_selection()
|
||||
|
||||
func _navigate_controls(direction: int):
|
||||
AudioManager.play_ui_click()
|
||||
current_control_index = (current_control_index + direction) % navigable_controls.size()
|
||||
if current_control_index < 0:
|
||||
current_control_index = navigable_controls.size() - 1
|
||||
_update_visual_selection()
|
||||
DebugManager.log_info("Settings navigation: index " + str(current_control_index), "Settings")
|
||||
|
||||
func _adjust_current_control(direction: int):
|
||||
if current_control_index < 0 or current_control_index >= navigable_controls.size():
|
||||
return
|
||||
|
||||
var control = navigable_controls[current_control_index]
|
||||
|
||||
# Handle sliders
|
||||
if control is HSlider:
|
||||
var slider = control as HSlider
|
||||
var step = slider.step if slider.step > 0 else 0.1
|
||||
var new_value = slider.value + (direction * step)
|
||||
new_value = clamp(new_value, slider.min_value, slider.max_value)
|
||||
slider.value = new_value
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Slider adjusted: %s = %f" % [_get_control_name(control), new_value], "Settings")
|
||||
|
||||
# Handle language stepper with left/right
|
||||
elif control == language_stepper:
|
||||
if language_stepper.handle_input_action("move_left" if direction == -1 else "move_right"):
|
||||
AudioManager.play_ui_click()
|
||||
|
||||
func _activate_current_control():
|
||||
if current_control_index < 0 or current_control_index >= navigable_controls.size():
|
||||
return
|
||||
|
||||
var control = navigable_controls[current_control_index]
|
||||
|
||||
# Handle buttons
|
||||
if control is Button:
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Activating button via keyboard/gamepad: " + control.text, "Settings")
|
||||
control.pressed.emit()
|
||||
|
||||
# Handle language stepper (no action needed on activation, left/right handles it)
|
||||
elif control == language_stepper:
|
||||
DebugManager.log_info("Language stepper selected - use left/right to change", "Settings")
|
||||
|
||||
func _update_visual_selection():
|
||||
for i in range(navigable_controls.size()):
|
||||
var control = navigable_controls[i]
|
||||
if i == current_control_index:
|
||||
# Use the ValueStepper's built-in highlighting
|
||||
if control == language_stepper:
|
||||
language_stepper.set_highlighted(true)
|
||||
else:
|
||||
control.scale = original_control_scales[i] * 1.05
|
||||
control.modulate = Color(1.1, 1.1, 0.9)
|
||||
else:
|
||||
# Reset highlighting
|
||||
if control == language_stepper:
|
||||
language_stepper.set_highlighted(false)
|
||||
else:
|
||||
control.scale = original_control_scales[i]
|
||||
control.modulate = original_control_modulates[i]
|
||||
|
||||
func _get_control_name(control: Control) -> String:
|
||||
if control == master_slider:
|
||||
return "master_volume"
|
||||
elif control == music_slider:
|
||||
return "music_volume"
|
||||
elif control == sfx_slider:
|
||||
return "sfx_volume"
|
||||
elif control == language_stepper:
|
||||
return language_stepper.get_control_name()
|
||||
else:
|
||||
return "button"
|
||||
|
||||
func _on_language_stepper_value_changed(new_value: String, new_index: int):
|
||||
DebugManager.log_info("Language changed via ValueStepper: " + new_value + " (index: " + str(new_index) + ")", "Settings")
|
||||
|
||||
Reference in New Issue
Block a user