godot
godot copied to clipboard
ScrollContainer scroll_started and scroll_ended signals aren't emitted
Bug?
Godot version: 3.0.6 stable
OS/device including version: Windows 7 pro / Linux Mint 19
Issue description: Signals "scroll_started()" and "scroll_ended()" never fired
Steps to reproduce: Create Scene with ScrollContainer Create Panel inside ScrollContainer (min_size > ScrollContainer) Link Signals (printing out to console) -> When scrolling with mouse or touch signals are never received
_gui_input is not called when using the scrollbars. And even if it got called drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); will always be false, if there is no touch emulation, so scroll startet is never emited.
Is drag_touching in the if clause in line 169 of scroll_container.cpp really neccessary? ( if (drag_touching && !drag_touching_deaccel) { )
It's seems that the problem become worse in Godot 3.1 alpha 5 , i can't emulate scrolling even if emulate touch screen option is enabled from Project configuration.
Just commenting to add that mouse_entered and mouse_exited signals aren't triggering either. I think it's safe to assume that none of the scrollcontainer signals work.
Tested with 3.1 btw.
edit: had a node in front of it that was set to Show Behind Parent
, setting it's mouse filter appropriately fixed it, doh.
Does not work on 3.2 mac. There is no work around for this issue
I can confirm the same on Mac OSX Mojave 10.14.6 (18G95) - ScrollContainer events are not firing.
I was able to get_vscrollbar() and connect to scrolling
signal, but scrollcontainer events do not seem to work at all. Mouse, focus, etc. I am using Godot_mono but working with GDScript.
Here is what I am doing to workaround this problem - create a timer that will clear after half a second, and then if you're still scrolling reset that timer.
extends ScrollContainer
var timer: SceneTreeTimer = null
func _ready():
get_v_scrollbar().connect('scrolling', self, 'on_scroll')
func on_scroll():
if !timer:
timer = get_tree().create_timer(.5)
timer.connect("timeout", self, "clear_scrollbar_dragging")
func clear_scrollbar_dragging():
timer = null
I am also experiencing this problem (Windows 10 Pro v1903). I'm looking to update the position of a sprite when the user stops scrolling. Is there a solution that would be more smooth especially if one is scrolling fast?
I hope, this will be fixed soon! I have the same problem.
Also experiencing this issue. Please fix, there is no clean workaround.
It looks like I'm still experiencing this issue with Godot 3.2.3 when testing on a PC.
But once I run on my mobile phone (which is my target device), the events fire as expected.
It's a bit disconcerting to not have it work on PC, so I still hope that a PR for this can be merged soon.
See also https://github.com/godotengine/godot/issues/46421.
Workaround I just found: connect to "value_changed" (Scrollbar inherits from Range) instead.
I can reproduce the issue on Godot 3.4.2-stable under macOS Big Sur (11.16.2). Neither signal works.
This issue is reproducible in Godot 3.5.2 and Godot 4.0. In addition to that in 4.0 changed
signal is not raised.
Also, if there is some help around dead zone functionality it will help.
P.S: If MRP for 4.0 and 3.5.2 is required I can upload it.
Just to update on the issue further. The signals are emitted in android devices, at-least in emulators I have tested. It seems the dead zone has to do something with this as per code. Need to understand more of this dead zone functionality. Note: It still does not work in desktop dev environment
Godot 4.2, issue persists to this day. Thankfully, I don't actually need this functionality, but someone else might.
Trying to nail down what desired behaviour is.
Clicking and dragging the scroll bar handle seems straighforward: a scroll_started
when the mouse button goes down on the handle (or first movement after mouse button down) and scroll_ended
when the mouse button is released (even if there are moments when the mouse movement pauses).
More complex are the mouse wheel interactions. Godot sees them as individual events, so there's no real "start" or "end" to them. Even if you spin the mouse wheel, Godot just sees them as a series of events.
So I guess in this situation we use a timer, like what @sporeservant used for their own project? Each time the scroll bar moves, a scroll_started
event is triggered and a timer starts. Each scroll bar movement from then on resets the time, and if the timer runs out, a scroll_ended
event is fired? It could even work for dragging the scroll handle.
Is this the preferred solution? And if so, what should the timeout value of the timer be?
You can get a reliable scroll started signal that emits at the right time by connecting item_rect_changed
on the child control of the ScrollContainer
with a CONNECT_DEFERRED
flag. This seems to be the only way to avoid delayed or late scroll started signals. This approach is also agnostic to how the scroll is initiated.
To get a scroll ended signal, you can create a "debounce" timer that's started on the item_rect_changed
signal, and after some timeout, emits a custom scroll ended signal.
So this will mean the signals will be triggered regardless of how the scroll is initiated, including programmatically. It would also replace the current system for inertia scrolling. Is this the desired behaviour?