UI State Manager¶
In v1.x, opening and closing inventories required manually toggling visible, calling InputMode.ui(), and managing mouse states.
In v2.0.0, the UIStateManager Autoload handles all of this automatically. It manages a stack of UI panels, handles background overlays, controls game pausing, and provides context for Quick-Moving items between open inventories.
Key Features¶
- Stack Management: Open multiple panels (e.g., Player Inventory + Chest) and close them in order.
- Automatic Mouse Handling: Automatically calls
InputMode.ui()when a panel opens andInputMode.game()when all panels close. - Background Overlay: Automatically draws a semi-transparent dark background behind your UI panels.
- Quick Context: Automatically tracks which inventories are open so
SlotUIcan perform Quick-Moves (Shift+Click) between them. - Global Shortcuts: Automatically closes all UIs when the player presses
Escape(ui_cancel) or Right-Clicks (if not dragging).
Opening Panels¶
To open a UI, you pass a PackedScene (your saved .tscn UI), the Inventory resource to bind, a title, a layout role, and an optional pause type.
# Signature
UIStateManager.open_panel(
scene: PackedScene,
inv: Inventory,
title: String = "",
role: String = "default",
type: UIStateManager.UIType = UIStateManager.UIType.BLOCK_INPUT
) -> Control
Layout Roles¶
The role parameter tells the UICoordinator where to place the panel on the screen:
- "player": Anchors to the right side of the screen.
- "container": Anchors to the left side (if a player UI is open) or centers itself.
- "default": Places the UI dead center.
UI Types (Pausing)¶
UIType.BLOCK_INPUT: (Default) Freezes player movement/mouse capture, but the game world keeps running.UIType.PAUSE_GAME: Actually pauses the Godot SceneTree (get_tree().paused = true). Useful for pause menus.
Closing Panels¶
You have several ways to close UIs depending on your needs:
# Closes every open panel, removes the background, and restores mouse capture.
UIStateManager.close_all()
# Closes only the most recently opened panel (top of the stack).
UIStateManager.close_top_ui()
# Closes a specific panel instance.
UIStateManager.close_panel(my_specific_panel_control)
Utility Methods¶
Checking UI State¶
# Returns true if ANY panels are currently open.
if UIStateManager.has_open_ui():
print("Menus are open!")
Quick Move Context¶
When a player Shift+Clicks an item, the SlotUI needs to know where to send it. UIStateManager handles this automatically:
# Returns the Inventory of the *other* open panel (e.g., the chest, if the player inv is current).
var target_inv = UIStateManager.get_other_inventory(current_inventory)
Example: Opening a Chest¶
Here is a complete example of how to open a chest and the player's inventory side-by-side using the new manager.
extends Node3D
@export var player_ui_scene: PackedScene
@export var chest_ui_scene: PackedScene
@export var player_inv: InventoryComponent
@export var chest_inv: InventoryComponent
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("interact"): # e.g., Press 'E'
if UIStateManager.has_open_ui():
UIStateManager.close_all()
else:
open_chest()
func open_chest():
# 1. Open Player Inventory (Role: "player" -> anchors right)
UIStateManager.open_panel(
player_ui_scene,
player_inv.inventory,
"Inventory",
"player"
)
# 2. Open Chest Inventory (Role: "container" -> anchors left)
UIStateManager.open_panel(
chest_ui_scene,
chest_inv.inventory,
"Chest",
"container"
)
# Note: You DO NOT need to call InputMode.ui() or UICoordinator manually!
# UIStateManager handles the mouse cursor, background dimming, and layout automatically.
Signals¶
If you need to react to UIs opening or closing (e.g., to play a sound effect or trigger an animation), UIStateManager emits two global signals:
| Signal | Description |
|---|---|
panel_spawned(panel: Control, scene: PackedScene, role: String) |
Emitted immediately after a panel is instantiated and added to the tree. |
panel_closed(panel: Control) |
Emitted right before a panel is freed from the tree. |