Skip to content

Instantly share code, notes, and snippets.

@evan-boissonnot
Created June 25, 2021 22:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evan-boissonnot/5402aa38b37b330b5a2b565ec80c98c2 to your computer and use it in GitHub Desktop.
Save evan-boissonnot/5402aa38b37b330b5a2b565ec80c98c2 to your computer and use it in GitHub Desktop.
Godot - Drag and drop example in GDScript and C#
/**
* Handle input events on the current slot.
*
* @param InputEvent @event The input event to handle
*
* @return void
*/
public override void _GuiInput(InputEvent @event)
{
// If right click, then equip item
if (@event.IsActionReleased("right_click")) {
this.AcceptEvent();
var item = this.getItem();
if (item != null) {
this.unsetItem();
var parent = (BagContent) this.GetParent();
parent.emitEquip(item);
}
}
// If left click, force drag and drop
if (@event.IsActionReleased("left_click")) {
GD.print("ACTION RELEASED!");
this.AcceptEvent();
var item = this.getItem();
if (item != null) {
this.unsetItem();
var preview = this.getDragPreview(item);
this.ForceDrag(item, preview);
}
}
}
/**
* Returns the drag-and-drop preview for an item.
*
* @return Control | null
*/
public Control getDragPreview(Item item = null)
{
if (item == null) {
item = this.getItem();
}
if (item != null) {
var preview = new Control();
var sprite = new Sprite();
sprite.SetTexture(item.getIcon());
preview.AddChild(sprite);
return preview;
}
return null;
}
/**
* Unsets the current item and starts the drag-and-drop flow.
*
* @param Vector2 _pos The position clicked
*
* @return Item The item we want to drag
*/
public override Godot.Object GetDragData(Vector2 position)
{
var item = this.getItem();
var preview = this.getDragPreview();
this.SetDragPreview(preview);
this.unsetItem();
return item;
}
/**
* Checks whether we can drop the item on the current slot.
* If the item is of class Item, then return true. Else return false
*
* @param Vector2 position The position clicked
* @param Variant data The dropped data
*
* @return bool True if we can drop the item here, false otherwise
*/
public override bool CanDropData(Vector2 position, object item)
{
if (item is Item) {
return true;
}
return false;
}
/**
* Drop an item on the current slot. If the slot is already occupied, swap them.
*
* @param Vector2 position The click/drop position
* @param Item item The item to drop
*
* @return void
*/
public override void DropData(Vector2 position, object item)
{
if (Input.IsActionPressed("left_click")) {
this.CallDeferred("force_drag", (Item)item, this.getDragPreview((Item)item));
} else {
var oldItem = this.getItem();
if (oldItem == null) {
this.setItem((Item)item);
} else {
this.EmitSignal("swapItem", item);
}
}
}
/**
* Swaps the item currently occupying the slot with another one, and forces drag-and-drop on the current one
*
* @param Item item The item which to swap with the one currently on the slot
*
* @return void
*/
public void swapItem(Item item)
{
var oldItem = this.getItem();
this.unsetItem();
this.setItem(item);
var preview = this.getDragPreview(oldItem);
this.CallDeferred("force_drag", oldItem, preview);
}
"""
Handle input events on the current slot.
@param InputEvent ev The input event to handle
"""
func _gui_input(ev):
"""
If right click, then equip item
"""
if (ev.is_action_pressed("right_click")):
self.accept_event()
var item = self.getItem()
if(item != null):
self.unsetItem()
get_parent().emitEquip(item)
"""
if left click RELEASED, force drag and drop
"""
if (ev.is_action_released("left_click")):
self.accept_event()
var item = self.getItem()
if (item != null):
self.unsetItem()
var preview = self.getDragPreview(item)
self.call_deferred("force_drag", item, preview)
"""
Returns a new Sprite with an item's icon, so we can se what we are dragging.
@param Item _item The item we need to generate the preview for. If it's null,
get the current item.
@return Control A control node with a Sprite child, containing the preview.
Control is used because the drag preview needs to be a Control node (or a child of Control)
"""
func getDragPreview(item = null):
if (item == null):
item = self.getItem()
if (item != null):
var preview = Control.new()
var sprite = Sprite.new()
sprite.set_texture(item.icon)
preview.add_child(sprite)
return preview
return null
"""
Unsets the current item and starts the drag-and-drop flow.
@param Vector2 _pos The position clicked
@return Item The item we want to drag
"""
func get_drag_data(pos):
var item = self.getItem()
var preview = self.getDragPreview()
self.set_drag_preview(preview)
self.unsetItem()
return item
"""
Checks whether we can drop the item on the current slot.
If the item is of class Item, then return true. Else return false
@param Vector2 _pos The position clicked
@param Variant _item The dropped data
@return book True if we can drop the item here, false otherwise
"""
func can_drop_data(pos, data):
if (data is Item):
return true
return false
"""
Drop an item on the current slot. If the slot is already occupied, swap them.
@param Vector2 _pos The click/drop position
@param Item _item The item to drop
@return void
"""
func drop_data(_pos, _item):
if(Input.is_action_pressed("left_click")):
self.call_deferred("force_drag", _item, self.getDragPreview(_item))
else:
var oldItem = self.getItem()
if (oldItem == null):
self.setItem(_item)
else:
emit_signal("swapItem", _item)
"""
Swaps the item currently occupying the slot with another one, and forces drag-and-drop on the current one
@param Item item The item which to swap with the one currently on the slot
@return void
"""
func swapItem(item):
var oldItem = getItem()
self.unsetItem()
self.setItem(item)
var preview = self.getDragPreview(oldItem)
self.force_drag(oldItem, preview)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment