+2 votes

Hello,
I´m having difficult understanding what I suppose should be a simple task.
I have a clickable map so that when i click over objects on the map I can select them, but of course I dont want the player to be able to click on the map THROUGH the GUI.
So I declared a mouse_on_map boolean variable to hold information about the position of the mouse, and linked it to GUI panels with mouse_entered() and mouse_exited()signals.

However it seems like that every button inside the monitored areas automatically trigger the mouse_exited() signal, setting mouse_on_map=true and tricking the game to think that the mouse is on the map and allowing the pressing of the button and selecting the map at the same time.
I know this thing should be managed with the mouse filters, but any combination of stop/pass/ignore seems not to work.

Can you explain the right combination of mouse filter of the parents and children nodes?

PS: is there a better way to mask the map and prevent it from being pressed rather than monitoring the mouse position? Something that block the mouse click to the first element it encounter?

in Engine by (1,430 points)

How are you detecting clicks on the map?
Usually, things that aren't GUI items should use _unhandled_input, which will be called only when input isn't handled by GUI nodes. It's explained here: http://docs.godotengine.org/en/3.0/tutorials/inputs/inputevent.html?highlight=_unhandled_input#how-does-it-work

If the UI doesn't cover all the screen (which would allow mouse to go through a pause menu for example), you can have an invisible Control on the menu that takes the whole screen and then blocks the mouse. Then you won't need any special boolean to monitor everywhere ;)

Wow, the unhandledinput(event) is exactly what I was looking for!
So basically the code for selecting the map will fire only if the mouse click is not consumed by any other node or _input(event), correct?
Super useful to know, thank you!

1 Answer

+1 vote
Best answer

How are you detecting clicks on the map?

Usually, things that aren't GUI items should use unhandledinput, which will be called only when input isn't handled by GUI nodes. It's explained here: http://docs.godotengine.org/en/3.0/tutorials/inputs/inputevent.html?highlight=_unhandled_input#how-does-it-work

If the UI doesn't cover all the screen (which would allow mouse to go through a pause menu for example), you can have an invisible Control on the menu that takes the whole screen and then blocks the mouse. Then you won't need any special boolean to monitor everywhere ;)

Note: I copied my post as answer because my comment started as a question... then I realized it could be an answer xD

by (27,825 points)
selected by

A related question:
thanks to your answer I´m using the mouse-left-click (detected with unhandled input) in order to select the tiles of my map.
Up to now I used TextureButtons to select objects placed above the map (armies, cities) with a left-click.
However, now I need to click on said objects with the right-click of the mouse too, but that does not produce any effect on buttons: I tried to add a pickable KinematicBody to the objects, but the CollisionObject_input(event) is the last one to be consumed and the result is that i pick the tile on the map below the object.

Is there a way to detect a right-click over a node without monitoring area entered/exited?

Whatever input is sent (right click, left click, mouse wheel etc), it will follow the same scheme of input as explained in the doc. If right-click doesn't work for some reason, maybe you need to change node, or implement input yourself.
If you decide to implement input on collision object and want this collider to "block" events, you can also set the event as handled (as seen in https://github.com/godotengine/godot/issues/16042 ) so that it won't be forwarded to next collision objects.

An important rule of this system is, a given element should not choose if it should be clicked or not every frame (i.e, it should not poll input globally with some ifs). It's the event system to decide that by calling the element, because otherwise you would loose control on what you want to interact with, and single elements would have to depend on everything else that could possibly cause them to not receive clicks for example.

An important rule of this system is, a given element should not choose if it should be clicked or not every frame (i.e, it should not poll input globally with some ifs). It's the event system to decide that by calling the element, because otherwise you would loose control on what you want to interact with, and single elements would have to depend on everything else that could possibly cause them to not receive clicks for example.

I kinda understood what you mean, that´s why I would prefer going with collision input event (i would prefer having a right-clickable-button, cause that would solve everything in a blink of an eye).
But the link you provided is not working :(

Dang, the website included the ')' into the link, I fixed it

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.