I have a VboxContainer as a child of a ScrollContainer and some text and buttons in it – a long list I can scoll through by finger-swiping on a touchscreen.
The code (based on https://github.com/godotengine/godot/issues/21137#issuecomment-414959543):
var swiping = false
var swipe_mouse_times = 
var swipe_mouse_positions = 
mouse_filter = Control.MOUSE_FILTER_IGNORE
if ev is InputEventMouseButton:
swiping = true
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
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
var flick_start = swipe_mouse_positions[idx]
var flick_dur = min(0.3, (ev.position - flick_start).length() / 1000)
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')
swiping = false
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)
print ("finger is swiping")
It works quite nicely, but there are three hurdles I need help with:
While swiping, the print "finger is swiping" is being printed all the time, many times, and I therefore assume that the signal "fingerisswiping" is being emitted as often as well. How can I have the signal being emitted only once per swipe? (Or is that a problem at all?)
How can I set a signal when my finger stops swiping (so when it's lifted from the touchscreen)?
I'd like the swipe-movement not to cause scrolling at all when touching a button in the list first. (My buttons work in a way so I can hold them down and make them not trigger by dragging the finger off... in such a case I'd like the list not to scroll despite the dragging.) I'd assume that I could have the button emit a signal which causes some "ignore swipe" or set the swipe speed to 0 maybe?
Yes, a simple
swiping = false does this trick!
Any suggestions are much appreciated!