Created
June 8, 2019 00:04
-
-
Save PrestonKnopp/b53752f08b5446ff248c8cfa58105c2b to your computer and use it in GitHub Desktop.
Examples of Godot's Control drag and drop functionality. Test it out by downloading this tscn and adding it to a Godot project. It is entirely self contained in one scene.
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
[gd_scene load_steps=6 format=2] | |
[sub_resource type="GDScript" id=1] | |
script/source = "extends Control | |
class DragDataColor: | |
var sender: Object | |
var color: Color" | |
[sub_resource type="GDScript" id=3] | |
script/source = "extends Control | |
export(bool) var is_accepting_drop_data = true | |
# This control will accept drop data from a color source, such as: | |
# source_red, source_blue, or source_green. | |
# The following two functions are virtual, meaning you the programmer must implement it. | |
# Then the two functions will be called by the engine. | |
# The can drop data will take a position local within self's local coordinate system. | |
# The position (0,0) is the top left corner. | |
# | |
# The data will be from other controls that have implemented `get_drag_data()`. | |
# | |
# You can perform any logic in this function. You must return a `true` when you want | |
# to accept the `data` and `false` when you reject the data. You can use the `position` | |
# to determine if you want to accept or reject the `data`. Additionally, this method should be | |
# fast as it is called every mouse move event. | |
# | |
# Some examples of ways to check if can drop data usually include checking if the data | |
# contains a specific property or is of a certain type. You could also only consider data | |
# when a certain condition or state is met. | |
# | |
# In this example we will be using a simple state called `is_accepting_drop_data` and then | |
# a type check to see if `data` is of a `DragDataColor` type. | |
# | |
# We only check for type `DragDataColor` here because that is the only requirement for this example. | |
func can_drop_data(position: Vector2, data) -> bool: | |
print('can drop data') | |
# The following return statement is the condensed form, but logically equivalent of: | |
# if not is_accepting_drop_data: return false | |
# if data is DragDataColor: return true | |
# else: return false | |
# | |
# The following line reads nicely as: | |
# When self is accepting drop data and the drop data is of type DragDataColor then | |
# accept the drop data. | |
return is_accepting_drop_data and data is get_parent().DragDataColor | |
func drop_data(position: Vector2, data) -> void: | |
print('accepting drop data') | |
# Here we will actually use the data. | |
# In this example we want to take the position and add a new source in that position. | |
# We know that data is DragDataColor which has the sender property: | |
# Let's make it simple and duplicate that source, then add it as a child. | |
var new_source = data.sender.duplicate() | |
new_source.rect_position = position | |
add_child(new_source)" | |
[sub_resource type="GDScript" id=2] | |
script/source = "extends ColorRect | |
# get_drag_data() is a virtual function that you, the programmer, implement. | |
# The engine will call this method, if defined, on your behalf. | |
# As any function, you can perform any logic you want inside of it. | |
# | |
# You want to return the data (or metadata) that this control represents. | |
# In this example, this control just represents a color. We want other color controls to accept | |
# this control's source color. | |
func get_drag_data(position: Vector2) -> Object: | |
# For this example to be contained in one scene, | |
# the DragDataColor class is on scene root. | |
var DragDataColor = get_node('../..').DragDataColor | |
# First create the data to be passed: | |
var data = DragDataColor.new() | |
data.sender = self | |
data.color = color | |
# Then create a preview for that data: | |
# In this case we can just duplicate self | |
set_drag_preview(self.duplicate()) | |
return data" | |
[sub_resource type="GDScript" id=4] | |
script/source = "extends ColorRect | |
# This control will take other source colors and mix it with itself. | |
# It can also be dragged and dropped as well. | |
func can_drop_data(position: Vector2, data) -> bool: | |
return data is get_node('../..').DragDataColor | |
func drop_data(position: Vector2, data) -> void: | |
var c = data.color | |
c.a = 0.5 | |
color = color.blend(c) | |
func get_drag_data(position: Vector2) -> Object: | |
var data = get_node('../..').DragDataColor.new() | |
data.sender = self | |
data.color = color | |
set_drag_preview(duplicate()) | |
return data" | |
[sub_resource type="GDScript" id=5] | |
script/source = "extends ColorRect | |
# This control will remove itself after being picked up. | |
func get_drag_data(position: Vector2) -> Object: | |
var data = get_node('../..').DragDataColor.new() | |
data.sender = duplicate() # note: this will be leaked, but for simplicities sake, I'm still using this. | |
data.color = color | |
set_drag_preview(duplicate()) | |
queue_free() | |
return data" | |
[node name="test_drag_and_drop" type="Control"] | |
anchor_right = 1.0 | |
anchor_bottom = 1.0 | |
script = SubResource( 1 ) | |
[node name="destination_large" type="Control" parent="."] | |
anchor_right = 1.0 | |
anchor_bottom = 1.0 | |
script = SubResource( 3 ) | |
[node name="source_red" type="ColorRect" parent="destination_large"] | |
margin_left = 51.632 | |
margin_top = 69.1674 | |
margin_right = 91.632 | |
margin_bottom = 109.167 | |
color = Color( 0.843137, 0.364706, 0.364706, 1 ) | |
script = SubResource( 2 ) | |
[node name="source_blue" type="ColorRect" parent="destination_large"] | |
margin_left = 104.238 | |
margin_top = 69.1673 | |
margin_right = 144.238 | |
margin_bottom = 109.167 | |
color = Color( 0.364706, 0.462745, 0.843137, 1 ) | |
script = SubResource( 2 ) | |
[node name="source_green" type="ColorRect" parent="destination_large"] | |
margin_left = 155.87 | |
margin_top = 69.1674 | |
margin_right = 195.87 | |
margin_bottom = 109.167 | |
color = Color( 0.364706, 0.843137, 0.384314, 1 ) | |
script = SubResource( 2 ) | |
[node name="source_and_destination_mix" type="ColorRect" parent="destination_large"] | |
margin_left = 106.186 | |
margin_top = 123.722 | |
margin_right = 146.186 | |
margin_bottom = 163.722 | |
script = SubResource( 4 ) | |
[node name="pickup_source" type="ColorRect" parent="destination_large"] | |
margin_right = 40.0 | |
margin_bottom = 40.0 | |
script = SubResource( 5 ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment