0 votes

Hello, I'm trying to make a panel with one small texture rect (DragButton) which, when clicked and dragged, will drag and reposition its parent node (QueryPanel) and all of QueryPanel's children.

Right now, the code below will drag and resposition the DragButton. I cannot figure out how to make it drag and reposition QueryPanel.

Any ideas?

 extends TextureRect

var dragPosition = null

func _ready():
    hint_tooltip = "Drag Panel" 

func _on_DragButton_gui_input(event):
    if event is InputEventMouseButton:
        if (event.is_pressed() and event.button_index == BUTTON_LEFT):
            # start dragging
            dragPosition = get_global_mouse_position() - rect_global_position
        else: 
            # end dragging
            dragPosition = null


    if event is InputEventMouseMotion and dragPosition: 
        rect_global_position = get_global_mouse_position() - dragPosition
in Engine by (17 points)

For others using this, there's still the issue of keeping this panel on screen.

I know that I have to use _process(delta) to somehow clamp the panel to the viewport size, but I can't get it to work.

Any suggestions?

1 Answer

+1 vote
Best answer

You could try it with a signal.
At the top of the script you declare the signal: signal dragging(Vector2(position))
Then you emit the signal:

func _on_DragButton_gui_input(event):
if event is InputEventMouseButton:
    if (event.is_pressed() and event.button_index == BUTTON_LEFT):
        # start dragging
        dragPosition = get_global_mouse_position() - rect_global_position
        emit_signal("dragging",rect_global_position)
    else: 
        # end dragging
        dragPosition = null

May you will have to emit dragPositioninstead of rect_global position - that you have to test, I am always unsure with these.

However on your Parent Panel you can now connect the signal dragging. For that you have to click on your button and then Node where you will find your signal. Connect it and in the resulting function you could write:

func _on_dragging(position):
    rect_global_position = position

Another possibility to implement this is with get_parent()

On your button script you just decalte another variable:
var button_parent : Control = get_parent()

Then you could use button_parent.rect_global_position = rect_global_position

Personally I always try to avoid get_parent()because it can easily screw up entire scipts when you have to move scenes inside a node.

Hope that helps

by (140 points)
selected by

Thanks for the detailed comment!

I am not familiar with using signals and Vector2ds... when I declare the signal, it's saying there's an expected "identifier" missing the argument. I only see the Vector2d arguement, is there something else missing?

signal dragging(Vector2(position))

I am sorry. You have to declare signal dragging(position)
With that you tell the engine there will be a signal called dragging with one argument position.
Since the last update you could probably also declare signal dragging(position : Vector2) to clarify the type of the argument.

positionis then given to the function the signal connects to. i.e. to func _on_dragging(position)

I would heavily recommend to read up on signals. They are incredibly useful. I use them all they time to communicate between scenes.

Thanks!

if event is InputEventMouseMotion and dragPosition: 
    rect_global_position = get_global_mouse_position() - dragPosition
    emit_signal("dragging", rect_global_position)

This is the part that worked the best for me. If I had it in the previous if statement, it would only update the panel when I left clicked. With if event is InputEventMouseMotion and dragPosition: the panel updates when I stop dragging.

You are a gentleman and a scholar!

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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.

Categories