cocos2dx源码分析:事件派发器EventDispatcher

事件派发器在事件监听器和事件源之间起了一个协调者的作用,所有的事件监听器都注册到事件派发器中,事件源通过向事件派发器派发事件触发监听器的回调函数
事件监听器必须注册到EventDispatcher中才能监听到对应的事件,有两种方式注册

    /*按场景优先级,也就是zorder*/
    void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
    /*固定优先级*/
    void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);

事件源有事件发生时,调用dispatchEvent派发事件

注册事件监听器

void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
{
    CCASSERT(listener && node, "Invalid parameters.");
    CCASSERT(!listener->isRegistered(), "The listener has been registered.");

    if (!listener->checkAvailable())
        return;

    listener->setAssociatedNode(node);
    /*0表示SceneGraphPriority*/
    listener->setFixedPriority(0);
    listener->setRegistered(true);

    addEventListener(listener);
}
void EventDispatcher::addEventListener(EventListener* listener)
{
    if (_inDispatch == 0)
    {
        /*不在事件派发中,直接添加*/
        forceAddEventListener(listener);
    }
    else
    {
        /*正在派发事件时不能添加事件监听器,先放到临时队列中,等派发事件结束,再添加这些事件监听器*/
        _toAddedListeners.push_back(listener);
    }
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
    auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
    if (sEngine)
    {
        sEngine->retainScriptObject(this, listener);
    }
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
    listener->retain();
}

void EventDispatcher::forceAddEventListener(EventListener* listener)
{
    EventListenerVector* listeners = nullptr;
    /*listenerID与事件类型有关,同一类事件有一个唯一listenerID*/
    EventListener::ListenerID listenerID = listener->getListenerID();
    /*事件时按类型分组的,这里找到listener所属的组,如果没有则创建一个*/
    auto itr = _listenerMap.find(listenerID);
    if (itr == _listenerMap.end())
    {

        listeners = new (std::nothrow) EventListenerVector();
        _listenerMap.insert(std::make_pair(listenerID, listeners));
    }
    else
    {
        listeners = itr->second;
    }

    listeners->push_back(listener);
    /*如果listener->getFixedPriority()是0则表示SceneGraphPriority*/
    if (listener->getFixedPriority() == 0)
    {
        setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);

        auto node = listener->getAssociatedNode();
        CCASSERT(node != nullptr, "Invalid scene graph priority!");
        /*关联node和listener*/
        associateNodeAndEventListener(node, listener);

        if (node->isRunning())
        {
            resumeEventListenersForTarget(node);
        }
    }
    else
    {
        setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
    }
}

触发事件

void EventDispatcher::dispatchEvent(Event* event)
{
    if (!_isEnabled)
        return;

    updateDirtyFlagForSceneGraph();

    /*保护,在派发事件时,不要继续添加或删除事件监听器*/
    DispatchGuard guard(_inDispatch);

    if (event->getType() == Event::Type::TOUCH)
    {
        /*touch事件的派发*/
        dispatchTouchEvent(static_cast<EventTouch*>(event));
        return;
    }
    /*获取事件所属的事件监听器组*/
    auto listenerID = __getListenerID(event);
    /*因为有优先级的关系,对事件监听器重排序*/
    sortEventListeners(listenerID);
    /*派发事件*/
    auto pfnDispatchEventToListeners = &EventDispatcher::dispatchEventToListeners;
    if (event->getType() == Event::Type::MOUSE) {
        pfnDispatchEventToListeners = &EventDispatcher::dispatchTouchEventToListeners;
    }
    auto iter = _listenerMap.find(listenerID);
    if (iter != _listenerMap.end())
    {
        auto listeners = iter->second;

        auto onEvent = [&event](EventListener* listener) -> bool{
            event->setCurrentTarget(listener->getAssociatedNode());
            listener->_onEvent(event);
            return event->isStopped();
        };

        (this->*pfnDispatchEventToListeners)(listeners, onEvent);
    }

    updateListeners(event);
}

你可能感兴趣的:(cocos2d-x)