diff --git a/inventory.gd b/inventory.gd index a02657a..b2d5b91 100644 --- a/inventory.gd +++ b/inventory.gd @@ -4,19 +4,18 @@ var _content:Array[ItemStack] = [] const INVENTORY_SIZE:int = 36 func _init() -> void: - _content.resize(INVENTORY_SIZE) + clear() func get_free_item_stack_index() -> int: for i:int in range(_content.size()): - if _content[i] == null: + if _content[i].count == 0: return i return -1 - func add_item(item:Item) -> bool: for item_stack:ItemStack in _content: - if item_stack == null: + if item_stack.count == 0: continue if item_stack.item.resource_path != item.resource_path: @@ -28,10 +27,8 @@ func add_item(item:Item) -> bool: var item_stack_index:int = get_free_item_stack_index() if item_stack_index >= 0: - var item_stack:ItemStack = ItemStack.new() - item_stack.item = item - item_stack.count = 1 - _content[item_stack_index] = item_stack + _content[item_stack_index].item = item + _content[item_stack_index].count = 1 return true return false @@ -39,14 +36,12 @@ func add_item(item:Item) -> bool: func remove_item(item:Item): for i in range(_content.size() - 1, -1, -1): var item_stack:ItemStack = _content[i] - if item_stack == null: + if item_stack.count == 0: continue if item_stack.item.resource_path == item.resource_path: if item_stack.count > 1: item_stack.count = item_stack.count - 1 - else: - _content[i] = null return @@ -57,13 +52,17 @@ func get_item_stacks() -> Array[ItemStack]: func clear() -> void: _content.clear() + _content.resize(INVENTORY_SIZE) + for i:int in range(_content.size()): + if _content[i] == null: + _content[i] = ItemStack.new() func has_all(items:Array[Item]) -> bool: var needed:Array[Item] = items.duplicate() for item_stack:ItemStack in _content: - if item_stack == null: + if item_stack.count == 0: continue for i in range (item_stack.count): diff --git a/model/save_game.gd b/model/save_game.gd index 47450b3..e0f950c 100644 --- a/model/save_game.gd +++ b/model/save_game.gd @@ -5,5 +5,5 @@ extends Resource @export var player_name:String @export var quest_states:Dictionary @export var player_transform:Transform3D -@export var inventory:Array[Item] +@export var inventory:Array @export var level_pickup_items:Array[NodePath] diff --git a/scenes/main.gd b/scenes/main.gd index 88622f8..29d252d 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -28,8 +28,8 @@ func save_game(): if (property.usage & PROPERTY_USAGE_STORAGE != 0) and (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != 0: save_game.quest_states[node.name][property.name] = node.get(property.name) - for item in player.inventory.get_items(): - save_game.inventory.append(item) + for item_stack in player.inventory.get_item_stacks(): + save_game.inventory.append({"item": item_stack.item, "count": item_stack.count}) ResourceSaver.save(save_game, "user://savegame.tres") root_ui.activate_ui_panel(%GameUI) @@ -57,8 +57,13 @@ func load_game(): # Inventory player.inventory.clear() - for item in save_game.inventory: - player.inventory.add_item(item) + var inventory_item_stacks:Array[ItemStack] = player.inventory.get_item_stacks() + + assert(inventory_item_stacks.size() >= save_game.inventory.size()) + + for i in range(save_game.inventory.size()): + inventory_item_stacks[i].item = save_game.inventory[i]["item"] + inventory_item_stacks[i].count = save_game.inventory[i]["count"] # Picked up items for item_path in save_game.level_pickup_items: diff --git a/ui/item_drag.gd b/ui/item_drag.gd new file mode 100644 index 0000000..fe166eb --- /dev/null +++ b/ui/item_drag.gd @@ -0,0 +1,16 @@ +class_name ItemDrag + +signal drag_completed(data:ItemDrag) + +var source:Control = null +var destination:Control = null + +var preview:Control + +func _init(source_control: Control, preview_control:Control): + self.source = source_control + self.preview = preview_control + self.preview.tree_exiting.connect(self._on_tree_exiting) + +func _on_tree_exiting()->void: + drag_completed.emit(self) diff --git a/ui/item_grid.gd b/ui/item_grid.gd index 6a06e48..b9f6fd3 100644 --- a/ui/item_grid.gd +++ b/ui/item_grid.gd @@ -11,10 +11,11 @@ func displayStacks(item_stacks:Array[ItemStack]): for item_stack in item_stacks: var slot:ItemSlot = slot_scene.instantiate() + slot.set_drag_drop_flags(ItemSlot.ALLOW_DRAG | ItemSlot.ALLOW_DROP) add_child(slot) if item_stack != null: - slot.display(item_stack.item, item_stack.count) + slot.display(item_stack) var item_count = rows * columns @@ -29,7 +30,10 @@ func display(item_stacks:Array[Item]): for item in item_stacks: var slot:ItemSlot = slot_scene.instantiate() add_child(slot) - slot.display(item, 1) + var item_stack:ItemStack = ItemStack.new() + item_stack.item = item + item_stack.count = 1 + slot.display(item_stack) var item_count = rows * columns diff --git a/ui/item_slot.gd b/ui/item_slot.gd index 52c292b..1123142 100644 --- a/ui/item_slot.gd +++ b/ui/item_slot.gd @@ -1,17 +1,84 @@ class_name ItemSlot extends PanelContainer +enum { + ALLOW_DRAG = 1, + ALLOW_DROP = 2 +} + @onready var texture_rect:TextureRect = %TextureRect @onready var count_label = %CountLabel -func display(item:Item, count:int): - if item != null: - texture_rect.texture = item.icon - update_quantity_text(count) +var drag_drop_flags:int = 0 +var _item_stack:ItemStack = null +func set_drag_drop_flags(flags:int) -> void: + drag_drop_flags = flags + +func display(item_stack): + _item_stack = item_stack + +func _process(_delta)->void: + if _item_stack == null: + return + + if _item_stack.count == 0: + texture_rect.texture = null + update_quantity_text(0) + else: + texture_rect.texture = _item_stack.item.icon + update_quantity_text(_item_stack.count) + func update_quantity_text(stack_size) -> void: if stack_size <= 1: count_label.hide() else: count_label.text = str(stack_size) count_label.show() + +func _get_drag_data(_at_position:Vector2)->Variant: + if drag_drop_flags & ALLOW_DRAG == 0: + return null + + if _item_stack == null: + return null + + var drag_data:ItemDrag = ItemDrag.new(self, self) + + var drag_preview = load("res://ui/item_slot.tscn").instantiate() + var drag_stack = ItemStack.new() + drag_stack.item = _item_stack.item + drag_stack.count = _item_stack.count + drag_preview.display(drag_stack) + set_drag_preview(drag_preview) + + return drag_data + +func _can_drop_data(_at_position:Vector2, data:Variant)->bool: + if drag_drop_flags & ALLOW_DROP == 0: + return false + + if !data is ItemDrag: + return false + + return _item_stack.count == 0 + +func _drop_data(_at_position:Vector2, data:Variant)->void: + if drag_drop_flags & ALLOW_DROP == 0: + return + + if !data is ItemDrag: + return + + var drag_data := data as ItemDrag + + drag_data.destination = self + if drag_data.source is ItemSlot: + var source_slot := drag_data.source as ItemSlot + + # add stuff to the destination + self._item_stack.item = source_slot._item_stack.item + self._item_stack.count = source_slot._item_stack.count + + # remove it from the source + source_slot._item_stack.count = 0 diff --git a/ui/item_stack.gd b/ui/item_stack.gd index 922771b..f6f90e1 100644 --- a/ui/item_stack.gd +++ b/ui/item_stack.gd @@ -2,8 +2,4 @@ class_name ItemStack extends Node var item:Item = null -@export var count:int = 1 - -# Called when the node enters the scene tree for the first time. -func _ready(): - pass # Replace with function body. +var count:int = 0 diff --git a/ui/tool_container.gd b/ui/tool_container.gd index bb208b9..fe56db0 100644 --- a/ui/tool_container.gd +++ b/ui/tool_container.gd @@ -6,8 +6,3 @@ extends HBoxContainer # Called when the node enters the scene tree for the first time. func _ready(): pass # Replace with function body. - - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - pass