How to have buttons ignore input while drag scrolling on button list.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Wasamiam
:warning: Old Version Published before Godot 3 was released.

As is, when scrolling through a button list on mobile, pressed signals are sent as soon as a touch occurs, without first checking if the user is scrolling. I’m not sure if it’s just not implemented for mobile. This can be applied to most controls that have pressable buttons like trees and itemlists. Please tell me your work around for this.

:bust_in_silhouette: Reply From: ingo_nikot

how did you connect your buttons to the signals?

as a work around, you could make the buttons only react on doubleclick/doubletapping.

I’ve been trying to connect Button signals to a function.

Wasamiam | 2016-12-13 03:18

to ask more specific:
a: what signal did you use
b: did you connect them via gdscript or via godot ide?

maybe you could give us some code.

ingo_nikot | 2016-12-13 11:57

I would like to just use Object.connect() with the Button signal, pressed(). I must have explained my problem wrong, because you shouldn’t need any code to understand it. If I make a scene with CanvasLayer > ScrollContainer > VBoxContainer > Buttons, then test it, I can scroll fine with swiping, but the Button below the beginning of the swipe will become pressed. Obviously on mobile, you don’t want buttons to be pressed while the user is scrolling. Does this make sense?

Wasamiam | 2016-12-13 23:59

I must have explained my problem wrong, because you shouldn’t need
any code to understand it

i only asked for code so i can use it to faster replicate the problem on my computer or to see an overseen mistake.

but after your description this sounds like a problem on godots part. moving your finger over the screen should be like mouse movement and not clicking. pls consider reporting this here:
https://github.com/godotengine/godot/issues

ingo_nikot | 2016-12-14 06:23

:bust_in_silhouette: Reply From: CKO

I have used a TextureButton inside a Panel (any control node will do) with the following input processing code:

func _on_ActionButton_gui_input(event : InputEvent) -> void:
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and _is_within_button(event.global_position):
			_handle_press(event.pressed)
		else:
			_reset_state()
	elif event is InputEventMouseMotion:
		if event.speed.length() > IDLE_DRAG_SPEED:  # has to be a small value between 10 and 20
			_reset_state()


# unfortunately gui_input event gets triggered even if event occurs outside control node area
func _is_within_button(event_position : Vector2) -> bool:
	return event_position.x >= rect_global_position.x and event_position.x <= rect_global_position.x + rect_size.x and \
			event_position.y >= rect_global_position.y and event_position.y <= rect_global_position.y + rect_size.y


# Using a timer to wait for 0.1s for any drag event to cancel triggering pressed action
func _on_Timer_timeout() -> void:
	if visible and not button.disabled:
		$Timer.stop()
		emit_signal("action_button_pressed")


func _reset_state() -> void:
	press_input_started = false

	if not $Timer.is_stopped():
		$Timer.stop()


func _handle_press(is_pressed : bool) -> void:
	if is_pressed:
		press_input_started = true
	elif press_input_started and $Timer.is_stopped():
		press_input_started = false
		$Timer.start()

The action_button_pressed signal is only emitted if panel is tapped and minimal or no dragging occurs until finger is removed from screen.

(TextureButton is only used for button state management (normal/pressed/hover/disabled))