cocos2d-x 源码分析 : EventDispatcher、EventListener、Event 源码分析 (新触摸机制,新的NotificationCenter机制)

来源:互联网 发布:java内存泄露场景 编辑:程序博客网 时间:2024/05/22 12:25

原文地址 http://blog.csdn.net/u011225840/article/details/34126789


1.继承结构

1.1 结构

      不详吐槽太多,也不贴图了,贴图要审核好久好久好久好久。
      从小到大,先来看下Event的结构。
      1.Event--------EventTouch,EventCustom,EventMouse,EventKeyboard,EventFocus,EventAcceleration
       其中,EventTouch 和 EventCustom是比较特殊的两个Event。EventTouch是3.x版本的触摸机制相关的Event,而EventCustom则是3.x自定义事件机制的基础,该机制取代了2.x版本中的NotificationCenter。

      2.EventListener-------------EventListenerTouchOneByOne,EventListenerTouchAllAtOnce,EventListenerCustom,EventListenerFocus,EventListenerMouse....对应
      相比于Event,Listener多了一个,因为对应的Touch被拆分成了两个Listener,一个是OneByone,一个是TouchAllAtOnce。前者是onTouchBegan等函数的Listener,后者是onTouchesBegan等函数的Listener。


1.2.EventDispatcher,EventListener,Event三者的关系

       Event相当于data,EventListener包含了data与fuction的一种映射关系,而EventDispatcher相当于一个Manager,管理着EventListener,决定着Event的调用顺序。
       Event中包含了type,target等信息;EventListener包含了ListenerID,相关联的Node,对应的callBack;EventDispatcher里含有各种map,vector来管理不同的Listener。具体的,可以看源码分析。

2.源码分析

        本次源码分析的量比较大,大家要有心理准备哟~

2.1Event相关

2.1.1 Event


[cpp] view plain copy
  1. enum class Type  
  2.    {  
  3.        TOUCH,  
  4.        KEYBOARD,  
  5.        ACCELERATION,  
  6.        MOUSE,  
  7.        FOCUS,  
  8.        CUSTOM  
  9.    };  
  10.    Type _type;     ///< Event type  
  11.      
  12.    bool _isStopped;       ///< whether the event has been stopped.  
  13.    Node* _currentTarget;  
      
      Event主要包含了三个重要的变量,type,是一个enum变量,里面定义了类型;isStopped定义该event是否已经停止,当一个event发生停止时,与其相关的Listener都要停止callback的调用;currentTarget是与该Event相关联的node。


2.1.2 EventTouch

    EventTouch是cocos2d-x引擎中非常非常重要的事件。对应于四种touch操作,该类内部定义了四种EventCode
    
[cpp] view plain copy
  1. enum class EventCode  
  2.    {  
  3.        BEGAN,  
  4.        MOVED,  
  5.        ENDED,  
  6.        CANCELLED  
  7.    };  

      不同的EventCode可以告诉Listener来调用不同的callback。

       除此之外,EventTouch中含有std::vector<Touch*> _touches 来记录该事件相关的touch,值得注意的是,本版本默认含有的触摸点最大是5个。

2.1.3 EventCustom


     EventCustom的出现取代了统治2.x版本多年的NotificationCenter,来看下EventCustom的两个重要成员变量。

[cpp] view plain copy
  1. void* _userData;       ///< User data  
  2. std::string _eventName;  

      有没有似曾相识的感觉,还是一样的key,还是一样的userData(有点不一样。原来是CCObject*)。


       其他的Event因为重要性以及使用度的原因,这里不再赘述,如果以后笔者对他们有新的认识,将会在这里进行添加。

2.2 EventListener相关

2.2.1 EventListener


     
[cpp] view plain copy
  1. std::function<void(Event*)> _onEvent;   /// Event callback function  
  2. Type _type;                             /// Event listener type  
  3. ListenerID _listenerID;                 /// Event listener ID  
  4. bool _isRegistered;                     /// Whether the listener has been added to dispatcher.  
  5.   
  6. int   _fixedPriority;   // The higher the number, the higher the priority, 0 is for scene graph base priority.  
  7. Node* _node;            // scene graph based priority  
  8. bool _paused;           // Whether the listener is paused  
  9. bool _isEnabled;        // Whether the listener is enabled  

       重要的成员变量:
      1.onEvent,是绑定于该Listener的callback function,该func的声明使用了c++11的新特性。
      2.type与Event类似,增加一个Unknown的属性。
      3.isRegistered变量非常重要,如果他没有被注册,则他的事件不会触发。
      4.优先级代表了响应一个事件时的顺序,该值越低,越先响应。
      5.node 代表了与该listener相关的node,用于 scene graph类的事件响应,具体的在Dispatcher里面有进行介绍。
      6.最后说下ListenerID,这是该类型事件的标识符。除了EventCustomListener的ListerID是与name相关的,其余的ListenerID都是固定的,用于标识该类EventListener。

     
[cpp] view plain copy
  1. /** Enables or disables the listener 
  2.     *  @note Only listeners with `enabled` state will be able to receive events. 
  3.     *        When an listener was initialized, it's enabled by default. 
  4.     *        An event listener can receive events when it is enabled and is not paused. 
  5.     *        paused state is always false when it is a fixed priority listener. 
  6.     */  
  7.    inline void setEnabled(bool enabled) { _isEnabled = enabled; };  
[cpp] view plain copy
  1. /** Sets paused state for the listener 
  2.      *  The paused state is only used for scene graph priority listeners. 
  3.      *  `EventDispatcher::resumeAllEventListenersForTarget(node)` will set the paused state to `true`, 
  4.      *  while `EventDispatcher::pauseAllEventListenersForTarget(node)` will set it to `false`. 
  5.      *  @note 1) Fixed priority listeners will never get paused. If a fixed priority doesn't want to receive events, 
  6.      *           call `setEnabled(false)` instead. 
  7.      *        2) In `Node`'s onEnter and onExit, the `paused state` of the listeners which associated with that node will be automatically updated. 
  8.      */  
  9.     inline void setPaused(bool paused) { _paused = paused; };  

      上面两段话,解释了什么时候一个Listener是可以接收事件,什么时候是不可以的。
       1.一个Listener想接收事件必须是enabled true 并且 paused false。
      2.值得注意的是,pause的变量专门是为了scenGraph类的事件存在的(后续有说明),而且一个Node的onEnter和onExit 事件会影响到与Node相关的该类事件的pause状态。

2.2.2 EventListenerOneByOne


     
[cpp] view plain copy
  1.     /// Overrides  
  2.     virtual EventListenerTouchOneByOne* clone() override;  
  3.     virtual bool checkAvailable() override;  
  4.     //  
  5.   
  6. public:  
  7.     std::function<bool(Touch*, Event*)> onTouchBegan;  
  8.     std::function<void(Touch*, Event*)> onTouchMoved;  
  9.     std::function<void(Touch*, Event*)> onTouchEnded;  
  10.     std::function<void(Touch*, Event*)> onTouchCancelled;  

        上面的是OneByOne重载父类的方法,以及自己本身需要被绑定4个callBack 函数。
        
        
[cpp] view plain copy
  1. EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()  
  2. {  
  3.     //深拷贝  
  4.     auto ret = new EventListenerTouchOneByOne();  
  5.     if (ret && ret->init())  
  6.     {  
  7.         ret->autorelease();  
  8.           
  9.         ret->onTouchBegan = onTouchBegan;  
  10.         ret->onTouchMoved = onTouchMoved;  
  11.         ret->onTouchEnded = onTouchEnded;  
  12.         ret->onTouchCancelled = onTouchCancelled;  
  13.           
  14.         ret->_claimedTouches = _claimedTouches;  
  15.         ret->_needSwallow = _needSwallow;  
  16.     }  
  17.     else  
  18.     {  
  19.         CC_SAFE_DELETE(ret);  
  20.     }  
  21.     return ret;  
  22. }  


[cpp] view plain copy
  1. bool EventListenerTouchOneByOne::checkAvailable()  
  2. {  
  3.     // EventDispatcher will use the return value of 'onTouchBegan' to determine whether to pass following 'move', 'end'  
  4.     // message to 'EventListenerTouchOneByOne' or not. So 'onTouchBegan' needs to be set.  
  5.     //OneByOne只需要onTouchBegan不为空,则可以认为其是可用的。  
  6.     if (onTouchBegan == nullptr)  
  7.     {  
  8.         CCASSERT(false"Invalid EventListenerTouchOneByOne!");  
  9.         return false;  
  10.     }  
  11.       
  12.     return true;  
  13. }  
       什么是可用性,当在dispatcher进行事件分发时,如果一个Listener是不可用的,则不会将该事件分发给他。

[cpp] view plain copy
  1. std::vector<Touch*> _claimedTouches;  
  2. bool _needSwallow;  

        OneByOne的touch是可以设置吞噬属性的。

2.2.3 EventListenerAllAtOnce

        
[cpp] view plain copy
  1. std::function<void(const std::vector<Touch*>&, Event*)> onTouchesBegan;  
  2. std::function<void(const std::vector<Touch*>&, Event*)> onTouchesMoved;  
  3. std::function<void(const std::vector<Touch*>&, Event*)> onTouchesEnded;  
  4. std::function<void(const std::vector<Touch*>&, Event*)> onTouchesCancelled;  

        AllAtOnce就是所谓的standard touch处理机制,一次性处理所有的touch。

       值得注意的是AllAtOnce的checkAvailable要求,上述四个函数指针都不能为空。

       
[cpp] view plain copy
  1. bool EventListenerTouchAllAtOnce::checkAvailable()  
  2. {  
  3.     if (onTouchesBegan == nullptr && onTouchesMoved == nullptr  
  4.         && onTouchesEnded == nullptr && onTouchesCancelled == nullptr)  
  5.     {  
  6.         CCASSERT(false"Invalid EventListenerTouchAllAtOnce!");  
  7.         return false;  
  8.     }  
  9.       
  10.     return true;  
  11. }  

2.3 EventListenerCustom


       同样的,EventListenerID是根据独特的Name进行命名的,值得注意的是请确保你的name是具有唯一性的,否在在DispatchCustomEvent时会有问题。


3. EventDispatcher

       从头到尾写了这么多,才开始进入主题,上面的东西都是为了看EventDispatcher源码的开胃菜!!!在介绍这个之前,我们必须要看一个内部类

3.1 EventListenerVector


      
[cpp] view plain copy
  1. class EventListenerVector  
  2.     {  
  3.     public:  
  4.         EventListenerVector();  
  5.         ~EventListenerVector();  
  6.         size_t size() const;  
  7.         bool empty() const;  
  8.           
  9.         void push_back(EventListener* item);  
  10.         void clearSceneGraphListeners();  
  11.         void clearFixedListeners();  
  12.         void clear();  
  13.           
  14.         inline std::vector<EventListener*>* getFixedPriorityListeners() const { return _fixedListeners; };  
  15.         inline std::vector<EventListener*>* getSceneGraphPriorityListeners() const { return _sceneGraphListeners; };  
  16.         inline ssize_t getGt0Index() const { return _gt0Index; };  
  17.         inline void setGt0Index(ssize_t index) { _gt0Index = index; };  
  18.     private:  
  19.         std::vector<EventListener*>* _fixedListeners;  
  20.         std::vector<EventListener*>* _sceneGraphListeners;  
  21.         ssize_t _gt0Index;  
  22.     };  

        首先我要说明的是两个非常非常重要的变量。fixedListeners和sceneGraphListeners,这是两个截然不同的Listener列表。
        1.sceneGraph类型的事件,是与当前正在运行的scene下node相关的事件,也就是说一个事件(比如说触摸事件),需要按照一定的响应序列,依次对这些Node进行事件响应,所以该类型的事件都会绑定一个与此相关联的node,并且响应顺序是与node在scene下的zorder相关的。该类型下的事件优先级统一为0.
        2.fixed类型的事件相对就比较简单了,但是有一个限制就是其优先级不能为0.

在EventDispatcher的成员变量中有一个map :std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;  一种ListenerID对应了一个Vector。

       
[cpp] view plain copy
  1. size_t EventDispatcher::EventListenerVector::size() const  
  2. {  
  3.     //vector内部的size大小是两个list的和  
  4.     size_t ret = 0;  
  5.     if (_sceneGraphListeners)  
  6.         ret += _sceneGraphListeners->size();  
  7.     if (_fixedListeners)  
  8.         ret += _fixedListeners->size();  
  9.       
  10.     return ret;  
  11. }  


[cpp] view plain copy
  1. void EventDispatcher::EventListenerVector::push_back(EventListener* listener)  
  2. {  
  3.     //查看listener的priority,如果为0,加入sceneGraphList,否则加入fixedList  
  4.     if (listener->getFixedPriority() == 0)  
  5.     {  
  6.         if (_sceneGraphListeners == nullptr)  
  7.         {  
  8.             _sceneGraphListeners = new std::vector<EventListener*>();  
  9.             _sceneGraphListeners->reserve(100);  
  10.         }  
  11.           
  12.         _sceneGraphListeners->push_back(listener);  
  13.     }  
  14.     else  
  15.     {  
  16.         if (_fixedListeners == nullptr)  
  17.         {  
  18.             _fixedListeners = new std::vector<EventListener*>();  
  19.             _fixedListeners->reserve(100);  
  20.         }  
  21.           
  22.         _fixedListeners->push_back(listener);  
  23.     }  
  24. }  

       上面两个函数是与一般Vector不一样的地方,需要注意的地方我已经标注了注释。


3.2 Add操作

       既然是一个类似于Manager的类,那就先从Add操作开始吧。

       三种事件的添加方式:

    3.2.1 sceneGraph类

  
[cpp] view plain copy
  1. void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)  
  2. {  
  3.     CCASSERT(listener && node, "Invalid parameters.");  
  4.     CCASSERT(!listener->isRegistered(), "The listener has been registered.");  
  5.       
  6.     //检查Listener可用性  
  7.     if (!listener->checkAvailable())  
  8.         return;  
  9.     //设置listener相关属性  
  10.     listener->setAssociatedNode(node);  
  11.     listener->setFixedPriority(0);  
  12.     listener->setRegistered(true);  
  13.       
  14.     addEventListener(listener);  
  15. }  

3.2.2 fixed类

     
[cpp] view plain copy
  1. void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)  
  2. {  
  3.     CCASSERT(listener, "Invalid parameters.");  
  4.     //一个事件只能被注册一次  
  5.     CCASSERT(!listener->isRegistered(), "The listener has been registered.");  
  6.     //Fixed类型的事件优先级不能是0  
  7.     CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");  
  8.       
  9.     //检查可用性  
  10.     if (!listener->checkAvailable())  
  11.         return;  
  12.       
  13.     //设置关联属性  
  14.     listener->setAssociatedNode(nullptr);  
  15.     listener->setFixedPriority(fixedPriority);  
  16.     listener->setRegistered(true);  
  17.     listener->setPaused(false);  
  18.   
  19.     addEventListener(listener);  
  20. }  

3.2.3 custom类

[cpp] view plain copy
  1. EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback)  
  2. {  
  3.     //custom类的事件添加是通过eventName 和 eventcallBack来进行添加的  
  4.     EventListenerCustom *listener = EventListenerCustom::create(eventName, callback);  
  5.       
  6.     //custom的事件优先级被默认为1  
  7.     addEventListenerWithFixedPriority(listener, 1);  
  8.       
  9.     return listener;  
  10. }  

   可以看出,添加函数最后都用到了一个函数addEventListener,下面对其进行剖析(这个函数又用到了其他函数,又,又,又。。。。。。)

3.2.4 addEventListener

[cpp] view plain copy
  1. void EventDispatcher::addEventListener(EventListener* listener)  
  2. {  
  3.     //如果当前Dispatcher正在进行事件Dispatch,则放到toAddList中。  
  4.     if (_inDispatch == 0)  
  5.     {  
  6.         forceAddEventListener(listener);  
  7.     }  
  8.     else  
  9.     {  
  10.         // std::vector  
  11.         _toAddedListeners.push_back(listener);  
  12.     }  
  13.   
  14.     listener->retain();  
  15. }  

3.2.5 forceAddEventListener


   
[cpp] view plain copy
  1. void EventDispatcher::forceAddEventListener(EventListener* listener)  
  2. {  
  3.     EventListenerVector* listeners = nullptr;  
  4.     EventListener::ListenerID listenerID = listener->getListenerID();  
  5.       
  6.     //找到该类eventlistener的vector,此处的vector是EventVector  
  7.     auto itr = _listenerMap.find(listenerID);  
  8.     //如果没有找到,则需要向map中添加一个pair  
  9.     if (itr == _listenerMap.end())  
  10.     {  
  11.           
  12.         listeners = new EventListenerVector();  
  13.         _listenerMap.insert(std::make_pair(listenerID, listeners));  
  14.     }  
  15.     else  
  16.     {  
  17.         listeners = itr->second;  
  18.     }  
  19.     //将该类别listenerpush_back进去(这个函数调用的是EventVector的pushback哦)  
  20.     listeners->push_back(listener);  
  21.       
  22.     //如果优先级是0,则设置为graph。  
  23.     if (listener->getFixedPriority() == 0)  
  24.     {  
  25.         //设置该listenerID的DirtyFlag  
  26.         //(setDirty函数可以这样理解,每个ListenerID都有特定的dirtyFlag,每次进行add操作后,都要更新该ID的flag)  
  27.         setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);  
  28.           
  29.         //如果是sceneGraph类的事件,则需要处理两个方面:  
  30.         //1.将node 与event 关联  
  31.         //2.如果该node是运行中的,则需要恢复其事件(因为默认的sceneGraph listener的状态时pause)  
  32.         //增加该listener与node的关联  
  33.         auto node = listener->getAssociatedNode();  
  34.         CCASSERT(node != nullptr, "Invalid scene graph priority!");  
  35.           
  36.         associateNodeAndEventListener(node, listener);  
  37.           
  38.         //恢复node的运行状态  
  39.         if (node->isRunning())  
  40.         {  
  41.             resumeEventListenersForTarget(node);  
  42.         }  
  43.     }  
  44.     else  
  45.     {  
  46.         setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);  
  47.     }  
  48. }  

3.2.6associateNodeAndEventListener

   
[cpp] view plain copy
  1. void EventDispatcher::associateNodeAndEventListener(Node* node, EventListener* listener)  
  2. {  
  3.     //将listener与node关联,先从map中找到与该node相关的listener vector  
  4.     std::vector<EventListener*>* listeners = nullptr;  
  5.     auto found = _nodeListenersMap.find(node);  
  6.     if (found != _nodeListenersMap.end())  
  7.     {  
  8.         listeners = found->second;  
  9.     }  
  10.     else  
  11.     {  
  12.         listeners = new std::vector<EventListener*>();  
  13.         _nodeListenersMap.insert(std::make_pair(node, listeners));  
  14.     }  
  15.     //vector内添加该listener,这里的vector 是std::vector  
  16.     listeners->push_back(listener);  
  17. }  

3.2.7  removeEventListenersForTarget


     
[cpp] view plain copy
  1. void EventDispatcher::resumeEventListenersForTarget(Node* target, bool recursive/* = false */)  
  2. {  
  3.     //恢复Node的运行状态  
  4.     auto listenerIter = _nodeListenersMap.find(target);  
  5.     if (listenerIter != _nodeListenersMap.end())  
  6.     {  
  7.         auto listeners = listenerIter->second;  
  8.         for (auto& l : *listeners)  
  9.         {  
  10.             l->setPaused(false);  
  11.         }  
  12.     }  
  13.     // toAdd List中也要进行恢复  
  14.     for (auto& listener : _toAddedListeners)  
  15.     {  
  16.         if (listener->getAssociatedNode() == target)  
  17.         {  
  18.             listener->setPaused(false);  
  19.         }  
  20.     }  
  21.     //将该Node 与 node的child 都放到dirtyNode中,来记录与event相关的node  
  22.     setDirtyForNode(target);  
  23.       
  24.     if (recursive)  
  25.     {  
  26.         const auto& children = target->getChildren();  
  27.         for (const auto& child : children)  
  28.         {  
  29.             resumeEventListenersForTarget(child, true);  
  30.         }  
  31.     }  
  32. }  

3.3 Remove

        看完了Add,当然要讲remove

    3.3.1 removeEventListener

     
[cpp] view plain copy
  1. void EventDispatcher::removeEventListener(EventListener* listener)  
  2. {  
  3.     //说在前面,移除一个事件的代价比较大,如果没有必要,请不要无故移除事件。  
  4.     //删除一个listener的步骤:  
  5.     if (listener == nullptr)  
  6.         return;  
  7.   
  8.     bool isFound = false;  
  9.       
  10.     //lambda函数,函数从std::vector<EventListener*>* listeners 中移除该listener  
  11.     auto removeListenerInVector = [&](std::vector<EventListener*>* listeners){  
  12.         if (listeners == nullptr)  
  13.             return;  
  14.         //遍历  
  15.         for (auto iter = listeners->begin(); iter != listeners->end(); ++iter)  
  16.         {  
  17.             auto l = *iter;  
  18.             if (l == listener)  
  19.             {  
  20.                 //找到后的处理方法,标记状态位,并处理关联Node  
  21.                 CC_SAFE_RETAIN(l);  
  22.                 l->setRegistered(false);  
  23.                 if (l->getAssociatedNode() != nullptr)  
  24.                 {  
  25.                     dissociateNodeAndEventListener(l->getAssociatedNode(), l);  
  26.                     l->setAssociatedNode(nullptr);  // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes.  
  27.                 }  
  28.                 //当前没有在分发事件 则直接从listeners中移除该listener(因为标记了状态未,如果此时在分发事件,则会等结束后再移除)  
  29.                 if (_inDispatch == 0)  
  30.                 {  
  31.                     listeners->erase(iter);  
  32.                     CC_SAFE_RELEASE(l);  
  33.                 }  
  34.                   
  35.                 isFound = true;  
  36.                 break;  
  37.             }  
  38.         }  
  39.     };  
  40.       
  41.     for (auto iter = _listenerMap.begin(); iter != _listenerMap.end();)  
  42.     {  
  43.         //从listenersmap 中遍历所有,拿出所有的vector  
  44.         auto listeners = iter->second;  
  45.         auto fixedPriorityListeners = listeners->getFixedPriorityListeners();  
  46.         auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();  
  47.   
  48.         //从graphList中寻找。找到后需要更新该listenerID的dirty flag。  
  49.         removeListenerInVector(sceneGraphPriorityListeners);  
  50.         if (isFound)  
  51.         {  
  52.             // fixed #4160: Dirty flag need to be updated after listeners were removed.  
  53.             setDirty(listener->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY);  
  54.         }  
  55.         //从fixedList中寻找  
  56.         else  
  57.         {  
  58.             removeListenerInVector(fixedPriorityListeners);  
  59.             if (isFound)  
  60.             {  
  61.                 setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY);  
  62.             }  
  63.         }  
  64.           
  65.   
  66.         //如果vector在删除后是空的,则需要移除该vector,并且将相应的listenerID从_priorityDirtyFlagMap中移除。  
  67.         if (iter->second->empty())  
  68.         {  
  69.             _priorityDirtyFlagMap.erase(listener->getListenerID());  
  70.             auto list = iter->second;  
  71.             iter = _listenerMap.erase(iter);  
  72.             CC_SAFE_DELETE(list);  
  73.         }  
  74.         else  
  75.         {  
  76.             ++iter;  
  77.         }  
  78.           
  79.         if (isFound)  
  80.             break;  
  81.     }  
  82.   
  83.     if (isFound)  
  84.     {  
  85.         CC_SAFE_RELEASE(listener);  
  86.     }  
  87.     //如果在上述过程中未找到,则从toAddList中寻找  
  88.     else  
  89.     {  
  90.         for(auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ++iter)  
  91.         {  
  92.             if (*iter == listener)  
  93.             {  
  94.                 listener->setRegistered(false);  
  95.                 listener->release();  
  96.                 _toAddedListeners.erase(iter);  
  97.                 break;  
  98.             }  
  99.         }  
  100.     }  
  101. }  

3.3.2  removeEventListenersForListenerID


 
[cpp] view plain copy
  1. void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID)  
  2. {  
  3.     auto listenerItemIter = _listenerMap.find(listenerID);  
  4.     if (listenerItemIter != _listenerMap.end())  
  5.     {  
  6.         auto listeners = listenerItemIter->second;  
  7.         auto fixedPriorityListeners = listeners->getFixedPriorityListeners();  
  8.         auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();  
  9.           
  10.         //啊哦 又是一个lambda函数,将std::vector<EventListener*>* listenerVector中的Listener全部移除  
  11.         auto removeAllListenersInVector = [&](std::vector<EventListener*>* listenerVector){  
  12.             if (listenerVector == nullptr)  
  13.                 return;  
  14.               
  15.             for (auto iter = listenerVector->begin(); iter != listenerVector->end();)  
  16.             {  
  17.                 //设置要删除的listener状态,清空与其相关的node信息  
  18.                 auto l = *iter;  
  19.                 l->setRegistered(false);  
  20.                 if (l->getAssociatedNode() != nullptr)  
  21.                 {  
  22.                     dissociateNodeAndEventListener(l->getAssociatedNode(), l);  
  23.                     l->setAssociatedNode(nullptr);  // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes.  
  24.                 }  
  25.                   
  26.                 if (_inDispatch == 0)  
  27.                 {  
  28.                     iter = listenerVector->erase(iter);  
  29.                     CC_SAFE_RELEASE(l);  
  30.                 }  
  31.                 else  
  32.                 {  
  33.                     ++iter;  
  34.                 }  
  35.             }  
  36.         };  
  37.           
  38.         //两种类型的事件哦  
  39.         removeAllListenersInVector(sceneGraphPriorityListeners);  
  40.         removeAllListenersInVector(fixedPriorityListeners);  
  41.           
  42.         // Remove the dirty flag according the 'listenerID'.  
  43.         // No need to check whether the dispatcher is dispatching event.  
  44.         _priorityDirtyFlagMap.erase(listenerID);  
  45.           
  46.         if (!_inDispatch)  
  47.         {  
  48.             listeners->clear();  
  49.             delete listeners;  
  50.             _listenerMap.erase(listenerItemIter);  
  51.         }  
  52.     }  
  53.       
  54.     //toAddList 的清理,真可怜,还没来得及进入家门就要被扫地出门了么。。。。  
  55.     for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end();)  
  56.     {  
  57.         if ((*iter)->getListenerID() == listenerID)  
  58.         {  
  59.             (*iter)->setRegistered(false);  
  60.             (*iter)->release();  
  61.             iter = _toAddedListeners.erase(iter);  
  62.         }  
  63.         else  
  64.         {  
  65.             ++iter;  
  66.         }  
  67.     }  
  68. }  

     与其相关的两个remove函数

    
[cpp] view plain copy
  1. void EventDispatcher::removeEventListenersForType(EventListener::Type listenerType)  
  2. {  
  3.     if (listenerType == EventListener::Type::TOUCH_ONE_BY_ONE)  
  4.     {  
  5.         removeEventListenersForListenerID(EventListenerTouchOneByOne::LISTENER_ID);  
  6.     }  
  7.     else if (listenerType == EventListener::Type::TOUCH_ALL_AT_ONCE)  
  8.     {  
  9.         removeEventListenersForListenerID(EventListenerTouchAllAtOnce::LISTENER_ID);  
  10.     }  
  11.     else if (listenerType == EventListener::Type::MOUSE)  
  12.     {  
  13.         removeEventListenersForListenerID(EventListenerMouse::LISTENER_ID);  
  14.     }  
  15.     else if (listenerType == EventListener::Type::ACCELERATION)  
  16.     {  
  17.         removeEventListenersForListenerID(EventListenerAcceleration::LISTENER_ID);  
  18.     }  
  19.     else if (listenerType == EventListener::Type::KEYBOARD)  
  20.     {  
  21.         removeEventListenersForListenerID(EventListenerKeyboard::LISTENER_ID);  
  22.     }  
  23.     else  
  24.     {  
  25.         CCASSERT(false"Invalid listener type!");  
  26.     }  
  27. }  

   
[cpp] view plain copy
  1. void EventDispatcher::removeCustomEventListeners(const std::string& customEventName)  
  2. {  
  3.     removeEventListenersForListenerID(customEventName);  
  4. }  

3.3.3 removeAllEventListeners

  
[cpp] view plain copy
  1. void EventDispatcher::removeAllEventListeners()  
  2. {  
  3.     bool cleanMap = true;  
  4.     std::vector<EventListener::ListenerID> types(_listenerMap.size());  
  5.       
  6.     for (const auto& e : _listenerMap)  
  7.     {  
  8.         if (_internalCustomListenerIDs.find(e.first) != _internalCustomListenerIDs.end())  
  9.         {  
  10.             cleanMap = false;  
  11.         }  
  12.         else  
  13.         {  
  14.             types.push_back(e.first);  
  15.         }  
  16.     }  
  17.   
  18.     for (const auto& type : types)  
  19.     {  
  20.         removeEventListenersForListenerID(type);  
  21.     }  
  22.       
  23.     if (!_inDispatch && cleanMap)  
  24.     {  
  25.         _listenerMap.clear();  
  26.     }  
  27. }  


3.4 DispatchEvent(核心内容)

     终于到了核心内容了,为啥我要把核心内容放到后面。如果不看上面,不了解Event,EventListener,EventVector以及Dispatcher是如何管理EventListener的,看下面的代码就会有很多的疑惑。ok,让我们静静欣赏源码吧。

    3.4.1 dispatchEvent

    
[cpp] view plain copy
  1. void EventDispatcher::dispatchEvent(Event* event)  
  2. {  
  3.     if (!_isEnabled)  
  4.         return;  
  5.       
  6.     //为dirtyNodesVector中的dirtyNode更新Scene Flag。  
  7.     updateDirtyFlagForSceneGraph();  
  8.       
  9.       
  10.     DispatchGuard guard(_inDispatch);  
  11.       
  12.     //特殊touch事件,转到特殊的touch事件处理  
  13.     if (event->getType() == Event::Type::TOUCH)  
  14.     {  
  15.         dispatchTouchEvent(static_cast<EventTouch*>(event));  
  16.         return;  
  17.     }  
  18.       
  19.     //根据事件的类型,获取事件的ID  
  20.     auto listenerID = __getListenerID(event);  
  21.       
  22.     //根据事件ID,将该类事件进行排序(先响应谁)  
  23.     sortEventListeners(listenerID);  
  24.       
  25.     auto iter = _listenerMap.find(listenerID);  
  26.     if (iter != _listenerMap.end())  
  27.     {  
  28.         auto listeners = iter->second;  
  29.         //该类事件的lambda函数  
  30.         auto onEvent = [&event](EventListener* listener) -> bool{  
  31.             //设置event的target  
  32.             event->setCurrentTarget(listener->getAssociatedNode());  
  33.             //调用响应函数  
  34.             listener->_onEvent(event);  
  35.             //返回是否已经停止  
  36.             return event->isStopped();  
  37.         };  
  38.           
  39.         //将该类事件的listeners 和 该类事件的 lambda函数传给该函数  
  40.         dispatchEventToListeners(listeners, onEvent);  
  41.     }  
  42.       
  43.     //更新该事件相关的listener  
  44.     updateListeners(event);  
  45. }  

    我们可以看出,特殊的touchEvent和普通的event走的不是同一条控制流程,既然如此,我们就先一般后特殊吧,先来看看一般流程下的DispatchEventToListeners吧

3.4.2 dispatchEventToListeners


  
[cpp] view plain copy
  1. void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)  
  2. {  
  3.     bool shouldStopPropagation = false;  
  4.     auto fixedPriorityListeners = listeners->getFixedPriorityListeners();  
  5.     auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();  
  6.       
  7.     //整体操作流程分为三个部分,处理优先级<0,=0,>0三个部分  
  8.     ssize_t i = 0;  
  9.     // priority < 0  
  10.     if (fixedPriorityListeners)  
  11.     {  
  12.         CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");  
  13.           
  14.         if (!fixedPriorityListeners->empty())  
  15.         {  
  16.             for (; i < listeners->getGt0Index(); ++i)  
  17.             {  
  18.                 auto l = fixedPriorityListeners->at(i);  
  19.                 // onEvent(l)的操作调用了event的callBack,并且会返回是否停止,如果停止后,则将shouldStopPropagation标记为true  
  20.                 //在其后面的listeners则不会响应到该事件(这里可以看出触摸事件是如何被吞噬的)  
  21.                 if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))  
  22.                 {  
  23.                     shouldStopPropagation = true;  
  24.                     break;  
  25.                 }  
  26.             }  
  27.         }  
  28.     }  
  29.       
  30.     if (sceneGraphPriorityListeners)  
  31.     {  
  32.         if (!shouldStopPropagation)  
  33.         {  
  34.             // priority == 0, scene graph priority  
  35.             for (auto& l : *sceneGraphPriorityListeners)  
  36.             {  
  37.                 if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))  
  38.                 {  
  39.                     shouldStopPropagation = true;  
  40.                     break;  
  41.                 }  
  42.             }  
  43.         }  
  44.     }  
  45.   
  46.     if (fixedPriorityListeners)  
  47.     {  
  48.         if (!shouldStopPropagation)  
  49.         {  
  50.             // priority > 0  
  51.             ssize_t size = fixedPriorityListeners->size();  
  52.             for (; i < size; ++i)  
  53.             {  
  54.                 auto l = fixedPriorityListeners->at(i);  
  55.                   
  56.                 if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))  
  57.                 {  
  58.                     shouldStopPropagation = true;  
  59.                     break;  
  60.                 }  
  61.             }  
  62.         }  
  63.     }  
  64. }  

3.4.3 dispatchTouchEvent(3.x版本的触摸机制)

       
[cpp] view plain copy
  1. void EventDispatcher::dispatchTouchEvent(EventTouch* event)  
  2. {  
  3.     //先将EventListeners排序  
  4.     sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID);  
  5.     sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID);  
  6.       
  7.     auto oneByOneListeners = getListeners(EventListenerTouchOneByOne::LISTENER_ID);  
  8.     auto allAtOnceListeners = getListeners(EventListenerTouchAllAtOnce::LISTENER_ID);  
  9.       
  10.     // If there aren't any touch listeners, return directly.  
  11.     if (nullptr == oneByOneListeners && nullptr == allAtOnceListeners)  
  12.         return;  
  13.       
  14.     //mutableTouches是用来处理allAtOnce的  
  15.     bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners);  
  16.       
  17.     //这些touch都来自该事件  
  18.     const std::vector<Touch*>& originalTouches = event->getTouches();  
  19.     std::vector<Touch*> mutableTouches(originalTouches.size());  
  20.     std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin());  
  21.   
  22.     //  
  23.     // process the target handlers 1st  
  24.     //  
  25.     if (oneByOneListeners)  
  26.     {  
  27.         auto mutableTouchesIter = mutableTouches.begin();  
  28.         auto touchesIter = originalTouches.begin();  
  29.         //遍历touches,每一个touch都来自于同一个事件  
  30.         for (; touchesIter != originalTouches.end(); ++touchesIter)  
  31.         {  
  32.             bool isSwallowed = false;  
  33.   
  34.             //事件处理的lambda函数  
  35.             auto onTouchEvent = [&](EventListener* l) -> bool { // Return true to break  
  36.                 EventListenerTouchOneByOne* listener = static_cast<EventListenerTouchOneByOne*>(l);  
  37.                   
  38.                 // Skip if the listener was removed.  
  39.                 if (!listener->_isRegistered)  
  40.                     return false;  
  41.                
  42.                 event->setCurrentTarget(listener->_node);  
  43.                 //claimed代表该listener是否接收了该touch(Began返回true or false)  
  44.                 bool isClaimed = false;  
  45.                 std::vector<Touch*>::iterator removedIter;  
  46.                   
  47.                 //根据eventNode的不同,会调用不同的callBack函数  
  48.                 EventTouch::EventCode eventCode = event->getEventCode();  
  49.                   
  50.                 if (eventCode == EventTouch::EventCode::BEGAN)  
  51.                 {  
  52.                     //调用began  
  53.                     if (listener->onTouchBegan)  
  54.                     {  
  55.                         isClaimed = listener->onTouchBegan(*touchesIter, event);  
  56.                         if (isClaimed && listener->_isRegistered)  
  57.                         {  
  58.                             //返回true后 将该touch放入该listener的claimedTouches  
  59.                             listener->_claimedTouches.push_back(*touchesIter);  
  60.                         }  
  61.                     }  
  62.                 }  
  63.                 //如果是后三个move end cancel  
  64.                 else if (listener->_claimedTouches.size() > 0  
  65.                          && ((removedIter = std::find(listener->_claimedTouches.begin(), listener->_claimedTouches.end(), *touchesIter)) != listener->_claimedTouches.end()))  
  66.                 {  
  67.                     isClaimed = true;  
  68.                     //调用相应的callBack  
  69.                     switch (eventCode)  
  70.                     {  
  71.                         case EventTouch::EventCode::MOVED:  
  72.                             if (listener->onTouchMoved)  
  73.                             {  
  74.                                 listener->onTouchMoved(*touchesIter, event);  
  75.                             }  
  76.                             break;  
  77.                         case EventTouch::EventCode::ENDED:  
  78.                             if (listener->onTouchEnded)  
  79.                             {  
  80.                                 listener->onTouchEnded(*touchesIter, event);  
  81.                             }  
  82.                             if (listener->_isRegistered)  
  83.                             {  
  84.                                 listener->_claimedTouches.erase(removedIter);  
  85.                             }  
  86.                             break;  
  87.                         case EventTouch::EventCode::CANCELLED:  
  88.                             if (listener->onTouchCancelled)  
  89.                             {  
  90.                                 listener->onTouchCancelled(*touchesIter, event);  
  91.                             }  
  92.                             if (listener->_isRegistered)  
  93.                             {  
  94.                                 listener->_claimedTouches.erase(removedIter);  
  95.                             }  
  96.                             break;  
  97.                         default:  
  98.                             CCASSERT(false"The eventcode is invalid.");  
  99.                             break;  
  100.                     }  
  101.                 }  
  102.                   
  103.                 // If the event was stopped, return directly.  
  104.                 if (event->isStopped())  
  105.                 {  
  106.                     updateListeners(event);  
  107.                     return true;  
  108.                 }  
  109.                   
  110.                 CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(), "");  
  111.                   
  112.                 //如果接收该touch并且需要吞噬该touch,会有两个影响  
  113.                 //1.Touches(standard 触摸机制)的触摸操作都接收不到该touch了  
  114.                 //2.因为返回值是true,在调用dispatchEventToListeners时,在该node之后的node将会不再接收该touch  
  115.                 if (isClaimed && listener->_isRegistered && listener->_needSwallow)  
  116.                 {  
  117.                     if (isNeedsMutableSet)  
  118.                     {  
  119.                         mutableTouchesIter = mutableTouches.erase(mutableTouchesIter);  
  120.                         isSwallowed = true;  
  121.                     }  
  122.                     return true;  
  123.                 }  
  124.                   
  125.                 return false;  
  126.             };  
  127.               
  128.             //结合上面的dispatchEventToListeners的源码分析,可以看出新版本的OneByOne touch机制是这样的:  
  129.             //1.listener根据Node的优先级排序后,依次响应。值得注意的是,新版本的优先级是根据Node的global Zorder来的,而不是2.x的触摸优先级。  
  130.             //2.当TouchEvent Began来了之后,所有的listener会依次影响Touch Began。然后再依次响应Touch Move...而不是一个listener响应完  
  131.             //began move end之后 轮到下一个listener响应的顺序。  
  132.             //3.吞噬操作只有发生在began return true后才可以发生  
  133.             dispatchEventToListeners(oneByOneListeners, onTouchEvent);  
  134.             if (event->isStopped())  
  135.             {  
  136.                 return;  
  137.             }  
  138.               
  139.             if (!isSwallowed)  
  140.                 ++mutableTouchesIter;  
  141.         }  
  142.     }  
  143.       
  144.     //  
  145.     // process standard handlers 2nd  
  146.     //  
  147.     //相比于OneByOne,AllAtOnce要简单许多。值得注意的是被吞噬的touch也不会被AllAtOnce响应到  
  148.     if (allAtOnceListeners && mutableTouches.size() > 0)  
  149.     {  
  150.           
  151.         auto onTouchesEvent = [&](EventListener* l) -> bool{  
  152.             EventListenerTouchAllAtOnce* listener = static_cast<EventListenerTouchAllAtOnce*>(l);  
  153.             // Skip if the listener was removed.  
  154.             if (!listener->_isRegistered)  
  155.                 return false;  
  156.               
  157.             event->setCurrentTarget(listener->_node);  
  158.               
  159.             switch (event->getEventCode())  
  160.             {  
  161.                 case EventTouch::EventCode::BEGAN:  
  162.                     if (listener->onTouchesBegan)  
  163.                     {  
  164.                         listener->onTouchesBegan(mutableTouches, event);  
  165.                     }  
  166.                     break;  
  167.                 case EventTouch::EventCode::MOVED:  
  168.                     if (listener->onTouchesMoved)  
  169.                     {  
  170.                         listener->onTouchesMoved(mutableTouches, event);  
  171.                     }  
  172.                     break;  
  173.                 case EventTouch::EventCode::ENDED:  
  174.                     if (listener->onTouchesEnded)  
  175.                     {  
  176.                         listener->onTouchesEnded(mutableTouches, event);  
  177.                     }  
  178.                     break;  
  179.                 case EventTouch::EventCode::CANCELLED:  
  180.                     if (listener->onTouchesCancelled)  
  181.                     {  
  182.                         listener->onTouchesCancelled(mutableTouches, event);  
  183.                     }  
  184.                     break;  
  185.                 default:  
  186.                     CCASSERT(false"The eventcode is invalid.");  
  187.                     break;  
  188.             }  
  189.               
  190.             // If the event was stopped, return directly.  
  191.             if (event->isStopped())  
  192.             {  
  193.                 updateListeners(event);  
  194.                 return true;  
  195.             }  
  196.               
  197.             return false;  
  198.         };  
  199.           
  200.         dispatchEventToListeners(allAtOnceListeners, onTouchesEvent);  
  201.         if (event->isStopped())  
  202.         {  
  203.             return;  
  204.         }  
  205.     }  
  206.       
  207.     updateListeners(event);  
  208. }  

      很多需要注意的地方我全给了中文标识,但是这里我还要再次说明下新版本的touch OneByOne机制:
      1.listener根据Node的优先级排序后,依次响应。值得注意的是,新版本的优先级是根据Node的global Zorder来的,而不是2.x的触摸优先级。
       2.当TouchEvent Began来了之后,所有的listener会依次影响Touch Began。然后再依次响应Touch Move...而不是一个listener响应完  began move end之后 轮到下一个listener响应的顺序。
        3.吞噬操作只有发生在began return true后才可以发生

3.4.4 DispatchCustomEvent (新版本的NotificationCenter机制)

    
[cpp] view plain copy
  1. void EventDispatcher::dispatchCustomEvent(const std::string &eventName, void *optionalUserData)  
  2. {  
  3.     EventCustom ev(eventName);  
  4.     ev.setUserData(optionalUserData);  
  5.     dispatchEvent(&ev);  
  6. }  

好简单,这个函数像不像 postNotification(......)?,在3.x的事件中,再也不要使用NotificationCenter了哦~

4.小结

      Event,EventListener,EventDispatcher的关系
      新的触摸机制
      新的NotificationCenter方法
阅读全文
0 0
原创粉丝点击