zhishu520 / blog

一个关于游戏开发的博客(*^__^*)
3 stars 0 forks source link

cocos2dx 事件分发机制 #5

Open zhishu520 opened 5 years ago

zhishu520 commented 5 years ago

cocos2dx 的事件机制由 事件(Event) 事件监听器(EventListener) 和 事件分发器(EventDispatcher)这三部分组成。

Event的创建,添加EventListener到EventDispatcher就不说了。就看下重要的分发代码。

分发事件代码

主要有四个点

  1. 更新是否需要重新排序的 DirtyFlag
  2. 重新排序
  3. 遍历监听器,找到对应的,并执行。
  4. 更新监听器

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

    //  更新 DirtyFlag 判断是否需要重新排序。
    updateDirtyFlagForSceneGraph();

    // 守护者,防止在分发过程中加入新的listener
    // 因为分发过程中添加或者删除,都会导致迭代器失效,所以需要一个这样的东西。
    // 来判断是否正在分发过程中
    DispatchGuard guard(_inDispatch);

    auto listenerID = __getListenerID(event);

    // 排序,分两种
    // 1. 按优先级 <0 =0 >0的顺序排序
    // 2. 优先级为0时候,一般是屏幕触摸事件,根据监听器绑定的节点的渲染顺序排序。
    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);
}
···