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

本文详细分析了cocos2d-x中的EventDispatcher类,从Event基类开始,逐步讲解了EventCustom、EventMouse、EventTouch子类,以及EventListener的各个子类如EventListenerCustom、EventListenerMouse、EventListenerTouchOneByOne和EventListenerTouchAllAtOnce。重点阐述了EventDispatcher如何组织并处理注册的监听器,当事件发生时如何调用相应回调。此外,还特别讨论了触摸事件的处理逻辑和updateListeners方法。
对应源码位置:(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:
    /** Creates an event listener with type and callback.
     *  @param eventType The type of the event.
     *  @param callback The callback function when the specified event was emitted.
     */
    static EventListenerCustom* create(const std::string& eventName, const std::function<void(EventCustom*)>& callback);
    
    /// Overrides
    virtual bool checkAvailable() override;
    virtual EventListenerCustom* clone() override;
    
CC_CONSTRUCTOR_ACCESS:
    /** Constructor */
    EventListenerCustom();
    
    /** Initializes event with type and callback function */
    bool init(const ListenerID& listenerId, const std::function<void(EventCustom*)>& callback);
    
protected:
	//
    std::function<void(EventCustom*)> _onCustomEvent;
    
    friend class LuaEventListenerCustom;
};
//实现
EventListenerCustom* EventListenerCustom::create(const std::string& eventName, const std::function<void(EventCustom*)>& callback)
{
    EventListenerCustom* ret = new (std::nothrow) EventListenerCustom();
    if (ret && ret->init(eventName, callback))
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

bool EventListenerCustom::init(const ListenerID& listenerId, const std::function<void(EventCustom*)>& callback)
{
    bool ret = false;
    
    _onCustomEvent = callback;
    //包装成 接受 Event* event的lambda
    auto listener = [this](Event* event){
        if (_onCustomEvent != nullptr)
        {
            _onCustomEvent(static_cast<EventCustom*>(event));
        }
    };
    //为上层(事件分发器)提供统一的接口
    if (EventListener::init(EventListener::Type::CUSTOM, listenerId, listener))
    {
        ret = true;
    }
    return ret;
}

继续看看 EventListenerMouse

class CC_DLL EventListenerMouse : public EventListener
{
public:
	// listenerid 是代表 这个类型listerner的监听器  
	//之所以 EventListenerCustom 没有这一项
	// 自定义监听器  每个传入的 name都代表 一种类型事件以及事件监听器
    static const std::string LISTENER_ID;
    static EventListenerMouse* create();
    /// Overrides
    virtual EventListenerMouse* clone() override;
    virtual bool checkAvailable() override;
	//主要的 对应四个事件类型的 处理
    std::function<void(Event* event)> onMouseDown;
    std::function<void(Event* event)> onMouseUp;
    std::function<void(Event* event)> onMouseMove;
    std::function<void(Event* event)> onMouseScroll;

CC_CONSTRUCTOR_ACCESS:
    EventListenerMouse();
    bool init();
};
//实现
const std::string EventListenerMouse::LISTENER_ID = "__cc_mouse";

bool EventListenerMouse::checkAvailable()
{
    return true;
}

EventListenerMouse* EventListenerMouse::create()
{
    auto ret = new (std::nothrow) EventListenerMouse();
    if (ret && ret->init())
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

EventListenerMouse* EventListenerMouse::clone()
{
    auto ret = new (std::nothrow) EventListenerMouse();
    if (ret && ret->init())
    {
        ret->autorelease();
        ret->onMouseUp = onMouseUp;
        ret->onMouseDown = onMouseDown;
        ret->onMouseMove = onMouseMove;
        ret->onMouseScroll = onMouseScroll;
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

EventListenerMouse::EventListenerMouse()
: onMouseDown(nullptr)
, onMouseUp(nullptr)
, onMouseMove(nullptr)
, onMouseScroll(nullptr)
{
}
//这个 就是  对应于每个 时间类型 调用相应的回调函数
//对上层 包装成 统一接口
bool EventListenerMouse::init()
{
    auto listener = [this](Event* event){
        auto mouseEvent = static_cast<EventMouse*>(event);
        switch (mouseEvent->_mouseEventType)
        {
            case EventMouse::MouseEventType::MOUSE_DOWN:
                if(onMouseDown != nullptr)
                    onMouseDown(event);
                break;
            case EventMouse::MouseEventType::MOUSE_UP:
                if(onMouseUp != nullptr)
                    onMouseUp(event);
                break;
            case EventMouse::MouseEventType::MOUSE_MOVE:
                if(onMouseMove != nullptr)
                    onMouseMove(event);
                break;
            case EventMouse::MouseEventType::MOUSE_SCROLL:
                if(onMouseScroll != nullptr)
                    onMouseScroll(event);
                break;
            default:
                break;
        }
    };

    if (EventListener::init(Type::MOUSE, LISTENER_ID, listener))
    {
        return true;
    }

    return false;
}

最后看看 最重要的 最常用 EventListenerTouchOneByOneEventListenerTouchAllAtOnce

class CC_DLL EventListenerTouchOneByOne : public EventListener
{
public:
    static const std::string LISTENER_ID;
    
    static EventListenerTouchOneByOne* create();
    
    virtual ~EventListenerTouchOneByOne();
    //是否吞噬 事件 就是自己处理完了  后面的就没得处理了
    void setSwallowTouches(bool needSwallow);
    bool isSwallowTouches();
    
    /// Overrides
    virtual EventListenerTouchOneByOne* clone() override;
    virtual bool checkAvailable() override;
    //

public:

    typedef std::function<bool(Touch*, Event*)> ccTouchBeganCallback;
    typedef std::function<void(Touch*, Event*)> ccTouchCallback;
	//不同的处理 回调
    ccTouchBeganCallback onTouchBegan;
    ccTouchCallback onTouchMoved;
    ccTouchCallback onTouchEnded;
    ccTouchCallback onTouchCancelled;
    
CC_CONSTRUCTOR_ACCESS:
    EventListenerTouchOneByOne();
    bool init();
    
private:
    std::vector<Touch*> _claimedTouches;
    bool _needSwallow;
    friend class EventDispatcher;
};
//具体实现
const std::string EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one";
//这里没有对各个处理的函数进行封装 
//应该是 这个情况比较复杂
// 那只有等到 事件分发的时候  具体情况调用
bool EventListenerTouchOneByOne::init()
{
    if (EventListener::init(Type::TOUCH_ONE_BY_ONE, LISTENER_ID, nullptr))
    {
        return true;
    }    
    return false;
}
//可以看到 并没有要求 create的时候传入 相关回调函数 因为这几个是 public 可以直接访问
EventListenerTouchOneByOne* EventListenerTouchOneByOne::create()
{
    auto ret = new (std::nothrow) EventListenerTouchOneByOne();
    if (ret && ret->init())
    {
        ret->autorelease();
    }
    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.
    if (onTouchBegan == nullptr)
    {
        CCASSERT(false, "Invalid EventListenerTouchOneByOne!");
        return false;
    }
    
    return true;
}

EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
{
    auto ret = new (std::nothrow) 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;
}
//同理 EventListenerTouchAllAtOnce 中也没有什么具体细节  和上面类似
//也应该在 具体调用的时候 来处理
到了关键的 EventDispatcher分析

其实可想而知 他负责将各种 注册的listener组织起来 ,然后当有模块发布了事件 就相应的找到 listener,然后回调其函数即可。

在这里插入图片描述
具体类的重要代码如下:

class CC_DLL EventDispatcher : public Ref
{
public:
    // Adds event listener
    
    /** Adds a event listener for a specified event with the priority of scene graph.
     *  @param listener The listener of a specified event.
     *  @param node The priority of the listener is based on the draw order of this node.
     *  @note  The priority of scene graph will be fixed value 0. So the order of listener item
     *          in the vector will be ' <0, scene graph (0 priority), >0'.
     */
     //添加时 绑定一个 node节点
    void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);

    /** Adds a event listener for a specified event with the fixed priority.
     *  @param listener The listener of a specified event.
     *  @param fixedPriority The fixed priority of the listener.
     *  @note A lower priority will be called before the ones that have a higher value.
     *        0 priority is forbidden for fixed priority since it's used for scene graph based priority.
     */
     //固定优先级 加入listener
    void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);

    /** Adds a Custom event listener.
     It will use a fixed priority of 1.
     @return the generated event. Needed in order to remove the event from the dispather
     */
     //添加 自定义的listener
    EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback);
    void dispatchEvent(Event* event);

    /** Dispatches a Custom Event with a event name an optional user data */
    //分发 自定义事件
    void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);
    //其中 有个内部类 就是对vector
    //实际上 对应于一个listenID 即为一个事件类型
    //对应于 一个 EventListenerVector
    class EventListenerVector
    {
    public:
        EventListenerVector();
        ~EventListenerVector();
        size_t size() const;
        bool empty() const;
        
        void push_back(EventListener* item);
        void clearSceneGraphListeners();
        void clearFixedListeners();
        void clear();
        
        inline std::vector<EventListener*>* getFixedPriorityListeners() const { return _fixedListeners; };
        inline std::vector<EventListener*>* getSceneGraphPriorityListeners() const { return _sceneGraphListeners; };
        inline ssize_t getGt0Index() const { return _gt0Index; };
        inline void setGt0Index(ssize_t index) { _gt0Index = index; };
    private:
        std::vector<EventListener*>* _fixedListeners;
        std::vector<EventListener*>* _sceneGraphListeners;
        //第一个 大于等于0的 位置
        ssize_t _gt0Index;
    };
    //添加 EventListener 内部实现  肯定根据 类型调用不同的函数
     void addEventListener(EventListener* listener);
    
    /** Force adding an event listener
     *  @note force add an event listener which will ignore whether it's in dispatching.
     *  @see addEventListener
     */
     //强行 添加一个 EventListener
    void forceAddEventListener(EventListener* listener);
      /** Touch event needs to be processed different with other events since it needs support ALL_AT_ONCE and ONE_BY_NONE mode. */
     //分发 触摸事件 其内部必然 分两种处理方式
    void dispatchTouchEvent(EventTouch* event);
    //偷来的一段话
   //DirtyFlag 是设置给 ListenerID 的,每当新添加一个 Listener,或则删除一个 Listener 的时候,
   //就会给当前 Listener 的 ListenerID 添加一个      			   
   	//DirtyFlag。说明这个脏是指 ListenerID 对应的监听器向量列表需要重新排序了,如果不脏就不需要排序。
    /// Priority dirty flag
    enum class DirtyFlag
    {
        NONE = 0,
        FIXED_PRIORITY = 1 << 0,
        SCENE_GRAPH_PRIORITY = 1 << 1,
        ALL = FIXED_PRIORITY | SCENE_GRAPH_PRIORITY
    };
    
    /** Sets the dirty flag for a specified listener ID */
    void setDirty(const EventListener::ListenerID& listenerID, DirtyFlag flag);
    
  	//通过SceneGraph来获取每个节点的绘制顺序,在使用SceneGraph优先级对事件侦听器进行排序之前调用它
    void visitTarget(Node* node, bool isRootNode);
    //重要的数据结构
    //ListenerID 与 EventListenerVector的 map 
    //即为 不同类型的 listener 存在不同位置
    /** Listeners map */
    std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
    //用来表明 ListenerID对应的 EventListenerVector的那一部分 listener脏了  需要重新排序
    /** The map of dirty flag */
    std::unordered_map<EventListener::ListenerID, DirtyFlag> _priorityDirtyFlagMap;
    //Node节点与其对应EventListener 数组,应该用在 SceneGraphPriority
    /** The map of node and event listeners */
    std::unordered_map<Node*, std::vector<EventListener*>*> _nodeListenersMap;
    //节点与其对应的优先级
    /** The map of node and its event priority */
    std::unordered_map<Node*, int> _nodePriorityMap;
    //z序与其对应的Node节点们
    /** key: Global Z Order, value: Sorted Nodes */
    std::unordered_map<float, std::vector<Node*>> _globalZOrderNodeMap;
    //这次事件分发后 将要的 加入 listener
    /** The listeners to be added after dispatching event */
    std::vector<EventListener*> _toAddedListeners;
    
    /** The nodes were associated with scene graph based priority listeners */
    //与基于SceneGraphPriority的listener 有关联的 node
    std::set<Node*> _dirtyNodes;
    
    /** Whether the dispatcher is dispatching event */
    int _inDispatch;
    
    /** Whether to enable dispatching event */
    bool _isEnabled;
    
    int _nodePriorityIndex;
    
    std::set<std::string> _internalCustomListenerIDs;
};

这部分代码比较长,具体该类的实现继续说:

//添加 SceneGraphPriority listener 传入对应的 node
void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
{
    CCASSERT(listener && node, "Invalid parameters.");
    CCASSERT(!listener->isRegistered(), "The listener has been registered.");
    
    if (!listener->checkAvailable())
        return;
    //设置 对应的node
    listener->setAssociatedNode(node);
    //其实这里可以看出来 SceneGraphPriority就是 优先级为0
    //并且多了个 AssociatedNode
    listener->setFixedPriority(0);
    listener->setRegistered(true);
    
    addEventListener(listener);
}
//添加 固定优先级的 listener
void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
{
    CCASSERT(listener, "Invalid parameters.");
    CCASSERT(!listener->isRegistered(), "The listener has been registered.");
    CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
    
    if (!listener->checkAvailable())
        return;
    //没有 关联的对象
    listener->setAssociatedNode(nullptr);
    listener->setFixedPriority(fixedPriority);
    listener->setRegistered(true);
    listener->setPaused(false);
	//底层都是调用了 addEventListener
    addEventListener(listener);
}
//添加 自定义的 listener 
EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback)
{
    EventListenerCustom *listener = EventListenerCustom::create(eventName, callback);
    //只是设置为 优先级 设为1 也算高了 
    //然后当做 固定优先级 添加 真是低调
    addEventListenerWithFixedPriority(listener, 1);
    return listener;
}
//添加 EventListener
void EventDispatcher::addEventListener(EventListener* listener)
{
	//直接 添加 listener
    if (_inDispatch == 0)
    {
        forceAddEventListener(listener);
    }
    //如果正在分发事件  就先存着
    else
    {
        _toAddedListeners.push_back(listener);
    }

    listener->retain();
}

void EventDispatcher::forceAddEventListener(EventListener* listener)
{
    EventListenerVector* listeners = nullptr;
    //先看看  有没有 这种类型的 ListenerID  对应的EventListenerVector
    EventListener::ListenerID listenerID = listener->getListenerID();
    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;
    }
    //这里push_back有个讲究 代码没贴 大概的意思是
    //如果 优先级为 0 就是 sceneGraphListeners
    //否则就加入到 另外一条中
    listeners->push_back(listener);
    //如果 优先级为 0 就说明 对于 listenerID的 SCENE_GRAPH_PRIORITY这部分更新了 脏了
    if (listener->getFixedPriority() == 0)
    {
        setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);
        
        auto node = listener->getAssociatedNode();
        CCASSERT(node != nullptr, "Invalid scene graph priority!");
        
        associateNodeAndEventListener(node, listener);
        
        if (node->isRunning())
        {
            resumeEventListenersForTarget(node);
        }
    }
    else
    {
    	//否则  就是 另外一部分 脏了
        setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
    }
}
//就是 把 node与EventListener的对应 存起来
void EventDispatcher::associateNodeAndEventListener(Node* node, EventListener* listener)
{
    std::vector<EventListener*>* listeners = nullptr;
    auto found = _nodeListenersMap.find(node);
    if (found != _nodeListenersMap.end())
    {
        listeners = found->second;
    }
    else
    {
        listeners = new std::vector<EventListener*>();
        _nodeListenersMap.insert(std::make_pair(node, listeners));
    }
    
    listeners->push_back(listener);
}

下面正式开始 介绍Dispatch的逻辑

//分发 自定义事件 简单包装一下 交由dispatchEvent
void EventDispatcher::dispatchCustomEvent(const std::string &eventName, void *optionalUserData)
{
    EventCustom ev(eventName);
    ev.setUserData(optionalUserData);
    dispatchEvent(&ev);
}
//最核心的 dispatchEvent
void EventDispatcher::dispatchEvent(Event* event)
{
    if (!_isEnabled)
        return;
    //不值得 展开讲
    //就是 将_dirtyNodes 也就是对应 与 SceneGraph有关的 node
    //找到 其对应的 listener数组
    //对每一个 listener 标记其 SceneGraph 脏了 需要更新
    //针对的是 新添加的 node相关  处理完 这个_dirtyNodes 会清空
    updateDirtyFlagForSceneGraph();
    DispatchGuard guard(_inDispatch);
    //单独处理 触摸事件
    if (event->getType() == Event::Type::TOUCH)
    {
        dispatchTouchEvent(static_cast<EventTouch*>(event));
        return;
    }
    //找出 这种事件类型的 对应的 listenerid
    auto listenerID = __getListenerID(event);
  	//排序 listener
    sortEventListeners(listenerID);
    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();
        };
        //直接 分发事件 
        dispatchEventToListeners(listeners, onEvent);
    }
    
    updateListeners(event);
}
// 先说 排序
void EventDispatcher::sortEventListeners(const EventListener::ListenerID& listenerID)
{
    DirtyFlag dirtyFlag = DirtyFlag::NONE;
    auto dirtyIter = _priorityDirtyFlagMap.find(listenerID);
    if (dirtyIter != _priorityDirtyFlagMap.end())
    {
        dirtyFlag = dirtyIter->second;
    }
    //这就是  如果数据没脏就不排序
    if (dirtyFlag != DirtyFlag::NONE)
    {
        // Clear the dirty flag first, if `rootNode` is nullptr, then set its dirty flag of scene graph priority
        dirtyIter->second = DirtyFlag::NONE;

        if ((int)dirtyFlag & (int)DirtyFlag::FIXED_PRIORITY)
        {
        	//先排序 固定 优先级的
            sortEventListenersOfFixedPriority(listenerID);
        }
        
        if ((int)dirtyFlag & (int)DirtyFlag::SCENE_GRAPH_PRIORITY)
        {
            auto rootNode = Director::getInstance()->getRunningScene();
            if (rootNode)
            {
            	//再排序  SceneGraphPriority
                sortEventListenersOfSceneGraphPriority(listenerID, rootNode);
            }
            else
            {
                dirtyIter->second = DirtyFlag::SCENE_GRAPH_PRIORITY;
            }
        }
    }
}
//继续深究 这两种 排序
void EventDispatcher::sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID)
{
    auto listeners = getListeners(listenerID);
    if (listeners == nullptr)
        return;
    auto fixedListeners = listeners->getFixedPriorityListeners();
    if (fixedListeners == nullptr)
        return;
    // After sort: priority < 0, > 0
   	//先排个序 按优先级 从小到大
    std::sort(fixedListeners->begin(), fixedListeners->end(), [](const EventListener* l1, const EventListener* l2) {
        return l1->getFixedPriority() < l2->getFixedPriority();
    });
    // FIXME: Should use binary search
    //找到 第一个>0的位置
    //因为 最后的顺序是  先 <0 再 SceneGraphPriority 即为0 
    //再分发 >0
    int index = 0;
    for (auto& listener : *fixedListeners)
    {
        if (listener->getFixedPriority() >= 0)
            break;
        ++index;
    }  
    listeners->setGt0Index(index);   
}
void EventDispatcher::sortEventListenersOfSceneGraphPriority(const EventListener::ListenerID& listenerID, Node* rootNode)
{
    auto listeners = getListeners(listenerID);
   
    if (listeners == nullptr)
        return;
    auto sceneGraphListeners = listeners->getSceneGraphPriorityListeners();
   
    if (sceneGraphListeners == nullptr)
        return;
    // Reset priority index
    _nodePriorityIndex = 0;
    //清空节点 优先级
    _nodePriorityMap.clear();
    //遍历 rootNode
    visitTarget(rootNode, true);

    // After sort: priority < 0, > 0
    //根据节点的优先级来 排序sceneGraphListeners
    std::sort(sceneGraphListeners->begin(), sceneGraphListeners->end(), [this](const EventListener* l1, const EventListener* l2) {
        return _nodePriorityMap[l1->getAssociatedNode()] > _nodePriorityMap[l2->getAssociatedNode()];
    });   
}
//看看 visitTarget
void EventDispatcher::visitTarget(Node* node, bool isRootNode)
{    
    int i = 0;
    auto& children = node->getChildren();
    auto childrenCount = children.size();
    if(childrenCount > 0)
    {
        Node* child = nullptr;
        // visit children zOrder < 0
        for( ; i < childrenCount; i++ )
        {
            child = children.at(i);
            
            if ( child && child->getLocalZOrder() < 0 )
            	//递归遍历 child->getLocalZOrder() < 0
                visitTarget(child, false);
            else
                break;
        }
        //如果某个节点对应了 listener
        if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
        {
        	//将其 添加到 GlobalZOrder对应的数组
            _globalZOrderNodeMap[node->getGlobalZOrder()].push_back(node);
        }
        //访问 另一部分  大于0的部分
        for( ; i < childrenCount; i++ )
        {
            child = children.at(i);
            if (child)
                visitTarget(child, false);
        }
    }
    else
    {
    //叶子节点 直接加入
        if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
        {
            _globalZOrderNodeMap[node->getGlobalZOrder()].push_back(node);
        }
    }
    //根节点 也就是最后一次调用的时候   整个遍历结束了
    if (isRootNode)
    {
        std::vector<float> globalZOrders;
        globalZOrders.reserve(_globalZOrderNodeMap.size());
        
        for (const auto& e : _globalZOrderNodeMap)
        {
            globalZOrders.push_back(e.first);
        }
        //排序所有的Zorder 从小大大 要知道 z越小 离屏幕越近
        std::sort(globalZOrders.begin(), globalZOrders.end(), [](const float a, const float b){
            return a < b;
        });
        
        for (const auto& globalZ : globalZOrders)
        {
            for (const auto& n : _globalZOrderNodeMap[globalZ])
            {	//按照不同Zorder 同一Zorder  从左到右  计数 
            	//此时 顺序已经定了
                _nodePriorityMap[n] = ++_nodePriorityIndex;
            }
        }
        
        _globalZOrderNodeMap.clear();
    }
}
//这时候再提 dispatchEventToListeners 触摸相关的一会儿说
void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
{
    bool shouldStopPropagation = false;
    //获取两个 listener 列表
    auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
    auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
    
    ssize_t i = 0;
    //下面分别 按照 priority < 0  priority == 0, >0 遍历 处理
    //注意的是  只要有listener处理了 并且吞吃了  就不会往后传递了 所以优先级的意义在这里
    // priority < 0 
    if (fixedPriorityListeners)
    {
        CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
        
        if (!fixedPriorityListeners->empty())
        {
            for (; i < listeners->getGt0Index(); ++i)
            {
                auto l = fixedPriorityListeners->at(i);
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }
    
    if (sceneGraphPriorityListeners)
    {
        if (!shouldStopPropagation)
        {
            // priority == 0, scene graph priority
            for (auto& l : *sceneGraphPriorityListeners)
            {
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }

    if (fixedPriorityListeners)
    {
        if (!shouldStopPropagation)
        {
            // priority > 0
            ssize_t size = fixedPriorityListeners->size();
            for (; i < size; ++i)
            {
                auto l = fixedPriorityListeners->at(i);
                
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }
}

单独提出来 对touch的处理,太长了 也很有意思

void EventDispatcher::dispatchTouchEvent(EventTouch* event)
{
	//排个序
    sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID);
    sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
    
    auto oneByOneListeners = getListeners(EventListenerTouchOneByOne::LISTENER_ID);
    auto allAtOnceListeners = getListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
    
    // If there aren't any touch listeners, return directly.
    if (nullptr == oneByOneListeners && nullptr == allAtOnceListeners)
        return;
    
    bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners);
    const std::vector<Touch*>& originalTouches = event->getTouches();
     //复制 一份
    std::vector<Touch*> mutableTouches(originalTouches.size());
    std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin());

    //
    // process the target handlers 1st
    //
    //优先处理 onebyone
    if (oneByOneListeners)
    {
        auto mutableTouchesIter = mutableTouches.begin();
        auto touchesIter = originalTouches.begin();
        
        for (; touchesIter != originalTouches.end(); ++touchesIter)
        {
            bool isSwallowed = false;

            auto onTouchEvent = [&](EventListener* l) -> bool { // Return true to break
                EventListenerTouchOneByOne* listener = static_cast<EventListenerTouchOneByOne*>(l);
                
                // Skip if the listener was removed.
                if (!listener->_isRegistered)
                    return false;
             
                event->setCurrentTarget(listener->_node);
                
                bool isClaimed = false;
                std::vector<Touch*>::iterator removedIter;
                
                EventTouch::EventCode eventCode = event->getEventCode();
                
                if (eventCode == EventTouch::EventCode::BEGAN)
                {
                    if (listener->onTouchBegan)
                    {
                    	//说明这个触摸点  他可以处理  收下了
                        isClaimed = listener->onTouchBegan(*touchesIter, event);
                        if (isClaimed && listener->_isRegistered)
                        {
                            listener->_claimedTouches.push_back(*touchesIter);
                        }
                    }
                }
                //不是 begin事件  begin时候已经记录了所有要处理的触摸点  
                //后续就是要确保  还是以前 触摸点  
                //注意一个触摸点 并非是一个坐标  是手指点击到屏幕  滑动 直到离开  
                //这看成一次完完整的触摸 其坐标都记录在这一个触摸点对象中
                else if (listener->_claimedTouches.size() > 0
                         && ((removedIter = std::find(listener->_claimedTouches.begin(), listener->_claimedTouches.end(), *touchesIter)) != listener->_claimedTouches.end()))
                {
                    isClaimed = true;
                    
                    switch (eventCode)
                    {
                        case EventTouch::EventCode::MOVED:
                            if (listener->onTouchMoved)
                            {
                                listener->onTouchMoved(*touchesIter, event);
                            }
                            break;
                        case EventTouch::EventCode::ENDED:
                            if (listener->onTouchEnded)
                            {
                                listener->onTouchEnded(*touchesIter, event);
                            }
                            //结束了  就从 listener删掉这个触摸点
                            if (listener->_isRegistered)
                            {
                                listener->_claimedTouches.erase(removedIter);
                            }
                            break;
                        case EventTouch::EventCode::CANCELLED:
                            if (listener->onTouchCancelled)
                            {
                                listener->onTouchCancelled(*touchesIter, event);
                            }
                            if (listener->_isRegistered)
                            {
                                listener->_claimedTouches.erase(removedIter);
                            }
                            break;
                        default:
                            CCASSERT(false, "The eventcode is invalid.");
                            break;
                    }
                }
                
                // If the event was stopped, return directly.
                //事件被stop了
                if (event->isStopped())
                {
                    updateListeners(event);
                    return true;
                }
                
                CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(), "");
                //如果这个触摸点 oneByOneListeners愿意处理  并且 _needSwallow就从触摸点列表中删掉
                //  后续listener就没机会 处理了
                if (isClaimed && listener->_isRegistered && listener->_needSwallow)
                {
                    if (isNeedsMutableSet)
                    {
                        mutableTouchesIter = mutableTouches.erase(mutableTouchesIter);
                        isSwallowed = true;
                    }
                    return true;
                }
                
                return false;
            };
            
            //
            dispatchEventToListeners(oneByOneListeners, onTouchEvent);
            if (event->isStopped())
            {
                return;
            }
            //吞了的话  迭代器已经自动更新了  所以不必自加
            if (!isSwallowed)
                ++mutableTouchesIter;
        }
    }
    
    //
    // process standard handlers 2nd
    //
    //最后  如果还剩下什么  点  就给 allAtOnceListeners 处理
    if (allAtOnceListeners && mutableTouches.size() > 0)
    {
        
        auto onTouchesEvent = [&](EventListener* l) -> bool{
            EventListenerTouchAllAtOnce* listener = static_cast<EventListenerTouchAllAtOnce*>(l);
            // Skip if the listener was removed.
            if (!listener->_isRegistered)
                return false;
            
            event->setCurrentTarget(listener->_node);
            //allAtOnceListeners  果然不同 一次处理多个触摸点操作
            //而且 他也没有 有始有终  的意味  不必要第一次返回bool的操作
            switch (event->getEventCode())
            {
                case EventTouch::EventCode::BEGAN:
                    if (listener->onTouchesBegan)
                    {
                        listener->onTouchesBegan(mutableTouches, event);
                    }
                    break;
                case EventTouch::EventCode::MOVED:
                    if (listener->onTouchesMoved)
                    {
                        listener->onTouchesMoved(mutableTouches, event);
                    }
                    break;
                case EventTouch::EventCode::ENDED:
                    if (listener->onTouchesEnded)
                    {
                        listener->onTouchesEnded(mutableTouches, event);
                    }
                    break;
                case EventTouch::EventCode::CANCELLED:
                    if (listener->onTouchesCancelled)
                    {
                        listener->onTouchesCancelled(mutableTouches, event);
                    }
                    break;
                default:
                    CCASSERT(false, "The eventcode is invalid.");
                    break;
            }
            
            // If the event was stopped, return directly.
            if (event->isStopped())
            {
                updateListeners(event);
                return true;
            }
            
            return false;
        };
        
        dispatchEventToListeners(allAtOnceListeners, onTouchesEvent);
        if (event->isStopped())
        {
            return;
        }
    }
    
    updateListeners(event);
}

最后简要介绍 updateListeners

//其实就是 根据事件的类型  更新对应种类listenerID的所有监听器 
//如果注册状态  为 未注册  测删掉对应监听器
//如果 更新后发现  整个种类都没了  就删除这一类的  表项
//同时  如果正在分发事件的最后  还可以把_toAddedListeners加入过来
void EventDispatcher::updateListeners(Event* event)
{
    CCASSERT(_inDispatch > 0, "If program goes here, there should be event in dispatch.");
    
    auto onUpdateListeners = [this](const EventListener::ListenerID& listenerID)
    {
        auto listenersIter = _listenerMap.find(listenerID);
        if (listenersIter == _listenerMap.end())
            return;

        auto listeners = listenersIter->second;
        
        auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
        auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
        
        if (sceneGraphPriorityListeners)
        {
            for (auto iter = sceneGraphPriorityListeners->begin(); iter != sceneGraphPriorityListeners->end();)
            {
                auto l = *iter;
                if (!l->isRegistered())
                {
                    iter = sceneGraphPriorityListeners->erase(iter);
                    l->release();
                }
                else
                {
                    ++iter;
                }
            }
        }
        
        if (fixedPriorityListeners)
        {
            for (auto iter = fixedPriorityListeners->begin(); iter != fixedPriorityListeners->end();)
            {
                auto l = *iter;
                if (!l->isRegistered())
                {
                    iter = fixedPriorityListeners->erase(iter);
                    l->release();
                }
                else
                {
                    ++iter;
                }
            }
        }
        
        if (sceneGraphPriorityListeners && sceneGraphPriorityListeners->empty())
        {
            listeners->clearSceneGraphListeners();
        }

        if (fixedPriorityListeners && fixedPriorityListeners->empty())
        {
            listeners->clearFixedListeners();
        }
    };

    
    if (event->getType() == Event::Type::TOUCH)
    {
        onUpdateListeners(EventListenerTouchOneByOne::LISTENER_ID);
        onUpdateListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
    }
    else
    {
        onUpdateListeners(__getListenerID(event));
    }
    
    if (_inDispatch > 1)
        return;
    
    CCASSERT(_inDispatch == 1, "_inDispatch should be 1 here.");
    
    for (auto iter = _listenerMap.begin(); iter != _listenerMap.end();)
    {
        if (iter->second->empty())
        {
            _priorityDirtyFlagMap.erase(iter->first);
            delete iter->second;
            iter = _listenerMap.erase(iter);
        }
        else
        {
            ++iter;
        }
    }
    
    if (!_toAddedListeners.empty())
    {
        for (auto& listener : _toAddedListeners)
        {
            forceAddEventListener(listener);
        }
        _toAddedListeners.clear();
    }
}
最后

下一篇 就 Node 类体系展开分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值