Last active
October 20, 2017 19:52
-
-
Save noidexe/8263b062faac3e4401d91e51dfcd67c3 to your computer and use it in GitHub Desktop.
Drag n Drop example in Godot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends Node2D | |
signal picked | |
signal dropped | |
enum DRAGSTATES { PICKED, DROPPED } | |
var drag_state = DRAGSTATES.DROPPED | |
var prev_mouse_pos = Vector2(0,0) | |
var absolute_z = IntArray([0]) | |
var last_event | |
func _ready(): | |
if 0 != get_node("area").connect("input_event", self, "_on_area_input_event"): | |
g.g.console.perror("Error: Failed to connect area to input event") | |
pass | |
_calculate_absolute_z() | |
set_process_unhandled_input(true) | |
func _on_area_input_event( viewport, event, shape_idx ): | |
if ( | |
event.is_action_pressed("click") | |
and drag_state == DRAGSTATES.DROPPED | |
and not g.picking_object | |
): | |
#g.console.pprint("picked " + str(get_name()) ) | |
#_on_picked(event) | |
last_event = event | |
g.pickup_candidates.push_back(self) | |
elif event.is_action_released("click") and drag_state == DRAGSTATES.PICKED: | |
g.console.pprint("dropped " + str(get_name()) ) | |
_on_dropped(event) | |
pass | |
func _on_picked(event): | |
drag_state = DRAGSTATES.PICKED | |
g.picking_object = true | |
prev_mouse_pos = get_global_mouse_pos() | |
pass | |
func _on_dropped(event): | |
#if !event: event = last_event | |
drag_state = DRAGSTATES.DROPPED | |
g.picking_object = false | |
_calculate_absolute_z() | |
pass | |
func _unhandled_input(event): | |
if ( | |
event.type == InputEvent.MOUSE_MOTION and | |
drag_state == DRAGSTATES.PICKED | |
): | |
set_pos(get_pos() + (get_global_mouse_pos() - prev_mouse_pos)) | |
g.camera.move_to(get_global_pos()) | |
prev_mouse_pos = get_global_mouse_pos() | |
pass | |
func _calculate_absolute_z(): | |
absolute_z = IntArray([]) | |
var node = self | |
#Add node indices from leaf to trunk excluding root and scene root | |
while node.get_parent().get_name() != "root": | |
absolute_z.append(node.get_index()) | |
#if it's a child of YSort append the y position so that is used | |
#first and index only in case both y are equal | |
if node.get_parent() extends YSort: | |
absolute_z.append(node.get_pos().y) | |
node = node.get_parent() | |
pass | |
#invert array so indices are arranged trunk to leaf | |
absolute_z.invert() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#this node extends draggableObject.gd and plays an animation when the object is picked or dropped | |
extends "res://scenes/draggableObject/draggableObject.gd" | |
onready var anims = get_node("anims") | |
func _ready(): | |
pass | |
func _on_picked(event): | |
._on_picked(event) | |
anims.play("picked") | |
func _on_dropped(event): | |
._on_dropped(event) | |
anims.play("dropped") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends Node | |
## Reference to globally available systems and states. | |
#In game console | |
var console #Node | |
#Main camera | |
var camera #Node | |
#StreamPlayer for backgroud music | |
var music #StreamPlayer | |
#Drag n Drop state | |
var picking_object #bool | |
var pickup_candidates = [] | |
func _ready(): | |
_initialize() | |
set_process(true) | |
pass | |
#Reload current scene | |
func reset(): | |
set_process(false) | |
_initialize() | |
get_tree().reload_current_scene() | |
#Initialization code for this node. To be called on run and on reset | |
func _initialize(): | |
console = null | |
camera = null | |
music = null | |
picking_object = false | |
pickup_candidates = [] | |
set_process(true) | |
print("Initialized %s" % get_name()) | |
func _process(delta): | |
if pickup_candidates.size() > 0: | |
_resolve_pickup() | |
#This picks the topmost candidate taking into account position within the scene tree and YSort nodes. It currenty ignores the Z property. | |
func _resolve_pickup(): | |
var good_list = [] | |
var iteration = 0 | |
while pickup_candidates.size() > 1: | |
good_list = [] | |
for candidate in pickup_candidates: | |
if good_list.size() == 0: | |
good_list.push_back(candidate) | |
else: | |
var abs_z = good_list[good_list.size()-1].absolute_z[iteration] | |
if candidate.absolute_z[iteration] == abs_z: | |
good_list.push_back(candidate) | |
elif candidate.absolute_z[iteration] > abs_z: | |
good_list = [candidate] | |
pickup_candidates = good_list | |
iteration +=1 | |
var winner = pickup_candidates[0] | |
winner._on_picked(winner.last_event) | |
pickup_candidates = [] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment