Inventory UI
Interface voor het beheren van items en containers.
Overzicht
┌─────────────────────────────────────────────────────────────────┐
│ INVENTORY [X] │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ [Rugzak 1] [Rugzak 2] [Buidel] Container ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ ┌───┬───┬───┬───┬───┬───┬───┬───┐ │
│ │🍯 │🌰 │🥕 │ │ │ │ │ │ Row 1 │
│ │x5 │x99│x12│ │ │ │ │ │ │
│ ├───┼───┼───┼───┼───┼───┼───┼───┤ │
│ │🪵 │🪨 │ │ │ │ │ │ │ Row 2 │
│ │x45│x23│ │ │ │ │ │ │ │
│ └───┴───┴───┴───┴───┴───┴───┴───┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ Selected: Honingpot ││
│ │ "Zoete honing van de bijen" ││
│ │ [Gebruiken] [Weggooien] ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
Scene Structuur
InventoryPanel (Control)
├── Background (NinePatchRect)
├── Header (HBoxContainer)
│ ├── Title (Label)
│ └── CloseButton
├── ContainerTabs (HBoxContainer)
│ └── [ContainerTabButton instances]
├── ItemGrid (GridContainer)
│ └── [ItemSlot instances]
├── ItemInfo (VBoxContainer)
│ ├── ItemName (Label)
│ ├── ItemDescription (Label)
│ └── ActionButtons (HBoxContainer)
└── DragPreview (Control)
Item Slot Component
Scene: ui/item_slot.tscn
ItemSlot (Control)
├── Background (TextureRect)
├── ItemIcon (TextureRect)
├── QuantityLabel (Label)
├── RarityBorder (TextureRect)
└── SelectionHighlight (ColorRect)
Script
# item_slot.gd
extends Control
signal item_selected(slot_index: int)
signal item_used(slot_index: int)
@export var slot_index: int = 0
@export var container_id: int = 0
@onready var item_icon: TextureRect = $ItemIcon
@onready var quantity_label: Label = $QuantityLabel
@onready var rarity_border: TextureRect = $RarityBorder
var item_data: Dictionary = {}
func set_item(item_id: String, quantity: int, icon: Texture2D = null) -> void:
if item_id.is_empty():
clear()
return
item_data = {
"item_id": item_id,
"quantity": quantity
}
if icon:
item_icon.texture = icon
else:
item_icon.texture = _load_item_icon(item_id)
quantity_label.text = str(quantity) if quantity > 1 else ""
quantity_label.visible = quantity > 1
func clear() -> void:
item_data = {}
item_icon.texture = null
quantity_label.visible = false
func _load_item_icon(item_id: String) -> Texture2D:
var path = "res://assets/items/%s.png" % item_id
if ResourceLoader.exists(path):
return load(path)
return preload("res://assets/ui/item_placeholder.png")
Drag & Drop
Drag Start
func _get_drag_data(at_position: Vector2) -> Variant:
if item_data.is_empty():
return null
# Create visual preview
var preview = TextureRect.new()
preview.texture = item_icon.texture
preview.custom_minimum_size = Vector2(48, 48)
preview.modulate.a = 0.8
set_drag_preview(preview)
return {
"type": "inventory_item",
"source_slot": slot_index,
"source_container": container_id,
"item": item_data.duplicate()
}
Drop Handling
func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
if not data is Dictionary:
return false
if data.get("type") != "inventory_item":
return false
return true
func _drop_data(at_position: Vector2, data: Variant) -> void:
var source = data as Dictionary
# Same slot - do nothing
if source.source_slot == slot_index and source.source_container == container_id:
return
# Call inventory manager to move
inventory_manager.move_item(
source.source_container,
source.source_slot,
container_id,
slot_index,
source.item.quantity
)
Container Tabs
Tab Component
# container_tab_button.gd
extends Button
signal tab_selected(container_id: int)
var container_id: int = 0
var container_name: String = ""
func setup(id: int, name: String, icon: Texture2D) -> void:
container_id = id
container_name = name
text = name
self.icon = icon
func _pressed() -> void:
tab_selected.emit(container_id)
Tab Switching
# inventory_panel.gd
func _on_tab_selected(container_id: int) -> void:
_current_container = container_id
_rebuild_grid()
_update_tab_visuals()
func _update_tab_visuals() -> void:
for tab in container_tabs.get_children():
if tab is Button:
tab.button_pressed = (tab.container_id == _current_container)
Grid Management
Building the Grid
func _rebuild_grid() -> void:
# Clear existing slots
for child in item_grid.get_children():
child.queue_free()
# Get container info
var container = inventory_manager.get_container_by_id(_current_container)
if container.is_empty():
return
var container_type = _get_container_type(container.container_type)
var slot_count = container_type.slot_count
# Create slots
for i in range(slot_count):
var slot = ITEM_SLOT_SCENE.instantiate()
slot.slot_index = i
slot.container_id = _current_container
slot.item_selected.connect(_on_item_selected)
item_grid.add_child(slot)
# Fill with items
_update_items()
func _update_items() -> void:
var items = inventory_manager.get_container_items(_current_container)
for slot in item_grid.get_children():
var item = items.get(slot.slot_index, {})
if item.is_empty():
slot.clear()
else:
var def = _get_item_definition(item.item_id)
slot.set_item(item.item_id, item.quantity, _load_icon(def.icon_path))
Item Info Panel
Display Selected Item
func _on_item_selected(slot_index: int) -> void:
_selected_slot = slot_index
var items = inventory_manager.get_container_items(_current_container)
var item = items.get(slot_index, {})
if item.is_empty():
_hide_item_info()
return
var def = _get_item_definition(item.item_id)
item_name.text = def.display_name
item_description.text = def.description
# Show appropriate action buttons
use_button.visible = _is_usable(def.category)
drop_button.visible = true
item_info_panel.visible = true
Action Buttons
func _on_use_pressed() -> void:
if _selected_slot < 0:
return
var items = inventory_manager.get_container_items(_current_container)
var item = items.get(_selected_slot)
if item.is_empty():
return
# Use the item
_use_item(item)
func _on_drop_pressed() -> void:
if _selected_slot < 0:
return
# Confirm dialog
confirm_dialog.show_confirmation(
"Item weggooien?",
"Weet je zeker dat je dit item wilt weggooien?",
func(): inventory_manager.remove_item(_current_container, _selected_slot, 1)
)
Keyboard Navigation
func _input(event: InputEvent) -> void:
if not visible:
return
if event.is_action_pressed("ui_cancel"):
hide_panel()
return
# Arrow key navigation
if event.is_action_pressed("ui_right"):
_move_selection(1, 0)
elif event.is_action_pressed("ui_left"):
_move_selection(-1, 0)
elif event.is_action_pressed("ui_down"):
_move_selection(0, 1)
elif event.is_action_pressed("ui_up"):
_move_selection(0, -1)
elif event.is_action_pressed("ui_accept"):
_use_selected_item()
func _move_selection(dx: int, dy: int) -> void:
var columns = item_grid.columns
var current = _selected_slot
var new_slot = current + dx + (dy * columns)
if new_slot >= 0 and new_slot < item_grid.get_child_count():
_select_slot(new_slot)