0 votes

What I want to achieve:
1. Drag and drop in 2d space moves the Node2D
2. Drag from the control node to 2d space should create a new Node2D
3. Drag from the control to a control node should do nothing
4. Drag from 2d space to the control node should delete the Node2D

I managed to implement 1, 2 and 3 with the signal based approach below, but how do I do 4? I tried to use "candropdata" / "drop_data" but could not get it to work either.


Project structure
- world (Node2d)
-- 2DThingy (Area2d with sprite and collision)
-- Menu (ColorRect)

world.gd

extends Node2D
var held_object = null

func _ready():
    for node in get_tree().get_nodes_in_group("pickable"):
        node.connect("clicked", self, "_on_pickable_clicked")

func _on_pickable_clicked(object):
    if !held_object:
        held_object = object
        held_object.pickup()

func _unhandled_input(event):
    if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
        if held_object and !event.pressed:
            held_object.drop()
            held_object = null

func _on_Menu_sprite_pickup(sprite):
    if !held_object:
        print("create sprite")
        held_object = sprite
        add_child(sprite)
        sprite.pickup()

func _on_Menu_sprite_drop_scene():
    if held_object:
        print("drop sprite in scene")
        held_object.drop()
        held_object.connect("clicked", self, "_on_pickable_clicked")
        held_object = null

func _on_Menu_sprite_drop_menu():
    if held_object:
        print("drop sprite in menu")
        remove_child(held_object)
        held_object = null

2DThingy.gd

extends Area2D 
signal clicked
var is_held = false

func _ready():
    pass

func _physics_process(delta):
    if is_held:
        global_transform.origin = get_global_mouse_position()

func _input_event(viewport, event, shape_idx):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT and event.pressed:
            emit_signal("clicked", self)

func pickup():
    if is_held:
        return
    is_held = true
    set_process_input(false)

func drop():
    assert(is_held)
    is_held = false
    set_process_input(true)

Menu.gd

extends ColorRect

const Thingy2D = preload("res://2DThingy.tscn")

signal sprite_pickup(sprite)
signal sprite_drop_scene()
signal sprite_drop_menu()

func _ready():
    connect("gui_input", self, "_on_gui_input")

func _on_gui_input(event):
    if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
        if event.pressed:
            var thingy = Thingy2D.instance()
            thingy.global_position = get_global_mouse_position()
            emit_signal("sprite_pickup", thingy)
        elif !event.pressed:
            var mouse_pos = get_global_mouse_position()
            # workaround for https://github.com/godotengine/godot/issues/20881
            if get_rect().has_point(mouse_pos):
                emit_signal("sprite_drop_menu")
            else:
                emit_signal("sprite_drop_scene")
asked Apr 24 in Engine by swenner (12 points)

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.