Closed rh101 closed 1 year ago
The way the current touch system works with regards to EventListenerTouchAllAtOnce and EventListenerTouchOneByOne is unexpected, and in my opinion, not correct. For example:
root_node (EventListenerTouchOneByOne)
├─ node_1 (EventListenerTouchOneByOne)
├─ node_2 (EventListenerTouchOneByOne)
├─ node_3 (EventListenerTouchAllAtOnce)
If you have a node tree as such, where node_3 is the one with the highest Z value, I would expect touch handling to be done in the order:
node_3, node_2, node_1, and finally root_node.
What actually happens at the moment is this order:
node_2, node_1, root_node, and finally node_3
From my understanding, touch handling should be done from the the highest Z order to the lowest. Splitting it into two different loops, one for EventListenerTouchAllAtOnce and another for EventListenerTouchOneByOne, means that the Z ordering between these two types of event listeners is not catered for.
I don't see any simple way to fix the EventDispatcher for this (without performance issues and such).
Now, regarding the RichText URL issue, I'll submit a PR to use EventListenerTouchOneByOne
instead of EventListenerTouchAllAtOnce
for the touch handling, and if anyone finds issues with it, then we'll figure out what to do next.
If a
RichText
with a clickable URL is a in the scene, and there is another node in the scene that has aEventListenerTouchOneByOne
listener, and theonTouchBegan
returns true (along withsetSwallowTouches(true)
), then the URL handler will not be triggered.The URL touch handler is implemented with this code (in
UIRichText.cpp
, classListenerComponent
):All
EventListenerTouchAllAtOnce
listeners will never be triggered if anyEventListenerTouchOneByOne
exist that returns true ononTouchBegan
.The reason is in function
EventDispatcher::dispatchTouchEvent(EventTouch* event)
, where the dispatcher first calls allEventListenerTouchOneByOne
listeners, and then if any returntrue
foronTouchBegan
, it removes the entries from a variable namedmutableTouches
(which holds all current touches).Once it loops through all
EventListenerTouchOneByOne
listeners, it then gets to the following code which should handle all theEventListenerTouchAllAtOnce
event listeners:The problem is that the
if
condition is false, sincemutableTouches
is empty, so it never enters that block, and noEventListenerTouchAllAtOnce
listeners ever receive the touch inputs.The main issue is that
EventListenerTouchOneByOne
andEventListenerTouchAllAtOnce
are not sorted together (by priority and Z order), so even if a node usingEventListenerTouchAllAtOnce
is on top of every other node in the scene, it would never be called because of other nodes usingEventListenerTouchOneByOne
. This is what doesn't make sense to me.My question is, does anyone know why
EventListenerTouchAllAtOnce
was used for the URL touch handler? IfEventListenerTouchOneByOne
is used, then this issue does not occur, but I'm not sure if there would be any side-effects.All
Widget
sub-classes (likeui::Button
etc) useEventListenerTouchOneByOne
, and they all work as intended, even to callopenURL
.One other thing,
EventListenerTouchAllAtOnce
is ONLY used for theRichText
URL handler; I can't find any usage of it at all in the Axmol source code (not including thecpp_tests
project of course).