Closed TheYellowArchitect closed 2 months ago
I should probably clarify in the documentation that item_dropped
only triggers if an item is dropped on top of an CtrlInventoryGrid
.
But I think the best way to handle item drops outside the inventory is to first create a transparent control that is positioned behind the UI and spans the entire screen. Then you should be able to implement _drop_data and _can_drop_data for that control:
func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
return true
func _drop_data(at_position: Vector2, data: Variant) -> void:
print("Item dropped: %s" % str(data.item))
# Remove the item from the inventory, handle the item drop etc.
Note that in v2.x the type of the data
parameter is defined inside addons/gloot/ui/ctrl_inventory_item_rect.gd
and the actual InventoryItem
must be accessed via data.item
. This is something that has been fixed in v3.x (still WIP) where the drop data is of type InventoryItem
.
I should probably clarify in the documentation that
item_dropped
only triggers if an item is dropped on top of anCtrlInventoryGrid
.
:+1:
But I think the best way to handle item drops outside the inventory is to first create a transparent control that is positioned behind the UI and spans the entire screen. Then you should be able to implement _drop_data and _can_drop_data for that control:
func _can_drop_data(at_position: Vector2, data: Variant) -> bool: return true func _drop_data(at_position: Vector2, data: Variant) -> void: print("Item dropped: %s" % str(data.item)) # Remove the item from the inventory, handle the item drop etc.
omw to try this, thank you for the proposed fix and the swift reply! :heart:
Note that in v2.x the type of the
data
parameter is defined insideaddons/gloot/ui/ctrl_inventory_item_rect.gd
and the actualInventoryItem
must be accessed viadata.item
. This is something that has been fixed in v3.x (still WIP) where the drop data is of typeInventoryItem
.
I will keep this in mind, when implementing the above, ty!
I placed the above code on the class inventory_grid_stacked_transfer.gd
of the scene inventory_grid_stacked_transfer.tscn
and it works perfectly!
Pretty clean to work with just these 2 functions added (idk if there is code to detect if a control node has that function, but to work so easily was unexpected)
So clean that I would suggest a quick PR for both grid demos, until this feature is implemented via a proper PR which doesn't need a seperate Control to trigger/detect (basically OP's suggestion)
That said, I also tried putting a seperate Control
node to cover the entire screen. It works exclusively if the Control
node is ABOVE the UI inventories. Otherwise, if it is BELOW in the hierarchy, despite all possible mouse filter combinations, it doesn't work (either blocks inventory mouse, or isn't detected)
My use-case is covered, and am surprised it was so simple (literally copy-pasted lol) and I thank you for the quick answer! I will only keep this issue open for the official PR (where there is a signal on the item itself, or the inventory grid itself, instead of having this logic above them)
idk if there is code to detect if a control node has that function, but to work so easily was unexpected
This is actually a built-in Godot feature and the usual way of doing drag&drop in Godot. I didn't have to implement any logic that calls _can_drop_data
or _drop_data
, the engine already handles that. I just provide it the data associated with the drag&drop operation (the dragged control node in my case).
I would suggest a quick PR for both grid demos
Good idea 👍 It's not very obvious how to implement such functionality, while I think it is pretty common in games.
a proper PR which doesn't need a seperate Control to trigger/detect (basically OP's suggestion)
This would be good to have, but I'm trying to stick to the Godot-way of doing things and it seems like there is no straight forward way of detecting if a control has been dropped onto "empty space". There is the NOTIFICATION_DRAG_END notification that can be used with Viewport.gui_is_drag_successful() to detect failed drops, but in that case the drag data is null
and it's difficult to determine which item has been dropped.
I also tried putting a seperate Control node to cover the entire screen. It works exclusively if the Control node is ABOVE the UI inventories.
That's weird, I tested it recently and it should work (either with GLoot or plain Godot controls). Sometimes it happens that there's a second control covering the same area and blocking the drop, so it might be worth double-checking if there's a container or some other control that's transparent, making it not so obvious.
This would be good to have, but I'm trying to stick to the Godot-way of doing things and it seems like there is no straight forward way of detecting if a control has been dropped onto "empty space". There is the NOTIFICATION_DRAG_END notification that can be used with Viewport.gui_is_drag_successful() to detect failed drops, but in that case the drag data is null and it's difficult to determine which item has been dropped.
I see that it bloats the code. So I suggest the following PR to implement this feature and close this issue: The code you posted
func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
return true
func _drop_data(at_position: Vector2, data: Variant) -> void:
print("Item dropped: %s" % str(data.item))
ctrl_inventory_left.inventory.remove_item(data.item)
ctrl_inventory_right.inventory.remove_item(data.item)
#Custom logic for handling the item drop here 👈
placed on the root of the 3 grid demo scenes
inventory_grid_stacked_ex_transfer.gd
, inventory_grid_ex_transfer.gd
, inventory_grid_transfer.gd
, and a wiki/docs entry so its visible/known to all users, would close this issue :+1:
I am trying to implement a system where if you drag an item outside a grid inventory, it drops to the 3D game world. The first requirement needed for this, and my request, is to have a signal which triggers for grid inventories if you stop dragging an item outside the inventory, returning the item and the screen position it was dropped (Vector2)
And each inventory grid should also have
@export var remove_item_on_drop: bool
which triggers the above signal, if the item is dropped on a non-inventory, which deletes the item entirely (with the above signal, I can just map it to 3D items)As for the existing signal
item_dropped
I cannot get it to work :thinking: Specifically, this code on the classctrl_grid_basic.gd
I assume the proper location is where the item preview is?
Trying to hack away the code, I detect when the preview is destroyed (when dragging ends, see
set_drag_preview(preview)
, and connect a signal right there. But I have no way to find if it ended up in an inventory or outside.Also in that class is the signal
dropped(zone, position)
which is completely unused, perhaps it was meant for this?