Topic was automatically imported from the old Question2Answer platform.
Asked By
Secularis
Originally, the code worked fine when clicking to pick up items, then clicking to drop said item. However, when I changed it to work “on release” it stopped dropping items, only picking them up. I just seem to be completely stuck and would much appreciate any help.
Slot script:
extends Panel
var ItemClass = preload("res://Resources/Inventory_Dev/test_item.tscn")
var item = null
func _ready():
if randi () % 2 == 0:
item = ItemClass.instantiate()
add_child(item)
func pickFromSlot():
remove_child(item)
var inventoryNode = find_parent("Inventory")
inventoryNode.add_child(item)
item = null
func putIntoSlot(new_item):
item = new_item
item.position = Vector2(0,0)
var inventoryNode = find_parent("Inventory")
inventoryNode.remove_child(item)
add_child(item)
Inventory Script:
extends Control
const SlotClass = preload("res://Resources/UI/Slot.gd")
@onready var inventory_slots = $GridContainer
var holding_item = null
func _ready():
for inv_slot in inventory_slots.get_children():
inv_slot.gui_input.connect(slot_gui_input.bind(inv_slot))
func slot_gui_input(event: InputEvent, slot: SlotClass):
if event.is_action_released("Touch") and holding_item != null:
print ("+++ ", !slot.item)
if !slot.item:
slot.putIntoSlot(holding_item)
holding_item = null
print("lalala")
else:
var temp_item = slot.item
slot.pickFromSlot()
temp_item.global_position = event.global_position
slot.putIntoSlot(holding_item)
holding_item = temp_item
if event.is_action_pressed("Touch"):
if slot.item and holding_item == null:
holding_item = slot.item
slot.pickFromSlot()
holding_item.global_position = get_global_mouse_position()
holding_item.global_position -= Vector2(32,32)
func _input(_event):
if holding_item:
holding_item.global_position = get_global_mouse_position()
holding_item.global_position -= Vector2(32,32)
pickFromSlot removes the item from Slot, but putIntoSlot is not adding the item as child of the Slot. Is that intented?
In Inventory, _input sets the global position of holding_item for ANY input event (mouse presses, key presses, wheel…), which might not be what you want. Perhaps you should check if the event is a mouse motion event at least. But it might happen to work as it is now, I guess.
As for the issue itself… which input are you actually testing with? Are you holding the mouse button while dragging the item (press, move, release), or are you clicking once to start moving the item and then clicking again into the destination slot (press+release, move, press+release)?
In case you are doing [press+release, move, press+release], then I’m not sure what’s up.
In case you are doing [press, move, release], you might be hitting a special GUI behavior, which can be nicknamed “input capture” ("mouse_entered" and "mouse_exited" signals are broken while holding down a mouse button · Issue #20881 · godotengine/godot · GitHub). Basically if you press a Control node, and hold the mouse button, only that Control will receive input events, until you release the button. That includes the release event. So if you press Slot 1, keep the button held, move to Slot 2, and release above Slot 2, Slot 1 will still receive the release event, not Slot 2. So you would end up dropping the item back into its original slot.
This behavior is particularly useful with controls that have sliding parts, such as progress bars, sliders or scrollable views, because they can be dragged with the mouse exiting their area without causing a mess with neighboring controls. But in your case, it sounds like it’s not intented.
If this is indeed the case you are in, you will have to workaround it somehow. Maybe by restructuring the way you handle input, as inconvenient as it sounds… like, handling input in a container of slots instead of individual slots, and figure out which slot the mouse is over manually.
I was also wondering if Godot could have an option to disable this behavior, but ironically, if you are dragging with the mouse button pressed, you would actually want that behavior, otherwise every UI your mouse goes over would start triggering things unwantedly (as all you want is for only slots to react).
Alternatively, the Control class seems to have a few methods related with drag-and-drop:
hello, thank you very much for your answer, it would seem that is the problem, I did indeed want to make a drag and drop functionality so that it works on mobile devices. You’ve nailed the problem on the head. Oh, if you can, whenever, please, this is the code before I broke it down, it used to work fine on click to both put into slot and pick from slot, but when I broke it down into 2 separate is_action_pressed, it stopped working, I tried my best to make it as similar in logic as possible to the other one but it simply seems to not work anymore
More precisely, in the code I originally posted, I replaced “is_action_released” with “is_action_pressed” so that it picks an item when clicking, then when clicking again it either places the item into an empty slot or replaces a different item from the inventory. However, in the broken into 2 pieces originally posted code, it only replaces items, no longer places them into empty slots. It should work identically to the code I added now and I am entirely perplexed as to why it doesn’t work