Random beginner-question: stop swipe-scrolling on finger-tap

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

Hi everyone,

I have my scroll-container up and running for mobile-tochscreen and everything scrolls smoothly „freely“ when I do a swipe until the scrolling gradually comes to a halt. This is my code:

extends ScrollContainer

var swiping = false
var button_down = false
var swipe_start
var swipe_mouse_start
var swipe_mouse_times = []
var swipe_mouse_positions = []

signal finger_started_swiping
signal finger_stopped_swiping

func _ready():
	mouse_filter = Control.MOUSE_FILTER_IGNORE

func _on_Button_button_down(): # coming from buttons within this container
	print ("button down")
	button_down = true
	swiping = false

func _input(ev):
# swiping to be possible only within the container-area:
	if (!self.get_global_rect().has_point(ev.position)):
		swiping = false
	if ev is InputEventMouseButton:
		if ev.pressed:
			swiping = true
			if not button_down:
			swipe_start = Vector2(get_h_scroll(), get_v_scroll())
			swipe_mouse_start = ev.position
			swipe_mouse_times = [OS.get_ticks_msec()]
			swipe_mouse_positions = [swipe_mouse_start]
			var source = Vector2(get_h_scroll(), get_v_scroll())
			#var idx = swipe_mouse_times.size() - 1 # original
			var idx = swipe_mouse_times.size() - 1
			var now = OS.get_ticks_msec()
			var cutoff = now - 100

			for i in range(swipe_mouse_times.size() - 1, -1, -1):
				if swipe_mouse_times[i] >= cutoff: idx = i
				else: break

			var flick_start = swipe_mouse_positions[idx]
			var flick_dur = min(0.7, (ev.position - flick_start).length() / 500)
# for smooth swiping:
			if flick_dur > 0.0:
				var tween = Tween.new()
				var delta = ev.position - flick_start
				var target = source - delta * flick_dur * 8.0
				#tween.interpolate_method(self, 'set_h_scroll', source.x, target.x, flick_dur, Tween.TRANS_QUAD, Tween.EASE_OUT)
				tween.interpolate_method(self, 'set_v_scroll', source.y, target.y, flick_dur, Tween.TRANS_QUAD, Tween.EASE_OUT)
				tween.interpolate_callback(tween, flick_dur, 'queue_free')
			if flick_dur == 0:
				print ("finger released --- not moving")
			swiping = false
			if not button_down:
	elif swiping and ev is InputEventMouseMotion:
		var delta = ev.position - swipe_mouse_start
		set_h_scroll(swipe_start.x - delta.x)
		set_v_scroll(swipe_start.y - delta.y)

The problem is: if I put my finger down while the smooth „free“ scrolling is still going on, it doesn’t stop, but will, when the scrolling ends, jump back to the position where my finger touched.
How could I have the scrolling instantly stop when touching the screen?

Unfortunately the signals scroll_started() and scroll_ended() won’t fire. These would be helpful… any ideas?

:bust_in_silhouette: Reply From: pferft

In the meantime, I put up this solution: I added a var tween_running = false and put tween_running = true right under tween.start(). At the beginning of func _input(ev): I added

if ev.is_action_pressed("mousebuttonclick"):
  if tween_running:

The only issue now is that the line add_child(tween) now throws the error

add_child: Can't add child to 'ScrollContainer', already has a parent 'ScrollContainer'.

It doesn’t crash the program at least. But still, any idea how I could get rid of the error?


…and of course, minutes later I found the easy fix.

Place a “real” Tween Node as a child of the ScrollContainer.
Get rid of var tween = Tween.new() and add_child(tweenG).
Replace all tween with $Tween.

The whole thing works like a charm (for now :wink: