From 173371e6fc31fd4db58a2d0ea5f74e44f33f3a88 Mon Sep 17 00:00:00 2001 From: Voyager Date: Tue, 18 Aug 2026 10:22:32 -0400 Subject: [PATCH] Fix controller access to settings controls --- tests/controller_ui_navigation_validation.gd | 66 ++++++++++++++++++++ ui/pixelation_reset_overlay.gd | 3 +- ui/settings_panel.gd | 11 ++++ ui/settings_panel.tscn | 7 +++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/tests/controller_ui_navigation_validation.gd b/tests/controller_ui_navigation_validation.gd index 786a520..488c790 100644 --- a/tests/controller_ui_navigation_validation.gd +++ b/tests/controller_ui_navigation_validation.gd @@ -20,6 +20,7 @@ func _run() -> void: _validate_controller_hierarchy_contract() _validate_player_page_zone_contracts() _validate_shop_navigation_contract() + _validate_settings_navigation_contract() _validate_four_by_three_centering() _validate_low_end_profile_contract() print("Controller UI navigation validation: PASS") @@ -167,6 +168,71 @@ func _validate_shop_navigation_contract() -> void: assert(source.contains("_configure_controller_focus")) +func _validate_settings_navigation_contract() -> void: + var settings_scene := load("res://ui/settings_panel.tscn") as PackedScene + var settings := settings_scene.instantiate() as SettingsPanel + root.add_child(settings) + var accessibility_tab := settings.get_node( + "%AccessibilityTab" + ) as Button + var auto_click_toggle := settings.get_node("%AutoClickToggle") as Button + var interval_slider := settings.get_node( + "%AutoClickIntervalSlider" + ) as HSlider + var apply_button := settings.get_node("%ApplySettingsButton") as Button + var back_button := settings.get_node("%SettingsBackButton") as Button + assert( + accessibility_tab.get_node(accessibility_tab.focus_neighbor_bottom) + == auto_click_toggle + ) + assert( + auto_click_toggle.get_node(auto_click_toggle.focus_neighbor_bottom) + == interval_slider + ) + assert( + interval_slider.get_node(interval_slider.focus_neighbor_top) + == auto_click_toggle + ) + assert( + interval_slider.get_node(interval_slider.focus_neighbor_bottom) + == apply_button + ) + assert(apply_button.get_node(apply_button.focus_neighbor_right) == back_button) + var reset_scene := load( + "res://ui/pixelation_reset_overlay.tscn" + ) as PackedScene + var reset_overlay := reset_scene.instantiate() as PixelationResetOverlay + root.add_child(reset_overlay) + settings.show() + reset_overlay.set_settings_open(true) + var reset_focus_requested: Array[bool] = [false] + settings.crisp_reset_focus_requested.connect(func() -> void: + reset_focus_requested[0] = true + ) + settings.crisp_reset_focus_requested.connect( + reset_overlay.focus_reset_button + ) + var focus_reset_event := InputEventAction.new() + focus_reset_event.action = &"ui_right" + focus_reset_event.pressed = true + settings.call("_on_back_button_gui_input", focus_reset_event) + assert(reset_focus_requested[0]) + assert( + root.gui_get_focus_owner() + == reset_overlay.get_node("%ResetPixelationButton") + ) + reset_overlay.return_to_settings_requested.connect( + settings.focus_back_button + ) + var return_event := InputEventAction.new() + return_event.action = &"ui_left" + return_event.pressed = true + reset_overlay.call("_on_reset_button_gui_input", return_event) + assert(root.gui_get_focus_owner() == back_button) + reset_overlay.queue_free() + settings.queue_free() + + func _validate_four_by_three_centering() -> void: var stage_position: Vector2 = ( UIReferencePresentationType.get_stage_position(Vector2(640.0, 480.0)) diff --git a/ui/pixelation_reset_overlay.gd b/ui/pixelation_reset_overlay.gd index 733a29b..f837bd8 100644 --- a/ui/pixelation_reset_overlay.gd +++ b/ui/pixelation_reset_overlay.gd @@ -63,7 +63,8 @@ func focus_reset_button() -> void: func _on_reset_button_gui_input(event: InputEvent) -> void: if ( - event.is_action_pressed("ui_up") + event.is_action_pressed("ui_left") + or event.is_action_pressed("ui_up") or event.is_action_pressed("ui_focus_prev") ): return_to_settings_requested.emit() diff --git a/ui/settings_panel.gd b/ui/settings_panel.gd index 28df7f1..f8714ab 100644 --- a/ui/settings_panel.gd +++ b/ui/settings_panel.gd @@ -206,6 +206,7 @@ func _populate_option_buttons() -> void: func _connect_controls() -> void: _apply_button.pressed.connect(_apply_settings) _back_button.pressed.connect(close_panel) + _back_button.gui_input.connect(_on_back_button_gui_input) _world_pixelation.item_selected.connect( _on_world_pixelation_selected ) @@ -257,6 +258,16 @@ func _connect_controls() -> void: ) +func _on_back_button_gui_input(event: InputEvent) -> void: + if ( + event.is_action_pressed("ui_right") + or event.is_action_pressed("ui_down") + or event.is_action_pressed("ui_focus_next") + ): + crisp_reset_focus_requested.emit() + get_viewport().set_input_as_handled() + + func _configure_style() -> void: UtilityPageStyle.apply_page(self) _main_panel.add_theme_stylebox_override( diff --git a/ui/settings_panel.tscn b/ui/settings_panel.tscn index 23642f9..2af0256 100644 --- a/ui/settings_panel.tscn +++ b/ui/settings_panel.tscn @@ -77,6 +77,7 @@ unique_name_in_owner = true custom_minimum_size = Vector2(180, 52) layout_mode = 2 focus_mode = 2 +focus_neighbor_bottom = NodePath("../../ContentPanel/ContentMargin/PageStack/AccessibilityPage/Grid/AutoClickToggle") text = "accessibility" script = ExtResource("3_tab") @@ -481,6 +482,8 @@ unique_name_in_owner = true custom_minimum_size = Vector2(330, 52) layout_mode = 2 focus_mode = 2 +focus_neighbor_top = NodePath("../../../../../../TabBar/AccessibilityTab") +focus_neighbor_bottom = NodePath("../AutoClickIntervalSlider") toggle_mode = true text = "off" @@ -498,6 +501,8 @@ unique_name_in_owner = true custom_minimum_size = Vector2(330, 52) layout_mode = 2 focus_mode = 2 +focus_neighbor_top = NodePath("../AutoClickToggle") +focus_neighbor_bottom = NodePath("../../../../../../FooterGroup/FooterLayout/Footer/ApplySettingsButton") min_value = 0.1 max_value = 0.5 step = 0.01 @@ -662,6 +667,7 @@ unique_name_in_owner = true custom_minimum_size = Vector2(180, 44) layout_mode = 2 focus_mode = 2 +focus_neighbor_right = NodePath("../SettingsBackButton") text = "apply" [node name="SettingsBackButton" type="Button" parent="MainPanel/OuterMargin/Layout/FooterGroup/FooterLayout/Footer"] @@ -669,4 +675,5 @@ unique_name_in_owner = true custom_minimum_size = Vector2(180, 44) layout_mode = 2 focus_mode = 2 +focus_neighbor_left = NodePath("../ApplySettingsButton") text = "back"