`
Rudolph
  • 浏览: 66562 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

cocos2d-x 3.0 触摸响应优先级的问题

阅读更多

按照相关资料说法:设置的数值越小,触摸优先级越高,同等优先级,优先响应后添加的

事实从源代码来看:同等优先级时会响应第一个添加的。

 

例如在3.0以前的版本中CCMenu就存在这样的情况,将子节点集合正序遍历改成反序遍历即可修正。

 

3.0之后触摸模块有改动,统一通过EventDispatcher控制,当然,依然是优先响应先添加的控件,在对集合遍历时时正序遍历,而此时集合为升序排序从小到大 0<,>0,设置的数值越小,触摸优先级越高在这里体现了

源代码如下:

void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
{
    bool shouldStopPropagation = false;
    auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
    auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
    
    ssize_t i = 0;
    // priority < 0
    if (fixedPriorityListeners)
    {
        CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
        
        if (!fixedPriorityListeners->empty())
        {
            for (; i < listeners->getGt0Index(); ++i)
            {
                auto l = fixedPriorityListeners->at(i);
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }
    
    //省略..
}

 

升序排序代码如下:

void EventDispatcher::sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID)
{
    auto listeners = getListeners(listenerID);

    if (listeners == nullptr)
        return;
    
    auto fixedListeners = listeners->getFixedPriorityListeners();
    if (fixedListeners == nullptr)
        return;
    
    // After sort: priority < 0, > 0
    std::sort(fixedListeners->begin(), fixedListeners->end(), [](const EventListener* l1, const EventListener* l2) {
        return l1->getFixedPriority() < l2->getFixedPriority();
    });
    
    // FIXME: Should use binary search
    int index = 0;
    for (auto& listener : *fixedListeners)
    {
        if (listener->getFixedPriority() >= 0)
            break;
        ++index;
    }
    
    listeners->setGt0Index(index);
    
#if DUMP_LISTENER_ITEM_PRIORITY_INFO
    log("-----------------------------------");
    for (auto& l : *fixedListeners)
    {
        log("listener priority: node (%p), fixed (%d)", l->_node, l->_fixedPriority);
    }    
#endif
    
}

 

到这里,再看同等优先级的问题,在注册添加回调的时候是这样的:

 

void EventDispatcher::forceAddEventListener(EventListener* listener)
{
    EventListenerVector* listeners = nullptr;
    EventListener::ListenerID listenerID = listener->getListenerID();
    auto itr = _listenerMap.find(listenerID);
    if (itr == _listenerMap.end())
    {
        
        listeners = new EventListenerVector();
        _listenerMap.insert(std::make_pair(listenerID, listeners));
    }
    else
    {
        listeners = itr->second;
    }
    
    listeners->push_back(listener);//添加到容器尾部
    
    if (listener->getFixedPriority() == 0)
    {
        setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);
        
        auto node = listener->getAssociatedNode();
        CCASSERT(node != nullptr, "Invalid scene graph priority!");
        
        associateNodeAndEventListener(node, listener);
        
        if (node->isRunning())
        {
            resumeEventListenersForTarget(node);
        }
    }
    else
    {
        setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
    }
}
 所以回到上面,对容器做排序,同等优先级是不会交换位置的,所以先添加的还是在前面。然后到派遣事件时,还是先派遣到先添加的。所以现在可以证明同等优先级时会响应第一个添加的

 

 

那么要改成同等优先级,优先响应后添加可以这样,在将监听添加进容器时插入:

 

void EventDispatcher::EventListenerVector::push_back(EventListener* listener)
{
#if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS
    CCASSERT(_sceneGraphListeners == nullptr ||
             std::count(_sceneGraphListeners->begin(), _sceneGraphListeners->end(), listener) == 0,
             "Listener should not be added twice!");
        
    CCASSERT(_fixedListeners == nullptr ||
             std::count(_fixedListeners->begin(), _fixedListeners->end(), listener) == 0,
             "Listener should not be added twice!");
#endif

    if (listener->getFixedPriority() == 0)
    {
        if (_sceneGraphListeners == nullptr)
        {
            _sceneGraphListeners = new std::vector<EventListener*>();
            _sceneGraphListeners->reserve(100);
        }
        
        //_sceneGraphListeners->push_back(listener);
		
		auto it = _sceneGraphListeners->begin();
		for (; it != _sceneGraphListeners->end(); it++)
		{
			if ((*it)->getFixedPriority() == listener->getFixedPriority())
				break;
		}
		_sceneGraphListeners->insert(it, listener);
    }
    else
    {
        if (_fixedListeners == nullptr)
        {
            _fixedListeners = new std::vector<EventListener*>();
            _fixedListeners->reserve(100);
        }
        
        //_fixedListeners->push_back(listener);
		auto it = _fixedListeners->begin();
		for (; it != _fixedListeners->end(); it++)
		{
			if ((*it)->getFixedPriority() == listener->getFixedPriority())
				break;
		}
		_fixedListeners->insert(it, listener);
    }
}

 

这样之后,就达到了同等优先级,优先响应后添加的

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics