How to detect mouse clicks on every unclickable place

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By sgsdxzy

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.
:bust_in_silhouette: Reply From: njamster

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!")

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.

sgsdxzy | 2020-05-29 13:03

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

njamster | 2020-05-29 13:28

That’s brilliant!

sgsdxzy | 2020-05-29 13:36