0 votes

Hello all,

I'm trying to make simple 3D game, where you need to drag-and-drop objects to assemble things mechanically.
What I've already accomplished is that you can grab an object, drag it to "Area" node (where it registers a mouse_enter event) and snaps it on mouse button release.
When you want to detach the object, you click on the area, and then the last object snapped becomes animated and follows the mouse.
The problem: When I click on the area and hold the mouse button to drag, other Areas do not receive any event. The strange thing is - if I move the mouse out of the whole window and get it back to Area - it registers.

Any ideas appreciated!

Heres the code detecting events, "unit" is the box where I need to drag and snap objects to:

    extends Spatial

signal unitSelected
signal unitDeselected
signal unitMouseEntered
signal unitMouseExited

var itemName

func _ready():
    var _err = self.connect("mouse_entered", self, "_on_mouse_entered")
    _err = self.connect("mouse_exited", self, "_on_mouse_exited")
    _err = self.connect("input_event", self, "_on_input_event")

func _on_input_event(_camera, event, _position, _normal, _shape_idx):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT:
            if event.pressed == true:
                emit_signal("unitSelected", int(self.name.replace("Unit", ""))) #inject unit number as an argument
            else:
                emit_signal("unitDeselected", int(self.name.replace("Unit", "")))

func _on_mouse_entered():
    $SelectBox.show()
    emit_signal("unitMouseEntered", int(self.name.replace("Unit", "")))

func _on_mouse_exited():
    $SelectBox.hide()
    emit_signal("unitMouseExited", int(self.name.replace("Unit", "")))

Edit: uploaded behavior (yellowish cube is shown with $SelectBox.show()):
https://giphy.com/gifs/Qfs7ow7aTaOOvg82FS

Godot version v3.4.2
in Engine by (15 points)
edited by

You mean all objects are detectable areas, that can be dragged onto each other and trigger something on combination ?

Areas don't detect collision when button is held, is it ? Make several print statements to determine if this is because of Input, drag function or object selection.
Make print statements to check what is being blocked - mouse entered signal, or only subsequent code.
Make sure other control nodes, like this selectbox don't obscure and consume mouse input.
Are your unitselected emitted once per click, or constantly while button is pressed ? I am afraid it is the latter. What is listening to unitselected signal, and can it affect mouse enter detection ?

You mean all objects are detectable areas, that can be dragged
Not exactly - the areas themselves are static and cannot be moved; the objects can be dragged into and out of those areas (I call them units in the code, but You can imagine just as slots for objects).

Just added the print statements to the beginning of every event, and I can confirm this:
**... or constantly while button is pressed ** , it always calls the oninput_event() after click.
I learn from prints that this happens:

  1. I move the mouse onto area.
  2. onmouse_entered() calls $SelectBox.show(), which shows that area reacted now.
  3. I click on the area and hold.
  4. oninput_event() is called on click, which then goes to signaling other nodes. I'm not moving the mouse at this moment.
  5. I move the mouse (in area) - oninput_event() calls again.
  6. I move the mouse outside the area - oninput_event() keeps calling again.
  7. No onmouse_exited happened!!
  8. I release the mouse button - oninputevent() AND _onmouse_exited calls, which then signals "unitDeselected" and "unitMouseExited".

I imagine that somehow the frame processing goes to oninput_event() and it somehow halts enter and exit calls from happening

no, input processing is fine, since even mouse movement triggers input event. It is good, unless it prints that left mouse click is the only event detected all the time.

Is there anything more that happens after click ? Like some kind of preview icon being picked and dragged on process ?

There's "_input()" code in each of the object's script:

func _input(event):
    if grabbed and (event is InputEventMouseMotion):
        var camera = get_node("Camera")
        var distance_to_frame = camera.translation.distance_to(get_tree().get_root().get_node("Spatial/spawn").global_transform.origin)
        var to = camera.project_position(event.position, distance_to_frame)
        self.global_transform.origin = to;

Basically when you click on object and hold, the "grabbed" flag is set to true. When you let go - "grabbed" is set to false, so "self" is not moved.
The code I pasted on my question is from the area script; so when you click and hold an area it pops the object and then sets this script's "grabbed" flag to be true.

I've added more printf statements and it seems that if I click and drag the mouse outside the area - the "input" code above and the area's "oninputevent()" are called simultaneously, but when I stop - no event is happening. And then, same as before, "mouseexit()" event calls only when I release the mouse button...

2 Answers

0 votes
Best answer

So finally I was able to fix it.
Issue was silly as so was I, when asking about it.

In area I had "Capture On Drag" Flag set to true, and this thing always called "input" function, thus disabling the "mouse exit" function from calling.

I found out this by creating dummy scene with two areas and nothing else, and it worked OK; so quickly found the difference.

by (15 points)
selected by
0 votes

But what are objects ? Are they also Area2d ? I can see You are influencing their global transform. This must be where the problem originates. Try to rewrite movement in any other way for testing, for example by moveandcollide() instead of arbitrary updating transform.

by (5,651 points)

The "object" that is being moved to Area is "rigid body". Yeah, I forgot to mention that my game is 3D (I edited my first post with .gif explaining a bit the situation).
hmm, I will try to use something different for moving the rigid body.

if they are rigidbodies than just use apply_central_impulse in a direction your area is. Just for test, to check if holding left click will also interrupt collision detection when using movement intended for bodies

I didn't use the "applycentralimpulse", but I dropped the rigidbody from different places, and it detects collision OK. It seems that nothing else stops, except area itself.
I have a feeling it is working similarly as button press - it is not released even if mouse is moved out from button while holding mouse button.

Actually I found another strange behavior (well strange for me, maybe it supposed to work like this):
1. I press and hold on area.
2. I drag the mouse out of the area.
3. "mouse exited" function is not called from area (as before).
4. I drag mouse cursor over a button (I have a simple 2D menu button up front on 3D view).
5. "mouse exited" is called! Area is not "selected" anymore.
6. Other areas can call "mouse entered" function when mouse is dragged into them. I didn't release mouse button this whole time.

So hovering over button somehow "unfreezes" the area behavior.

That is what I suspected in the first answer :
"Make sure other control nodes, like this selectbox don't obscure and consume mouse input"
Is your UI anchor set to full viewport ? Find mouse_filter property of this UI, and every UI, and set it to ignore, then check if collision works

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.