feat: add controller hotbar management

This commit is contained in:
Alexander Sellite 2026-08-08 16:20:40 -04:00
parent 4ac7d5edb8
commit ded8494cc6
4 changed files with 159 additions and 7 deletions

View file

@ -210,10 +210,16 @@ func _ready() -> void:
_on_hotbar_presentation_transition_finished
)
_player_menu.controller_hotbar_placement_requested.connect(
_hotbar_ui.begin_controller_placement
_on_controller_hotbar_placement_requested
)
_player_menu.controller_hotbar_placement_ended.connect(
_hotbar_ui.end_controller_placement
_on_controller_hotbar_placement_ended
)
_player_menu.controller_hotbar_management_requested.connect(
_on_controller_hotbar_management_requested
)
_player_menu.controller_hotbar_management_ended.connect(
_on_controller_hotbar_management_ended
)
_title_settings_panel.panel_visibility_changed.connect(
_on_settings_visibility_changed
@ -2045,6 +2051,48 @@ func _on_inventory_hotbar_context_changed(show_hotbar: bool) -> void:
_refresh_hotbar_visibility()
func _on_controller_hotbar_placement_requested(
assignment_kind: PlayerHotbarType.AssignmentKind,
identity: StringName,
initial_slot: int,
) -> void:
_player_menu_hotbar_visible = true
_hotbar_ui.set_player_menu_context(true)
_hotbar_ui.set_drag_enabled(false)
_hotbar_ui.set_presentation_visible(true, false)
_hotbar_ui.begin_controller_placement(
assignment_kind,
identity,
initial_slot,
)
func _on_controller_hotbar_placement_ended() -> void:
_hotbar_ui.end_controller_placement()
_hotbar_ui.set_drag_enabled(
_player_menu_open
and _player_menu_hotbar_visible
and not _system_menu_open
)
func _on_controller_hotbar_management_requested(initial_slot: int) -> void:
_player_menu_hotbar_visible = true
_hotbar_ui.set_player_menu_context(true)
_hotbar_ui.set_drag_enabled(false)
_hotbar_ui.set_presentation_visible(true, false)
_hotbar_ui.begin_controller_management(initial_slot)
func _on_controller_hotbar_management_ended() -> void:
_hotbar_ui.end_controller_management()
_hotbar_ui.set_drag_enabled(
_player_menu_open
and _player_menu_hotbar_visible
and not _system_menu_open
)
func _on_hotbar_presentation_transition_finished(
is_visible: bool,
) -> void:

View file

@ -4,6 +4,7 @@ extends Control
signal presentation_transition_finished(is_visible: bool)
const ItemCatalogType = preload("res://items/item_catalog.gd")
const ItemDataType = preload("res://items/item_data.gd")
const PlayerBagType = preload("res://inventory/player_bag.gd")
const PlayerHotbarType = preload("res://inventory/player_hotbar.gd")
const FishInventoryType = preload("res://inventory/fish_inventory.gd")
@ -42,6 +43,7 @@ var _motion_elapsed: float = 0.0
var _compact_layout: bool = false
var _player_menu_context: bool = false
var _controller_placement_active: bool = false
var _controller_management_active: bool = false
var _controller_placement_kind: PlayerHotbarType.AssignmentKind = (
PlayerHotbarType.AssignmentKind.EMPTY
)
@ -147,6 +149,36 @@ func end_controller_placement() -> void:
_show_selected_item_briefly()
func begin_controller_management(initial_slot: int) -> void:
if _hotbar == null or _slots.is_empty():
return
_controller_management_active = true
var slot_count: int = _slots.size()
for index: int in slot_count:
var slot: BubbleHotbarSlotType = _slots[index]
slot.focus_mode = Control.FOCUS_ALL
slot.focus_neighbor_left = slot.get_path_to(
_slots[wrapi(index - 1, 0, slot_count)]
)
slot.focus_neighbor_right = slot.get_path_to(
_slots[wrapi(index + 1, 0, slot_count)]
)
slot.focus_neighbor_top = slot.get_path_to(slot)
slot.focus_neighbor_bottom = slot.get_path_to(slot)
var target_index: int = clampi(initial_slot, 0, slot_count - 1)
_hotbar.select_slot(target_index)
_slots[target_index].call_deferred("grab_focus")
func end_controller_management() -> void:
if not _controller_management_active:
return
_controller_management_active = false
for slot: BubbleHotbarSlotType in _slots:
slot.focus_mode = Control.FOCUS_NONE
_show_selected_item_briefly()
func _resolve_controller_placement_texture() -> Texture2D:
if (
_controller_placement_kind == PlayerHotbarType.AssignmentKind.FISH
@ -368,10 +400,14 @@ func _on_selected_slot_changed(
func _on_controller_slot_focused(slot_index: int) -> void:
if not _controller_placement_active or _hotbar == null:
if (
not (_controller_placement_active or _controller_management_active)
or _hotbar == null
):
return
_hotbar.select_slot(slot_index)
_refresh_controller_placement_preview()
if _controller_placement_active:
_refresh_controller_placement_preview()
func _on_slot_item_hovered(

View file

@ -91,6 +91,8 @@ signal controller_hotbar_placement_requested(
initial_slot: int,
)
signal controller_hotbar_placement_ended
signal controller_hotbar_management_requested(initial_slot: int)
signal controller_hotbar_management_ended
signal menu_exit_started
signal shop_cooler_modal_changed(is_open: bool)
@ -133,6 +135,7 @@ enum CloseReason {
enum ControllerOwnership {
ITEM_LIST,
NOTEPAD_ACTIONS,
HOTBAR_MANAGEMENT,
HOTBAR_PLACEMENT,
}
@ -678,6 +681,17 @@ func _handle_controller_ownership_input(event: InputEvent) -> bool:
JOY_BUTTON_Y,
)
)
if _controller_ownership == ControllerOwnership.HOTBAR_MANAGEMENT:
if cancel_pressed:
_release_controller_ownership(true, false)
return true
if alternate_pressed:
if _hotbar != null:
_hotbar.clear_slot(_hotbar.get_selected_slot())
return true
if accept_pressed:
return true
return false
if _controller_ownership == ControllerOwnership.HOTBAR_PLACEMENT:
if accept_pressed:
_confirm_controller_hotbar_placement()
@ -902,6 +916,11 @@ func _release_controller_ownership(
if restore_previous_hotbar_slot and _hotbar != null:
_hotbar.select_slot(_controller_previous_hotbar_slot)
controller_hotbar_placement_ended.emit()
if prior_ownership == ControllerOwnership.HOTBAR_MANAGEMENT:
controller_hotbar_management_ended.emit()
inventory_hotbar_context_changed.emit(
_current_section in [Section.COOLER, Section.BAG]
)
if restore_source_focus:
call_deferred(
"_restore_controller_item_focus",
@ -914,7 +933,10 @@ func _restore_controller_item_focus(
section: Section,
identity: StringName,
) -> void:
if not visible or section != _current_section or identity.is_empty():
if not visible or section != _current_section:
return
if identity.is_empty():
_focus_current_section()
return
var target: Control
if section == Section.COOLER:
@ -940,6 +962,8 @@ func _restore_controller_item_focus(
and target.focus_mode != Control.FOCUS_NONE
):
target.grab_focus()
else:
_focus_current_section()
func _handle_controller_page_switch(event: InputEvent) -> bool:
@ -1047,6 +1071,10 @@ func _handle_controller_secondary_switch(event: InputEvent) -> bool:
return false
if not button_event.pressed:
return true
var direction: int = -1 if uses_left_bumper else 1
if _controller_ownership == ControllerOwnership.HOTBAR_MANAGEMENT:
_cycle_from_controller_hotbar_management(direction)
return true
if (
_transitioning
or _page_transitioning
@ -1055,12 +1083,17 @@ func _handle_controller_secondary_switch(event: InputEvent) -> bool:
or _controller_ownership != ControllerOwnership.ITEM_LIST
):
return true
var direction: int = -1 if uses_left_bumper else 1
if _is_inventory_section(_current_section):
if (
(direction > 0 and _current_section == Section.BAG)
or (direction < 0 and _current_section == Section.COOLER)
):
_begin_controller_hotbar_management()
return true
var inventory_sections: Array[Section] = [
Section.COOLER,
Section.BAG,
Section.TACKLE_BOX,
Section.BAG,
]
var inventory_index: int = inventory_sections.find(_current_section)
_show_section(inventory_sections[wrapi(
@ -1073,6 +1106,35 @@ func _handle_controller_secondary_switch(event: InputEvent) -> bool:
return true
func _begin_controller_hotbar_management() -> void:
if _hotbar == null:
return
_controller_source_section = _current_section
_controller_source_identity = StringName()
var focus_owner: Control = get_viewport().gui_get_focus_owner()
if _current_section == Section.COOLER:
var fish_node := focus_owner as CoolerFishSpriteType
if fish_node != null:
_controller_source_identity = fish_node.catch_id
elif _current_section == Section.BAG:
var item_node := focus_owner as BagItemSpriteType
if item_node != null:
_controller_source_identity = item_node.item_id
_controller_ownership = ControllerOwnership.HOTBAR_MANAGEMENT
controller_hotbar_management_requested.emit(_hotbar.get_selected_slot())
func _cycle_from_controller_hotbar_management(direction: int) -> void:
_release_controller_ownership(false, false)
var target_section: Section = (
Section.COOLER if direction > 0 else Section.BAG
)
if target_section == _current_section:
call_deferred("_focus_current_section")
else:
_show_section(target_section)
func _cycle_visible_secondary_tabs(direction: int) -> bool:
var navigation_cluster := get_node_or_null("%NavigationCluster") as Control
var grouped_buttons: Dictionary = {}
@ -1257,6 +1319,9 @@ func open_menu() -> void:
_update_shell_layout()
_begin_menu_entry()
menu_visibility_changed.emit(true)
inventory_hotbar_context_changed.emit(
_current_section in [Section.COOLER, Section.BAG]
)
func open_section(section: Section) -> bool: