4.【cocos2d-x 源码分析】:EventDispatcher类的详细分析

本文详细分析了cocos2d-x中的EventDispatcher类,从Event基类开始,逐步讲解了EventCustom、EventMouse、EventTouch子类,以及EventListener的各个子类如EventListenerCustom、EventListenerMouse、EventListenerTouchOneByOne和EventListenerTouchAllAtOnce。重点阐述了EventDispatcher如何组织并处理注册的监听器,当事件发生时如何调用相应回调。此外,还特别讨论了触摸事件的处理逻辑和updateListeners方法。
摘要由CSDN通过智能技术生成
对应源码位置:(1)cocos2d-x-3.3\cocos\base\CCEvent*
先从 Event 类开头
class CC_DLL Event : public Ref
{
   
public:
	//可想而知 对应这几个类型  分别有对应的Event子类 
	//以及 对应事件的 eventlistener
    enum class Type
    {
   
        TOUCH,
        KEYBOARD,
        ACCELERATION,
        MOUSE,
        FOCUS,
        GAME_CONTROLLER,
        CUSTOM
    };
    /** Constructor */
    Event(Type type);
public:
    /** Destructor */
    virtual ~Event();

    /** Gets the event type */
	inline Type getType() const {
    return _type; };
    
    /** Stops propagation for current event */
    inline void stopPropagation() {
    _isStopped = true; };
    
    /** Checks whether the event has been stopped */
    inline bool isStopped() const {
    return _isStopped; };
    inline Node* getCurrentTarget() {
    return _currentTarget; };
    
protected:
    /** Sets current target */
    inline void setCurrentTarget(Node* target) {
    _currentTarget = target; };
    //事件类型
	Type _type;     ///< Event type
    //是否阻止传播  也就是所谓的 swallow 是否吞下这个事件
    bool _isStopped;       ///< whether the event has been stopped.
    Node* _currentTarget;  ///< Current target
    
    friend class EventDispatcher;
};

再来看看 EventCustom 这个子类,也就是所谓自定义事件

class CC_DLL EventCustom : public Event
{
   
public:
    /** Constructor */
    EventCustom(const std::string& eventName);
    
    /** Sets user data */
    inline void setUserData(void* data) {
    _userData = data; };
    
    /** Gets user data */
    inline void* getUserData() const {
    return _userData; };
    
    /** Gets event name */
    inline const std::string& getEventName() const {
    return _eventName; };
protected:
	//恕我直言  没什么东西
    void* _userData;       ///< User data
    //事件名称
    std::string _eventName;
};

那再来看看 EventMouse 这个子类,也就是鼠标事件

//鼠标的操作
#define MOUSE_BUTTON_LEFT       0
#define MOUSE_BUTTON_RIGHT      1
#define MOUSE_BUTTON_MIDDLE     2
#define MOUSE_BUTTON_4          3
#define MOUSE_BUTTON_5          4
#define MOUSE_BUTTON_6          5
#define MOUSE_BUTTON_7          6
#define MOUSE_BUTTON_8          7
class CC_DLL EventMouse : public Event
{
   
public:
    /**
    * 鼠标事件类型
    */
    enum class MouseEventType
    {
   
        MOUSE_NONE,
        MOUSE_DOWN,
        MOUSE_UP,
        MOUSE_MOVE,
        MOUSE_SCROLL,
    };

    EventMouse(MouseEventType mouseEventCode);

    /** Set mouse scroll data */
    inline void setScrollData(float scrollX, float scrollY) {
    _scrollX = scrollX; _scrollY = scrollY; };
    inline float getScrollX() {
    return _scrollX; };
    inline float getScrollY() {
    return _scrollY; };
	//也就是  把最新的  鼠标位置保存 根据使 是否要开始捕获开始点  保存旧数据
    inline void setCursorPosition(float x, float y) {
    
        _x = x;
        _y = y;
        _prevPoint = _point;
        _point.x = x;
        _point.y = y;
        if (!_startPointCaptured)
        {
   
            _startPoint = _point;
            _startPointCaptured = true;
        }
    }

    inline void setMouseButton(int button) {
    _mouseButton = button; };
    inline int getMouseButton() {
    return _mouseButton; };
    inline float getCursorX() {
    return _x; };
    inline float getCursorY() {
    return _y; };

    /** returns the current touch location in OpenGL coordinates */
    Vec2 getLocation() const;
    /** returns the previous touch location in OpenGL coordinates */
    Vec2 getPreviousLocation() const;
    /** returns the start touch location in OpenGL coordinates */
    Vec2 getStartLocation() const;
    /** returns the delta of 2 current touches locations in screen coordinates */
    Vec2 getDelta() const;
    /** returns the current touch location in screen coordinates */
    Vec2 getLocationInView() const;
    /** returns the previous touch location in screen coordinates */
    Vec2 getPreviousLocationInView() const;
    /** returns the start touch location in screen coordinates */
    Vec2 getStartLocationInView() const;


private:
    MouseEventType _mouseEventType;
    int _mouseButton;
    float _x;
    float _y;
    float _scrollX;
    float _scrollY;

    bool _startPointCaptured;
    Vec2 _startPoint;
    Vec2 _point;
    Vec2 _prevPoint;

    friend class EventListenerMouse;
};
//基本操作  没什么关键点  

最后看看 EventTouch 这个类,也就是最常用的 触摸事件。

class CC_DLL EventTouch : public Event
{
   
public:
    static const int MAX_TOUCHES = 15;
    //触摸事件类型
    enum class EventCode
    {
   
        BEGAN,
        MOVED,
        ENDED,
        CANCELLED
    };

    EventTouch();

    inline EventCode getEventCode() const {
    return _eventCode; };
    //触摸点的 数组 所谓 多点触摸
    inline const std::vector<Touch*>& getTouches() const {
    return _touches; };

#if TOUCH_PERF_DEBUG
    void setEventCode(EventCode eventCode) {
    _eventCode = eventCode; };
    void setTouches(const std::vector<Touch*>& touches) {
    _touches = touches; };
#endif
    
private:
    EventCode _eventCode;
    std::vector<Touch*> _touches;

    friend class GLView;
};
//他的实现  没什么东西  顺便看看 Touch类
class CC_DLL Touch : public Ref
{
   
public:
    /** how the touches are dispathced */
    //分为 两种分发方式  如果你一次点击了多个点  因为人有10个手指 
    // 是把这些触摸点 一个个处理  还是一次处理
    enum class DispatchMode {
   
        /** All at once */
        ALL_AT_ONCE,
        /** one by one */
        ONE_BY_ONE,
    };

    Touch() 
        : _id(0),
        _startPointCaptured(false)
    {
   }
	//省略了一部分 get set
	//这个 和鼠标是一样的 毕竟触摸也只是有个触摸点
    void setTouchInfo(int id, float x, float y)
    {
   
        _id = id;
        _prevPoint = _point;
        _point.x   = x;
        _point.y   = y;
        if (!_startPointCaptured)
        {
   
            _startPoint = _point;
            _startPointCaptured = true;
            _prevPoint = _point;
        }
    }
    int getID() const
    {
   
        return _id;
    }

private:
    int _id;
    bool _startPointCaptured;
    Vec2 _startPoint;
    Vec2 _point;
    Vec2 _prevPoint;
};

可以看到 事件本身确实定义的很简洁,更多的处理在于各个事件的监听器。

下面介绍 EventListener
class CC_DLL EventListener : public Ref
{
   
public:
	//监听器的类型 比事件类型 多了两个
	// 一个是UNKNOWN 另一个是将TOUCH 细分为两种  总的说  是一一对应的
    enum class Type
    {
   
        UNKNOWN,
        TOUCH_ONE_BY_ONE,
        TOUCH_ALL_AT_ONCE,
        KEYBOARD,
        MOUSE,
        ACCELERATION,
        FOCUS,
		GAME_CONTROLLER,
        CUSTOM
    };
	//这个名字 其实有点误导人  ID本来单独指向 一个listener还好
	//这里用来代表的是 一种类型的事件监听器
	//为什么 不直接用上面的Type呢 因为  有自定义事件这个 搅*棍 
	//自定义事件  不知道有哪些类型的
    typedef std::string ListenerID;
    /** Initializes event with type and callback function */
    bool init(Type t, const ListenerID& listenerID, const std::function<void(Event*)>& callback);
public:
    /** Destructor */
    virtual ~EventListener();

    /** Checks whether the listener is available. */
    virtual bool checkAvailable() = 0;

    /** Clones the listener, its subclasses have to override this method. */
    virtual EventListener* clone() = 0;
	//值得一读 
    /** 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; };

    /** Checks whether the listener is enabled */
    inline bool isEnabled() const {
    return _isEnabled; };

protected:
	//值得一读 
    /** 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; };

    /** Checks whether the listener is paused */
    inline bool isPaused() const {
    return _paused; };
	//是用来 表明是否是向 事件分发器 注册过
    /** Marks the listener was registered by EventDispatcher */
    inline void setRegistered(bool registered) {
    _isRegistered = registered; };

    /** Checks whether the listener was registered by EventDispatcher */
    inline bool isRegistered() const {
    return _isRegistered; };

    /** Gets the type of this listener
     *  @note It's different from `EventType`, e.g. TouchEvent has two kinds of event listeners - EventListenerOneByOne, EventListenerAllAtOnce
     */
    inline Type getType() const {
    return _type; };

    /** Gets the listener ID of this listener
     *  When event is being dispatched, listener ID is used as key for searching listeners according to event type.
     */
    inline const ListenerID& getListenerID() const {
    return _listenerID; };

    /** Sets the fixed priority for this listener
     *  @note This method is only used for `fixed priority listeners`, it needs to access a non-zero value.
     *  0 is reserved for scene graph priority listeners
     */
     //非0值 0是给 scene graph priority 用的
    inline void setFixedPriority(int fixedPriority) {
    _fixedPriority = fixedPriority; };

    /** Gets the fixed priority of this listener
     *  @return 0 if it's a scene graph priority listener, non-zero for fixed priority listener
     */
    inline int getFixedPriority() const {
    return _fixedPriority; };

    /** Sets the node associated with this listener */
    inline void setAssociatedNode(Node* node) {
    _node = node; };

    /** Gets the node associated with this listener
     *  @return nullptr if it's a fixed priority listener, otherwise return non-nullptr
     */
     //fixed priority listener 将会返回null 因为他未与node绑定
    inline Node* getAssociatedNode() const {
    return _node; };

    ///
    // Properties
    //
    //仿函数 实现回调 很方便 前面几篇的  Schedule也是使用这种方式  
    //特别是对于 lambda 成员函数  会特别方便 
    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
    friend class EventDispatcher;
};

照例 还是先看看 EventListenerCustom

//一如既往的  没什么看头
class CC_DLL EventListenerCustom : public EventListener
{
   
public
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值