3.x事件分发的一个Bug

1.在CCEventDispatcher.cpp的visitTarget(Node* node, bool isRootNode)函数里面,事件分发的时候没有先排序,造成快速点击时响应顺序不对。

void EventDispatcher::visitTarget(Node* node, bool isRootNode)
{    
    int i = 0;
    //node->sortAllChildren(); //这个地方应该先排一下序
    auto& children = node->getChildren();
    
    auto childrenCount = children.size();
    
    if(childrenCount > 0)
    {
        Node* child = nullptr;
        // visit children zOrder < 0
        for( ; i < childrenCount; i++ )
        {
            child = children.at(i);
            
            if ( child && child->getLocalZOrder() < 0 )
                visitTarget(child, false);
            else
                break;
        }
       .....
}


```

在场景渲染的时候Node::visit会调用Node::sortAllChildren()。分发事件在drawScene前后都有调用(这个地方没看懂怎么在一个函数里面分发了那么多次)。
造成的影响就是当点击很快的时候visitTarget里面的children有可能还没有来得及排序,然后缓存在_listenerMap中,之后的visit再排序已经没有作用(因为之后就不会再调用sortEventListenersOfSceneGraphPriority(listenerID, rootNode)这个函数)。


2.当parent隐藏的时候,listener的target还会接受事件,这点很不友好。(像ui::Button隐藏了就不会吞噬事件)


也是耽误了大半天时间,分享一下。

图片]
图片]
图片]
图片]
void EventDispatcher::visitTarget(Node* node, bool isRootNode)
{
    node->sortAllChildren();
    
    int i = 0;
    auto& children = node->getChildren();
    
    auto childrenCount = children.size();
    
    if(childrenCount > 0)
    {
        Node* child = nullptr;
        // visit children zOrder < 0
        for( ; i < childrenCount; i++ )
        {
            child = children.at(i);
            
            if ( child && child->getLocalZOrder() < 0 )
                visitTarget(child, false);
            else
                break;
        }
        
        if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
        {
            _globalZOrderNodeMap.push_back(node);
        }
        
        for( ; i < childrenCount; i++ )
        {
            child = children.at(i);
            if (child)
                visitTarget(child, false);
        }
    }
    else
    {
        if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
        {
            _globalZOrderNodeMap.push_back(node);
        }
    }
    
    if (isRootNode)
    {
        std::vector globalZOrders;
        globalZOrders.reserve(_globalZOrderNodeMap.size());
        
        for (const auto& e : _globalZOrderNodeMap)
        {
            globalZOrders.push_back(e.first);
        }
        
        std::sort(globalZOrders.begin(), globalZOrders.end(), ](const float a, const float b){
            return a < b;
        });
        
        for (const auto& globalZ : globalZOrders)
        {
            for (const auto& n : _globalZOrderNodeMap)
            {
                _nodePriorityMap = ++_nodePriorityIndex;
            }
        }
        
        _globalZOrderNodeMap.clear();
    }
}


```

更新了以下版本发现3.8版本之后已经改过来了。