SpyrexDE / SmoothScroll

Addon for the Godot Game Engine that adds a SmoothScrollContainer.
https://spyrexde.github.io/SmoothScroll/
MIT License
132 stars 11 forks source link

Weird flickering when overdragged and scrolling the opposite direction #2

Closed Kazuren closed 1 year ago

Kazuren commented 2 years ago

To reproduce and for the effects to be more visible:

Make a SmoothScrollContainer that has a VBoxContainer as a child Add a lot of ColorRect nodes as children of the VBoxContainer so we can scroll Set Speed to 10 Set Damping to a small value like 0.05 or 0.1 Scroll past the top(overdragging) and quickly scroll down to notice the 1 frame "snap" that occurs Scroll past the bottom and quickly scroll up for the same thing to happen Has something to do with this line of code set_v_scroll(-pos.y) because when I remove it, it works fine, but that removes the smoothness of the scrollbar

SpyrexDE commented 2 years ago

Has something to do with this line of code set_v_scroll(-pos.y) because when I remove it, it works fine, but that removes the smoothness of the scrollbar

You are absolutely right. Currently, the smooth moving of the SmoothScrollContainer's child is made by overwriting the position of the node after it has been moved by the default behavior of the scroll container. As you already experienced, this does not update the scroll bar's position. So I had to call set_v_scroll(-pos.y) because besides updating the content's position, this function also updates the position of the scroll bar. This workaround to overwrite the scroll container's default behavior seems to work very well except for this one frame you pointed out. In this frame, the "original" content position (on top or bottom) is drawn before the position, overwritten by the script could be drawn. I am currently a bit unsure how to solve this. Trying to only use set_v_scroll when not over dragging like this didn't fix the issue:

if top_distance < 0 and bottom_distance > 0:
    set_v_scroll(-pos.y)

If you (or somebody else) have any ideas please tell me 👍

Kazuren commented 2 years ago

Okay I think I figured it out. The VScrollBar node has some values you can set which I couldn't find in the documentation but I could find them when I added the node manually to a scene as seen below. image setting allow_greater and allow_lesser to true in the _ready() function seems to fix bug

func _ready() -> void:
    var v_scrollbar: VScrollBar = get_v_scrollbar()
    v_scrollbar.allow_greater = true
    v_scrollbar.allow_lesser = true
    v_scrollbar.connect("scrolling", self, "_on_VScrollBar_scrolling")
    for c in get_children():
        content_node = c
Kazuren commented 2 years ago

I just noticed a side-effect though, if we're manually dragging the bar with the mouse we can make it exceed the max value(for some reason not the min value) and it will also get stuck there unless we scroll again.

Kazuren commented 2 years ago

I just noticed a side-effect though, if we're manually dragging the bar with the mouse we can make it exceed the max value(for some reason not the min value) and it will also get stuck there unless we scroll again.

setting allow_greater and allow_lesser on the VScrollBar to the opposite of scrolling when scrolling changes fixes that. However it might not be the best fix. Also I've noticed that when the mouse is over the scrollbar and we scroll with scroll wheel all the smoothness is gone and it behaves like a normal ScrollContainer, could be a good place to look to improve this further 😃

SpyrexDE commented 1 year ago

Fixed by #12