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

源码版本来自3.x,转载请注明

cocos2d-x 源码分析总目录

http://blog.csdn.net/u011225840/article/details/31743129


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


 enum class Type
    {
        TOUCH,
        KEYBOARD,
        ACCELERATION,
        MOUSE,
        FOCUS,
        CUSTOM
    };
    Type _type;     ///< Event type
    
    bool _isStopped;       ///< whether the event has been stopped.
    Node* _currentTarget;
      
      Event主要包含了三个重要的变量,type,是一个enum变量,里面定义了类型;isStopped定义该event是否已经停止,当一个event发生停止时,与其相关的Listener都要停止callback的调用;currentTarget是与该Event相关联的node。


2.1.2 EventTouch

    EventTouch是cocos2d-x引擎中非常非常重要的事件。对应于四种touch操作,该类内部定义了四种EventCode
    
 enum class EventCode
    {
        BEGAN,
        MOVED,
        ENDED,
        CANCELLED
    };

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

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

2.1.3 EventCustom


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

    void* _userData;       ///< User data
    std::string _eventName;

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


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

2.2 EventListener相关

2.2.1 EventListener


     
    std::function<void(Event*)> _onEvent;   /// Event callback function
    Type _type;                             /// Event listener type
    ListenerID _listenerID;                 /// Event listener ID
    bool _isRegistered;                     /// Whether the listener has been added to dispatcher.

    int   _fixedPriority;   // The higher the number, the higher the priority, 0 is for scene graph base priority.
    Node* _node;            // scene graph based priority
    bool _paused;           // Whether the listener is paused
    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。

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


     
    /// Overrides
    virtual EventListenerTouchOneByOne* clone() override;
    virtual bool checkAvailable() override;
    //

public:
    std::function<bool(Touch*, Event*)> onTouchBegan;
    std::function<void(Touch*, Event*)> onTouchMoved;
    std::function<void(Touch*, Event*)> onTouchEnded;
    std::function<void(Touch*, Event*)> onTouchCancelled;

        上面的是OneByOne重载父类的方法,以及自己本身需要被绑定4个callBack 函数。
        
        
EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
{
	//深拷贝
    auto ret = new EventListenerTouchOneByOne();
    if (ret && ret->init())
    {
        ret->autorelease();
        
        ret->onTouchBegan = onTouchBegan;
        ret->onTouchMoved = onTouchMoved;
        ret->onTouchEnded = onTouchEnded;
        ret->onTouchCancelled = onTouchCancelled;
        
        ret->_claimedTouches = _claimedTouches;
        ret->_needSwallow = _needSwallow;
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}


bool EventListenerTouchOneByOne::checkAvailable()
{
    // EventDispatcher will use the return value of 'onTouchBegan' to determine whether to pass following 'move', 'end'
    // message to 'EventListenerTouchOneByOne' or not. So 'onTouchBegan' needs to be set.
	//OneByOne只需要onTouchBegan不为空,则可以认为其是可用的。
    if (onTouchBegan == nullptr)
    {
        CCASSERT(false, "Invalid EventListenerTouchOneByOne!");
        return false;
    }
    
    return true;
}
       什么是可用性,当在dispatcher进行事件分发时,如果一个Listener是不可用的,则不会将该事件分
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值