Operating system or device - Godot version:
Windows 10, Godot 3.0.alpha 01d4ffd3ee8abbbfba45871ee8d83eee18d3bf97
Issue description:
"Control node -> mouse filter" doesn't seem to be working properly. I believe that "stop" and "pass" mouse filters should behave differently- "stop" should accept and stop input event and "pass" should accept the input event and pass it further, so that the Control nodes which are below could access the same event until it is either stopped somewhere or simply just becomes unhandled event.
Steps to reproduce:
Place two button nodes with some overlap; when user clicks on the overlapping area, only one button(the top one) gets pressed.
Link to minimal example project:
Is this still valid in the current master branch?
As of da4edf83d, "Stop" and "Pass" work as expected, except that events seem to propagate UP the hierarchy, instead of DOWN, as most people (myself included) would expect.
I wouldn't expect that UP direction, I wound up reworking my controls hierarchy because of this.
Even if UP is intended and desired, it __needs__ to be documented.
I have no idea why people would expect an inverse propagation, to me that
makes no sense or has any use case. Feel free to documment the current
behavior in that property if you wish anyway.
On Fri, Jan 5, 2018 at 2:01 PM, Martin Green notifications@github.com
wrote:
Even if UP is intended and desired, it needs to be documented.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/godotengine/godot/issues/10511#issuecomment-355607571,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AF-Z26RWPXfmoGbZLkya2aTq49F8ARzFks5tHlVxgaJpZM4O9sor
.
It also seems pretty evident to me that events should propagate from child to parent, just like drawing happens. Imagine this structure:
- Panel
- VBoxContainer
- Label
where all those nodes overlap in the UI (so the Label is layared ON TOP of the VBoxContainer which is layered ON TOP of the Panel). If you click on a pixel shared by all those nodes, it's logical that the event propagation goes Label -> VBoxContainer -> Panel, no? Or do I misunderstand what you're discussing?
After a little thought, I agree that events bubbling up is __logical__ and __correct__, but it's also somewhat unexpected, as evident from this issue and #10320. InputEvent docs should be updated to make this clear. I'll work on a PR.
I think there was really a bug beyond the documentation need, but it has been fixed in the meantime. The actual documentation about event propagation is improved in https://github.com/godotengine/godot-docs/pull/952.
I think the misunderstanding comes from the expectation of sibling elements or child elements of a parent node that would handle the events normally on IGNORE, but don't on PASS. e.g.:
- Panel
- VBoxContainer
- Button
- Label
The button is below (UI-wise) the label, and therefore the label would normally block the events unless set to IGNORE. Setting it to PASS however, only passes the events directly to VBoxContainer and they will only propagate from there - the Button never receives any event.
Intuitively, "pass" to me would make me think it handles the events and then passes them along as per usual to underlying UI elements, not only through the direct parents in the node hierarchy. Every time that I pick up Godot again I have to remember how this works or if it was even a bug because it always catches me off guard.
Hi
@Banderi and @UgisBrekis
im breaking my head here to understand the same thing. I agree with you, pass will trigger the event in current element and will let under elements will be triggered too.
In my case i build a select stage that is:
Button cannot trigger the event and let ScrollContainer be trigger too to scroll.
There is any way to solve it?
Hey @prsolucoes, I'm not sure I understand the setup.
Are you trying to get multiple buttons to activate when on top of each other?
Hi,
No. I put a set of texture buttons inside scroll container and want drag over the buttons to go to other part of scrolls:
1 [ screen ]
2 [ (button) -- (button) -- (button) -- (button) -- (button) -- (button) ]
3 [ screen ]
When i drag over button on item 2, i want move entire list, but button don't propagate events to scroll container.
Im using a script that i found here on one issue to do it:
https://github.com/godotengine/godot/issues/21137#issuecomment-595045811
But the script has only one problem. When i release drag it propagate button release. Im using it with this problem and will publish my game with this. But to be perfect i don't want that it propagate event after drag, only when i only click/touch. My current code on scroll view:
SimpleScrollContainer.gd
extends ScrollContainer
var swiping = false
var swipe_start
var swipe_mouse_start
var swipe_mouse_times = []
var swipe_mouse_positions = []
func _input(ev):
if ev is InputEventMouseButton:
if ev.pressed:
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]
else:
swipe_mouse_times.append(OS.get_ticks_msec())
swipe_mouse_positions.append(ev.position)
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
else: break
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()
add_child(tween)
var delta = ev.position - flick_start
var target = source - delta * flick_dur * 15.0
tween.interpolate_method(self, 'set_h_scroll', source.x, target.x, flick_dur, Tween.TRANS_LINEAR, Tween.EASE_OUT)
tween.interpolate_method(self, 'set_v_scroll', source.y, target.y, flick_dur, Tween.TRANS_LINEAR, Tween.EASE_OUT)
tween.interpolate_callback(tween, flick_dur, 'queue_free')
tween.start()
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)
swipe_mouse_times.append(OS.get_ticks_msec())
swipe_mouse_positions.append(ev.position)
Will be nice if the script has this correction. I tried somethings, but without success.
Thanks.
Most helpful comment
It also seems pretty evident to me that events should propagate from child to parent, just like drawing happens. Imagine this structure:
where all those nodes overlap in the UI (so the Label is layared ON TOP of the VBoxContainer which is layered ON TOP of the Panel). If you click on a pixel shared by all those nodes, it's logical that the event propagation goes Label -> VBoxContainer -> Panel, no? Or do I misunderstand what you're discussing?