+1 vote

I am desgining a puzzle game, which involves the player click on on the right place (metas in RichTextLabel and CollisionShape of Area2D) to proceed.
This games features literarily "everthing clickable" that even some borders of GUI elements are clickable, and the screen is supposed to be littered with clickable elements.
And I want to notify the player that he clicked on the wrong place, so i need to know that the player clicked but not on the right place. There will be so many clickable elements, and their position may change depends on the chosen game language and window size, so it is impossible to make a "reverse mask" that covers every wrong place.
How can I filter every click event that is not on the right place?

My experiments so far:
1. _unhandled_input() is after GUI elements consumes inputs, and clicks on GUI elements, even not on the right place, will be consumed.
2. Setting GUI elements mouse filter to "Pass", however correct clicks will also be passed, and I only want the "you clicked on the wrong place" message to display when clicked not on the right place.
3. Get all inputs via _input(), and if it is on the right place, the corresponding callback will mark this input as "right". If no callbacks mark this input, it is "wrong". However I don't know when and where are all callbacks are guaranteed to finish so I can judge it's right or wrong. I could use a small time delay to expect all callbacks to finish, but that will be the most ugly thing to do.

in Engine by (28 points)

1 Answer

0 votes
Best answer

Simply add a Control-node (spanning the entire screen) as the background of your scene - use a CanvasLayer-node, if you don't want to make it the root-node. Clicking on any GUI-elements will stop the event propagation by default, so that Control-node will only receive "false" input-events, simply connect its gui_input-signal:

extends Control

func _on_Background_gui_input(event: InputEvent):
    if event is InputEventMouseButton:
        print("Wrong!")
by (10,221 points)
selected by

Thanks, I tried that before, the problem is, let me take RichTextLabel for example.
RichTextLabel support meta link, and click on the meta emit a signal, that's the "correct" result.
Non-meta text should be treated as "wrong", however with this method, they still stop the click event propagation. No signal emiited and the background node will not receive and input, so they become not right and not wrong.

That should fix it:

extends RichTextLabel

func _ready():
    self.mouse_filter = MOUSE_FILTER_PASS

func _on_RichTextLabel_meta_hover_started(meta) -> void:
    self.mouse_filter = MOUSE_FILTER_STOP

func _on_RichTextLabel_meta_hover_ended(meta) -> void:
    self.mouse_filter = MOUSE_FILTER_PASS

That's brilliant!

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.