@tool class_name ItemGrid extends GridContainer signal item_selected @export var slot_scene:PackedScene @export var allow_selection:bool = false @export var allow_drag_drop:bool = false @export var rows:int: get: return rows set(value): if value == rows: return rows = value if slot_scene == null or not is_node_ready(): return resize_grid() var _slots:Array = [] var _item_slot_to_index:Dictionary = {} var _highlighted_slot_index = -1 var _highlighted_slot:ItemSlot = null var selected_slot:ItemSlot = null var _selected_slot_index:int = -1 func _ready() -> void: resize_grid() func resize_grid() -> void: _item_slot_to_index.clear() for child in get_children(): child.get_parent().remove_child(child) child.queue_free() _slots.clear() while get_child_count() < rows * columns: var slot_instance = slot_scene.instantiate() as ItemSlot if allow_drag_drop: slot_instance.set_drag_drop_flags(ItemSlot.ALLOW_DRAG | ItemSlot.ALLOW_DROP) add_child(slot_instance) _slots.append(slot_instance) if allow_selection and not Engine.is_editor_hint(): slot_instance.connect("mouse_entered_slot", _on_slot_mouse_entered) slot_instance.connect("mouse_left_pressed", _on_slot_mouse_left_pressed) _item_slot_to_index[slot_instance] = _item_slot_to_index.size() func clear_slots() -> void: for slot:ItemSlot in _slots: slot.display(ItemStack.new()) func get_slot_index(slot:ItemSlot) -> int: if _item_slot_to_index.has(slot): return _item_slot_to_index[slot] return -1 func _on_slot_mouse_entered(slot:ItemSlot): if _highlighted_slot != null: _highlighted_slot.highlighted = false _highlighted_slot_index = -1 _highlighted_slot = null if _item_slot_to_index.has(slot): _highlighted_slot_index = _item_slot_to_index[slot] _highlighted_slot = slot _highlighted_slot.highlighted = true func select_slot(index:int) -> void: if index < 0 or index > _slots.size(): item_selected.emit(null) return _selected_slot_index = index selected_slot = _slots[_selected_slot_index] selected_slot.selected = true item_selected.emit(selected_slot) func _on_slot_mouse_left_pressed(slot:ItemSlot): if selected_slot: selected_slot.selected = false if slot == _highlighted_slot: _highlighted_slot.highlighted = false select_slot(get_slot_index(slot)) func displayStacks(item_stacks:Array[ItemStack]): var item_stack_index = 0 for slot:ItemSlot in _slots: if item_stack_index < item_stacks.size(): slot.display(item_stacks[item_stack_index]) else: var item_stack:ItemStack = ItemStack.new() item_stack.item = null slot.display(item_stack) item_stack_index = item_stack_index + 1 func display(item_stacks:Array[ItemResource]): var item_stack_index = 0 for slot:ItemSlot in _slots: var item_stack:ItemStack = ItemStack.new() if item_stack_index < item_stacks.size(): item_stack.item = item_stacks[item_stack_index] item_stack.count = 1 else: item_stack.item = null item_stack_index = item_stack_index + 1 slot.display(item_stack)