fix: stabilize controller menu navigation
This commit is contained in:
parent
5df8b2e7cc
commit
a8be597d27
32 changed files with 910 additions and 2376 deletions
|
|
@ -33,10 +33,6 @@ const KeyboardMouseMappingPanelType = preload(
|
|||
const DialogControllerNavigationType = preload(
|
||||
"res://ui/file_dialog_controller_navigation.gd"
|
||||
)
|
||||
const ControllerFocusNavigationType = preload(
|
||||
"res://ui/controller_focus_navigation.gd"
|
||||
)
|
||||
|
||||
signal applied
|
||||
signal closed
|
||||
signal closing
|
||||
|
|
@ -117,6 +113,10 @@ var _mouse_sensitivity: float = 0.005
|
|||
var _controller_sensitivity: float = 2.5
|
||||
var _invert_camera_y: bool = false
|
||||
var _on_screen_keyboard_enabled: bool = false
|
||||
var _chat_dock_right: bool = false
|
||||
var _chat_mobile_mode: bool = false
|
||||
var _paint_dock_right: bool = true
|
||||
var _fullscreen_enabled: bool = false
|
||||
var _master_volume: float = 1.0
|
||||
var _music_volume: float = 1.0
|
||||
var _effects_volume: float = 1.0
|
||||
|
|
@ -144,6 +144,11 @@ var _pending_identity_path := ""
|
|||
var _pending_import_data: Dictionary = {}
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_VISIBILITY_CHANGED and not visible:
|
||||
_release_owned_focus()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_pages = {
|
||||
PAGE_DISPLAY: _display_page,
|
||||
|
|
@ -235,7 +240,7 @@ func _connect_controls() -> void:
|
|||
)
|
||||
%ControllerMapping.pressed.connect(_open_controller_mapping)
|
||||
%KeyboardMapping.pressed.connect(_open_keyboard_mouse_mapping)
|
||||
%OpenDataFolder.pressed.connect(_confirm_open_data_folder)
|
||||
%OpenDataFolder.pressed.connect(_open_data_folder)
|
||||
%ChangeDataFolder.pressed.connect(_choose_data_folder)
|
||||
%ExportPlayerIdentity.pressed.connect(
|
||||
_choose_identity_export.bind("player")
|
||||
|
|
@ -348,6 +353,7 @@ func open_panel(
|
|||
animate_gameplay_host_transitions: bool = false,
|
||||
) -> void:
|
||||
_cancel_panel_transition()
|
||||
_release_owned_focus()
|
||||
_presentation_mode = presentation_mode
|
||||
_animate_gameplay_host_transitions = animate_gameplay_host_transitions
|
||||
_settings_manager = settings_manager
|
||||
|
|
@ -359,7 +365,6 @@ func open_panel(
|
|||
panel_visibility_changed.emit(true)
|
||||
_main_panel.modulate.a = 1.0
|
||||
_main_panel.scale = Vector2.ONE
|
||||
call_deferred("_configure_controller_navigation")
|
||||
call_deferred("_focus_active_tab")
|
||||
if (
|
||||
presentation_mode == PresentationMode.TITLE_EMBEDDED
|
||||
|
|
@ -472,6 +477,7 @@ func _finish_panel_close(applied_result: bool) -> void:
|
|||
_keyboard_mouse_mapping_panel.close_panel()
|
||||
_main_panel.modulate.a = 1.0
|
||||
_main_panel.scale = Vector2.ONE
|
||||
_release_owned_focus()
|
||||
hide()
|
||||
panel_visibility_changed.emit(false)
|
||||
if applied_result:
|
||||
|
|
@ -521,6 +527,7 @@ func handle_back() -> void:
|
|||
func _select_page(page_id: StringName, focus_tab: bool = true) -> void:
|
||||
if not _pages.has(page_id):
|
||||
return
|
||||
var target_tab: OrganizerTab = _tabs.get(page_id)
|
||||
_active_page_id = page_id
|
||||
for candidate_id: StringName in _pages:
|
||||
_pages[candidate_id].visible = candidate_id == page_id
|
||||
|
|
@ -530,9 +537,8 @@ func _select_page(page_id: StringName, focus_tab: bool = true) -> void:
|
|||
)
|
||||
if page_id == PAGE_DATA:
|
||||
_refresh_data_page()
|
||||
call_deferred("_configure_controller_navigation")
|
||||
if focus_tab:
|
||||
_tabs[page_id].call_deferred("grab_focus")
|
||||
if focus_tab and target_tab != null:
|
||||
target_tab.grab_focus()
|
||||
|
||||
|
||||
func _focus_active_tab() -> void:
|
||||
|
|
@ -541,30 +547,6 @@ func _focus_active_tab() -> void:
|
|||
tab.grab_focus()
|
||||
|
||||
|
||||
func _configure_controller_navigation() -> void:
|
||||
if not is_node_ready() or not visible:
|
||||
return
|
||||
var controls: Array[Control] = []
|
||||
_collect_focusable_controls(_main_panel, controls)
|
||||
ControllerFocusNavigationType.configure_spatial_neighbors(controls)
|
||||
|
||||
|
||||
func _collect_focusable_controls(
|
||||
node: Node,
|
||||
controls: Array[Control],
|
||||
) -> void:
|
||||
for child: Node in node.get_children():
|
||||
var control := child as Control
|
||||
if control != null and not control.is_visible_in_tree():
|
||||
continue
|
||||
if (
|
||||
control != null
|
||||
and ControllerFocusNavigationType.is_focusable(control)
|
||||
):
|
||||
controls.append(control)
|
||||
_collect_focusable_controls(child, controls)
|
||||
|
||||
|
||||
func _open_controller_mapping() -> void:
|
||||
if _controller_mapping_manager == null:
|
||||
_feedback.text = "no controller mapping service is available"
|
||||
|
|
@ -627,38 +609,30 @@ func _refresh_data_page() -> void:
|
|||
"copy player fingerprint · %s"
|
||||
% NetworkIdentityCrypto.compact_suffix(fingerprint)
|
||||
)
|
||||
call_deferred("_configure_controller_navigation")
|
||||
|
||||
|
||||
func _open_data_folder() -> void:
|
||||
if _data_root == null or not _data_root.open_folder():
|
||||
_feedback.text = "could not open the data folder."
|
||||
|
||||
|
||||
func _confirm_open_data_folder() -> void:
|
||||
if (
|
||||
not is_visible_in_tree()
|
||||
or _active_page_id != PAGE_DATA
|
||||
or not _data_page.is_visible_in_tree()
|
||||
or not %OpenDataFolder.is_visible_in_tree()
|
||||
or get_viewport().gui_get_focus_owner() != %OpenDataFolder
|
||||
):
|
||||
return
|
||||
if _data_root == null:
|
||||
_feedback.text = "the data folder is unavailable."
|
||||
return
|
||||
var dialog := ConfirmationDialog.new()
|
||||
dialog.title = "open data folder?"
|
||||
dialog.ok_button_text = "open folder"
|
||||
dialog.cancel_button_text = "cancel"
|
||||
dialog.dialog_text = (
|
||||
"open this folder outside NETfishing?\n\n" + _data_root.root_path
|
||||
)
|
||||
dialog.confirmed.connect(func() -> void:
|
||||
_open_data_folder()
|
||||
dialog.queue_free()
|
||||
)
|
||||
dialog.canceled.connect(dialog.queue_free)
|
||||
if _interface_fonts != null:
|
||||
_interface_fonts.apply_utility_theme(dialog)
|
||||
add_child(dialog)
|
||||
dialog.popup_centered(Vector2i(620, 300))
|
||||
_configure_confirmation_dialog.call_deferred(
|
||||
dialog,
|
||||
dialog.get_cancel_button(),
|
||||
)
|
||||
if not _data_root.open_folder():
|
||||
_feedback.text = "could not open the data folder."
|
||||
|
||||
|
||||
func _release_owned_focus() -> void:
|
||||
if not is_inside_tree():
|
||||
return
|
||||
var focus_owner: Control = get_viewport().gui_get_focus_owner()
|
||||
if focus_owner != null and is_ancestor_of(focus_owner):
|
||||
focus_owner.release_focus()
|
||||
|
||||
|
||||
func _copy_player_fingerprint() -> void:
|
||||
|
|
@ -950,6 +924,10 @@ func _apply_settings() -> void:
|
|||
edited.controller_camera_sensitivity = _controller_sensitivity
|
||||
edited.invert_camera_y = _invert_camera_y
|
||||
edited.on_screen_keyboard_enabled = _on_screen_keyboard_enabled
|
||||
edited.chat_dock_right = _chat_dock_right
|
||||
edited.chat_mobile_mode = _chat_mobile_mode
|
||||
edited.paint_dock_right = _paint_dock_right
|
||||
edited.fullscreen_enabled = _fullscreen_enabled
|
||||
edited.master_volume = _master_volume
|
||||
edited.music_volume = _music_volume
|
||||
edited.effects_volume = _effects_volume
|
||||
|
|
@ -976,16 +954,20 @@ func _load_controls() -> void:
|
|||
_controller_sensitivity = settings.controller_camera_sensitivity
|
||||
_invert_camera_y = settings.invert_camera_y
|
||||
_on_screen_keyboard_enabled = settings.on_screen_keyboard_enabled
|
||||
_chat_dock_right = settings.chat_dock_right
|
||||
_chat_mobile_mode = settings.chat_mobile_mode
|
||||
_paint_dock_right = settings.paint_dock_right
|
||||
_fullscreen_enabled = settings.fullscreen_enabled
|
||||
_master_volume = settings.master_volume
|
||||
_music_volume = settings.music_volume
|
||||
_effects_volume = settings.effects_volume
|
||||
_environment_volume = settings.environment_volume
|
||||
_world_pixelation.select(settings.world_pixel_size - 1)
|
||||
_ui_pixelation.select(settings.ui_pixel_size - 1)
|
||||
_chat_dock.select(1 if settings.chat_dock_right else 0)
|
||||
_chat_mode.select(1 if settings.chat_mobile_mode else 0)
|
||||
_paint_dock.select(1 if settings.paint_dock_right else 0)
|
||||
_fullscreen_toggle.set_pressed_no_signal(settings.fullscreen_enabled)
|
||||
_chat_dock.select(1 if _chat_dock_right else 0)
|
||||
_chat_mode.select(1 if _chat_mobile_mode else 0)
|
||||
_paint_dock.select(1 if _paint_dock_right else 0)
|
||||
_fullscreen_toggle.set_pressed_no_signal(_fullscreen_enabled)
|
||||
_master_volume_slider.set_value_no_signal(_master_volume * 100.0)
|
||||
_music_volume_slider.set_value_no_signal(_music_volume * 100.0)
|
||||
_effects_volume_slider.set_value_no_signal(_effects_volume * 100.0)
|
||||
|
|
@ -1084,43 +1066,22 @@ func _set_ui_pixelation(pixel_size: int) -> void:
|
|||
|
||||
|
||||
func _on_chat_dock_selected(index: int) -> void:
|
||||
_set_presentation_toggle(
|
||||
&"chat_dock_right",
|
||||
_chat_dock.get_item_id(index) == 1,
|
||||
)
|
||||
_chat_dock_right = _chat_dock.get_item_id(index) == 1
|
||||
|
||||
|
||||
func _on_chat_mode_selected(index: int) -> void:
|
||||
_set_presentation_toggle(
|
||||
&"chat_mobile_mode",
|
||||
_chat_mode.get_item_id(index) == 1,
|
||||
)
|
||||
_chat_mobile_mode = _chat_mode.get_item_id(index) == 1
|
||||
|
||||
|
||||
func _on_paint_dock_selected(index: int) -> void:
|
||||
_set_presentation_toggle(
|
||||
&"paint_dock_right",
|
||||
_paint_dock.get_item_id(index) == 1,
|
||||
)
|
||||
_paint_dock_right = _paint_dock.get_item_id(index) == 1
|
||||
|
||||
|
||||
func _set_fullscreen(enabled: bool) -> void:
|
||||
_set_presentation_toggle(&"fullscreen_enabled", enabled)
|
||||
_fullscreen_enabled = enabled
|
||||
_refresh_value_labels()
|
||||
|
||||
|
||||
func _set_presentation_toggle(
|
||||
property_name: StringName,
|
||||
enabled: bool,
|
||||
) -> void:
|
||||
if _settings_manager == null:
|
||||
return
|
||||
var edited: PlayerSettings = _settings_manager.current_settings.copy()
|
||||
edited.set(property_name, enabled)
|
||||
if not _settings_manager.apply_settings(edited):
|
||||
_feedback.text = "failed to save display setting."
|
||||
|
||||
|
||||
func _on_mouse_sensitivity_changed(value: float) -> void:
|
||||
_mouse_sensitivity = clampf(
|
||||
value,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue