Confusion with input events and screen touch

Godot Version

4.2.1 Stable

Question

Hi all!

I’m doing an android game. There’s an overworld map and I have a touch screen camera that you can move by dragging with one finger, and zoom with pinching.

So far so good.

Now I want the user to touch a specific area of the overworld so they can, at first touch, highlight the region, and in second touch, activate the behaviour.

Problem is that dragging and touching events get overlapped, highlighting the region while paning the camera, see the gif attached:

I have tried to set the the input as handled both in the camera dragging and the map touch, but that doesn’t work.

The camera was processing input both in _input and _unhandled_input virtual functions, whereas the map is connected to the input_event signal.

Thanks all!

In a Viewport, the order of these is:

  1. _input
  2. _unhandled_input
  3. input_event signal.

So if you set the event as handled in input_event, then it doesn’t have any effect on 1. and 2.

Hi @Sauermann thanks a lot for your help!

I’m aware of this order, and I’m trying different places and orders. Let me throw some code in :slight_smile:

This is the code handling input in the touch camera.

func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventScreenTouch:
		if event.pressed:
			_events[event.index] = event
		else:
			_events.erase(event.index)
	
	if event is InputEventScreenDrag:
		_events[event.index] = event
		if _events.size() == 1:
			_handle_camera_move()
		elif _events.size() == 2:
			_handle_camera_zoom()

And this is the code in the area that has the region of the map that needs to highlight.

input_event.connect(
		func (_viewport: Node, event: InputEvent, _shape_idx: int):
			if event is InputEventScreenTouch and event.is_pressed():
				_toggle_focus()
	)

If I put the get_viewport().set_input_as_handled() line in the first line of the _unhandled_input method of the camera, the highlighting doesn’t work at all, as expected, since the camera has priority and consumes the event.

Since I only want to consume the event in case you’re dragging the camera, and let it be in all other cases, I have put the get_viewport().set_input_as_handled() line inside the if event is InputEventScreenDrag: if block, but the event is propagated even when dragging, which is what causes confusion to me.

I’m sorry if I’m being too detailed, hope this helps to clarify my problem a bit more.

Thanks again for your answer!

Ok, I solved it doing something different because I think this is not a problem of input transmission, but a problem with my game design.

Since I didn’t want to trigger the event logic of the map region after a touch camera drag, I just exposed the last used event of the touch camera in a static function, so the map region can access it safely and check if it is an InputEventScreenDrag event, in which case it will ignore the input completely.

Changes in the map region code:

input_event.connect(
		func (_viewport: Node, event: InputEvent, _shape_idx: int):
			if event is InputEventScreenTouch and event.is_released():
				var last_event := TouchScreenCamera.get_last_event()
				if not last_event is InputEventScreenDrag:
					_toggle_focus()
	)