最近学习了下cocos2dx3.x版本的事件响应和分发逻辑,由于3.x版本作者个人用的比较少,结果是看的一头雾水。这里简单的笔记下大概的代码流程吧,以后用的多了理解加深了在随时更新吧。
先看一些基础的类的定义。
CONTENTS
CCEvent.h/cpp:
事件的基类,定义了相关的类型和操作函数,没有具体的业务处理。代码比较简单,如下:
class Event : public Ref { public: enum class Type { TOUCH, KEYBOARD, ACCELERATION, MOUSE, FOCUS, CUSTOM }; protected: /** 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; }; /** @brief Gets current target of the event * @return The target with which the event associates. * @note It onlys be available when the event listener is associated with node. * It returns 0 when the listener is associated with fixed priority. */ inline Node* getCurrentTarget() { return _currentTarget; }; protected: /** Sets current target */ inline void setCurrentTarget(Node* target) { _currentTarget = target; }; Type _type; ///< Event type bool _isStopped; ///< whether the event has been stopped. Node* _currentTarget; ///< Current target //注意这里将EventDispatcher设置为其友元类,这样EventDispatcher可以方便的访问Event的各种变量和函数。 friend class EventDispatcher; };
CCEventListener.h/cpp:
事件监听器的基类,定义了相关的函数和类型等,没有具体的业务处理。代码比较简单,如下:
/** * The base class of event listener. * If you need custom listener which with different callback, you need to inherit this class. * For instance, you could refer to EventListenerAcceleration, EventListenerKeyboard, EventListenerTouchOneByOne, EventListenerCustom. */ class EventListener : public Ref { public: //这里的Type要比Event中的定义的要多,因为同一个事件可以进行不同的处理。 //这里主要是触摸事件。 enum class Type { UNKNOWN, TOUCH_ONE_BY_ONE, TOUCH_ALL_AT_ONCE, KEYBOARD, MOUSE, ACCELERATION, FOCUS, CUSTOM }; typedef std::string ListenerID; protected: /** Constructor */ EventListener(); /** 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 */ 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 */ inline Node* getAssociatedNode() const { return _node; }; /////////////// // Properties ////////////// 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; }; ====== .cpp内容: EventListener::EventListener() {} EventListener::~EventListener() { CCLOGINFO("In the destructor of EventListener. %p", this); } bool EventListener::init(Type t, const ListenerID& listenerID, const std::function<void(Event*)>& callback) { _onEvent = callback; _type = t; _listenerID = listenerID; _isRegistered = false; _paused = true; _isEnabled = true; return true; } bool EventListener::checkAvailable() { return (_onEvent != nullptr); }
CCEventDispatcher:
首先需要笔记的是cocos2dx3.x版本的EventDispatcher是事件驱动型的,即当事件响应函数注册好之后,只有外部事件发生之后,主动调用EventDispatcher的方法,才回逐步路由到时间响应函数中。
事件监听器的优先级如果为0,则会被认为graphic listener。如果要把监听器设置为fix,那么它的优先级不能设置为0。
首先看下EventDispatcher中定义的一个内部类EventListenerVector:
EventListenerVector是EventDispatcher的一个内部类,需要注意的是它是protected,因此对外是不可见的。
EventListenerVector的主要作用是分类存储外部注册进来的各种listener,并且对其进行管理。
class EventDispatcher : public Ref { protected: /** * The vector to store event listeners with scene graph based priority and fixed priority. */ 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; ssize_t _gt0Index; }; } ======= EventDispatcher::EventListenerVector::EventListenerVector() : _fixedListeners(nullptr),//_fixedListeners和_sceneGraphListeners均为std::vector,用到时在初始化 _sceneGraphListeners(nullptr), _gt0Index(0) { } EventDispatcher::EventListenerVector::~EventListenerVector() { CC_SAFE_DELETE(_sceneGraphListeners); CC_SAFE_DELETE(_fixedListeners); } //返回已经注册的eventlistener的数量 size_t EventDispatcher::EventListenerVector::size() const { size_t ret = 0; if (_sceneGraphListeners) ret += _sceneGraphListeners->size(); if (_fixedListeners) ret += _fixedListeners->size(); return ret; } //判断是否有eventlistener bool EventDispatcher::EventListenerVector::empty() const { return (_sceneGraphListeners == nullptr || _sceneGraphListeners->empty()) && (_fixedListeners == nullptr || _fixedListeners->empty()); } //将一个eventlistener注册到Dispatcher尾端。 //这里需要注意的是一个隐含逻辑: //graphic listener的优先级是固定为0的,因此如果一个listener的优先级为0,说明这个listener是GraphListener级别的。 void EventDispatcher::EventListenerVector::push_back(EventListener* listener) { #if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS CCASSERT(_sceneGraphListeners == nullptr || std::count(_sceneGraphListeners->begin(), _sceneGraphListeners->end(), listener) == 0, "Listener should not be added twice!"); CCASSERT(_fixedListeners == nullptr || std::count(_fixedListeners->begin(), _fixedListeners->end(), listener) == 0, "Listener should not be added twice!"); #endif //如果优先级别为0,是一个graphic listener。 if (listener->getFixedPriority() == 0) {//如果_sceneGraphListeners为空,就申请一个新的,容量为100 if (_sceneGraphListeners == nullptr) { _sceneGraphListeners = new std::vector<EventListener*>(); _sceneGraphListeners->reserve(100); } //将这个listener放到这个vector中 _sceneGraphListeners->push_back(listener); } else { //优先级不为0,就放到_fixedListeners中。 if (_fixedListeners == nullptr) { _fixedListeners = new std::vector<EventListener*>(); _fixedListeners->reserve(100); } _fixedListeners->push_back(listener); } } //清空_sceneGraphListeners,并且删除它 void EventDispatcher::EventListenerVector::clearSceneGraphListeners() { if (_sceneGraphListeners) { _sceneGraphListeners->clear(); delete _sceneGraphListeners; _sceneGraphListeners = nullptr; } } //清空_fixedListeners,并且删除它 void EventDispatcher::EventListenerVector::clearFixedListeners() { if (_fixedListeners) { _fixedListeners->clear(); delete _fixedListeners; _fixedListeners = nullptr; } } //清空EventDispatcher void EventDispatcher::EventListenerVector::clear() { clearSceneGraphListeners(); clearFixedListeners(); }
由于EventDispatch的函数非常多,成员变量也很多很乱,这里先看下它的头文件。
CCEventDispatcher.h:
class 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'. */ //注释比较清楚,添加一个listener,Graph优先级(即优先级为0) 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,返回这个listener的实例(EventListenerCustom的构造函数是protected,无法直接创建) EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback); ///////////////////////////////////////////// // Removes event listener /** Remove a listener * @param listener The specified event listener which needs to be removed. */ //移除一个listener void removeEventListener(EventListener* listener); /** Removes all listeners with the same event listener type */ //移除某种类型的所有listener void removeEventListenersForType(EventListener::Type listenerType); /** Removes all listeners which are associated with the specified target. */ //移除关联到某个节点的所有listener void removeEventListenersForTarget(Node* target, bool recursive = false); /** Removes all custom listeners with the same event name */ //移除某个自定义的事件的listener void removeCustomEventListeners(const std::string& customEventName); /** Removes all listeners */ //移除所有的listener void removeAllEventListeners(); ///////////////////////////////////////////// // Pauses / Resumes event listener /** Pauses all listeners which are associated the specified target. */ //暂停与某个节点相关联的listener的响应 void pauseEventListenersForTarget(Node* target, bool recursive = false); /** Resumes all listeners which are associated the specified target. */ //恢复与某个节点相关联的listener的响应 void resumeEventListenersForTarget(Node* target, bool recursive = false); ///////////////////////////////////////////// /** Sets listener's priority with fixed value. */ //设置某个listener的优先级 void setPriority(EventListener* listener, int fixedPriority); /** Whether to enable dispatching events */ //使能 void setEnabled(bool isEnabled); /** Checks whether dispatching events is enabled */ //返回是否使能 bool isEnabled() const; ///////////////////////////////////////////// /** Dispatches the event * Also removes all EventListeners marked for deletion from the * event dispatcher list. */ //非常重要!!分发某个事件,外部调用此函数才会驱动EventDispatcher进行工作。 void dispatchEvent(Event* event); /** Dispatches a Custom Event with a event name an optional user data */ //非常重要!!分发某个自定义事件,外部调用此函数才会驱动EventDispatcher进行工作。 void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr); ///////////////////////////////////////////// /** Constructor of EventDispatcher */ EventDispatcher(); /** Destructor of EventDispatcher */ ~EventDispatcher(); protected: class EventListenerVector { 。。。。。。 }; //一大堆protected函数,不对外开放,后面笔记。 。。。。。。 //一大堆protected成员变量,主要都是map,都是为了服务事件的分发和处理。最复杂的也是这个地方: /** Listeners map */ //储存和管理所有注册的事件响应函数,按照ListenerID进行分组,注意value为EventListenerVector,即相同类型的listenerID的listener也有不同的优先级 std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap; /** The map of dirty flag */ //管理当前ListenerID最近一次注册的listener的flag。 std::unordered_map<EventListener::ListenerID, DirtyFlag> _priorityDirtyFlagMap; /** The map of node and event listeners */ //储存和管理node及与其相关的的listener。 std::unordered_map<Node*, std::vector<EventListener*>*> _nodeListenersMap; /** The map of node and its event priority */ //管理遍历节点树时Node对应的优先级,和_nodePriorityIndex有关。 std::unordered_map<Node*, int> _nodePriorityMap; /** key: Global Z Order, value: Sorted Nodes */ //管理具有相同优先级的Node,这里记录的原因是防止函数返回后当前值丢失。 std::unordered_map<float, std::vector<Node*>> _globalZOrderNodeMap; /** The listeners to be added after dispatching event */ //注册监听器时关联的node,和_dirtyNodes相反,如果处在分发事件函数中,则会进入该vector //事件分发时会将其内容传入_dirtyNodes std::vector<EventListener*> _toAddedListeners; /** The nodes were associated with scene graph based priority listeners */ //注册监听器时关联的node,如果此时正在分发事件函数中,则node不会进入该set,正常状态下注册的graph优先级别的node会进入该set。 //在事件分发时会清空该set std::set<Node*> _dirtyNodes; /** Whether the dispatcher is dispatching event */ //标记EventDispatcher是否正在分发事件。这里是为了防止分发事件时遇到删除自己等异常情况,造成数据混乱。类似于AntionManager int _inDispatch; /** Whether to enable dispatching event */ bool _isEnabled; //用于节点优先级计数。当遍历节点树时,会累加该变量,然后将该值附到对应节点上。 //这里记录的原因是防止函数返回后当前累加值丢失。 int _nodePriorityIndex; //EventDispatcher内部注册的自定义事件,目前只有两个:返回前台和返回后台,这两个事件响应是不能被删除的。及时调用删除所有事件响应函数,也不能把这两个删掉。 //这里额外记录的原因是为了后续的可扩展性,即在这个set中的自定义事件响应是无法被删除的。 std::set<std::string> _internalCustomListenerIDs; };
EventDispatcher.cpp:
由于内容很多,比较复杂。这里作者只笔记下最基本的流程。后续补齐整体的流程。另外,触摸响应部分以后单独拿出来笔记。
#define DUMP_LISTENER_ITEM_PRIORITY_INFO 0 namespace { //类似于stl中的智能指针,利用了类实例离开其作用域后会自动调用析构函数来实现一些特殊的功能,这里的功能是对某个值(_inDispatch)进行增减。。 class DispatchGuard { public: DispatchGuard(int& count): _count(count) { ++_count; } ~DispatchGuard() { --_count; } private: int& _count;//注意这里是引用!!!!! }; } NS_CC_BEGIN //本地方法,用来获取一个Event的名称。这里会根据Event的类型来判断指针属于哪个子类。 //由于touch的类型不唯一,因此不能使用这个方法。 static EventListener::ListenerID __getListenerID(Event* event) { EventListener::ListenerID ret; switch (event->getType()) { case Event::Type::ACCELERATION: ret = EventListenerAcceleration::LISTENER_ID; break; case Event::Type::CUSTOM: { auto customEvent = static_cast<EventCustom*>(event); ret = customEvent->getEventName(); } break; case Event::Type::KEYBOARD: ret = EventListenerKeyboard::LISTENER_ID; break; case Event::Type::MOUSE: ret = EventListenerMouse::LISTENER_ID; break; case Event::Type::FOCUS: ret = EventListenerFocus::LISTENER_ID; break; case Event::Type::TOUCH: // Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce. // return UNKNOWN instead. CCASSERT(false, "Don't call this method if the event is for touch."); break; default: CCASSERT(false, "Invalid type!"); break; } return ret; } EventDispatcher::EventDispatcher() : _inDispatch(0) , _isEnabled(false) , _nodePriorityIndex(0) { _toAddedListeners.reserve(50); // fixed #4129: Mark the following listener IDs for internal use. // Therefore, internal listeners would not be cleaned when removeAllEventListeners is invoked. //EventDispatcher内部注册的自定义事件,目前只有两个:返回前台和返回后台,这两个事件响应是不能被删除的。及时调用删除所有事件响应函数,也不能把这两个删掉。 _internalCustomListenerIDs.insert(EVENT_COME_TO_FOREGROUND); _internalCustomListenerIDs.insert(EVENT_COME_TO_BACKGROUND); } EventDispatcher::~EventDispatcher() { // Clear internal custom listener IDs from set, // so removeAllEventListeners would clean internal custom listeners. _internalCustomListenerIDs.clear(); removeAllEventListeners(); } void EventDispatcher::visitTarget(Node* node, bool isRootNode) { int i = 0; auto& children = node->getChildren(); auto childrenCount = children.size(); //遍历子节点。注意这里的子节点是排好序的。可以参考【 void Node::sortAllChildren() 】 if(childrenCount > 0) { Node* child = nullptr; // visit children zOrder < 0 for( ; i < childrenCount; i++ ) {//首先遍历子节点中Zorder<0的,递归调用visitTarget child = children.at(i); if ( child && child->getLocalZOrder() < 0 ) visitTarget(child, false);//注意这里的第二个参数是false else break; } if (_nodeListenersMap.find(node) != _nodeListenersMap.end()) {//把自己放入Map,key是自己的全局Zorder,value是自己 _globalZOrderNodeMap[node->getGlobalZOrder()].push_back(node); } //继续遍历子节点,剩下的子节点递归调用visitTarget。 for( ; i < childrenCount; i++ ) { child = children.at(i); if (child) visitTarget(child, false);//注意这里的第二个参数是false } } else { if (_nodeListenersMap.find(node) != _nodeListenersMap.end()) { _globalZOrderNodeMap[node->getGlobalZOrder()].push_back(node); } } //当所有的子节点递归调用完成之后,就会回到这里 if (isRootNode) { //将_globalZOrderNodeMap的key取出并且排序。 std::vector<float> globalZOrders; globalZOrders.reserve(_globalZOrderNodeMap.size()); for (const auto& e : _globalZOrderNodeMap) { globalZOrders.push_back(e.first); } std::sort(globalZOrders.begin(), globalZOrders.end(), [](const float a, const float b){ return a < b; }); //遍历刚刚排过序的globalZOrder,根据每个全局Zorder,取出对应的node,并设置它的node的优先级 for (const auto& globalZ : globalZOrders) { for (const auto& n : _globalZOrderNodeMap[globalZ]) { _nodePriorityMap[n] = ++_nodePriorityIndex; } } _globalZOrderNodeMap.clear(); } //这个函数完成之后,当前执行的场景中的所有的节点都放入了_nodePriorityMap中,而且对应的优先级也根据节点的 //父子关系和globalZOrder大小按照顺序累加完成。 //这里需要注意的是节点的globalZOrder的值默认都是0,因此_globalZOrderNodeMap的value是一个vector。 } //暂停与某个节点相关联的listener的响应,和Resume相反。 void EventDispatcher::pauseEventListenersForTarget(Node* target, bool recursive/* = false */) { auto listenerIter = _nodeListenersMap.find(target); if (listenerIter != _nodeListenersMap.end()) { auto listeners = listenerIter->second; for (auto& l : *listeners) { l->setPaused(true); } } for (auto& listener : _toAddedListeners) { if (listener->getAssociatedNode() == target) { listener->setPaused(true); } } if (recursive) { const auto& children = target->getChildren(); for (const auto& child : children) { pauseEventListenersForTarget(child, true); } } } //恢复与某个节点相关联的listener的响应 void EventDispatcher::resumeEventListenersForTarget(Node* target, bool recursive/* = false */) { auto listenerIter = _nodeListenersMap.find(target); //先在map中查一下这个Node是否有listener if (listenerIter != _nodeListenersMap.end()) {//查到了,就把里面的关联的所有的listener全部恢复运行 auto listeners = listenerIter->second; for (auto& l : *listeners) { l->setPaused(false); } } //再查一遍待添加列表,把里面的关联的listener全部恢复运行 for (auto& listener : _toAddedListeners) { if (listener->getAssociatedNode() == target) { listener->setPaused(false); } } //将受到影响的Node的子节点树全部置脏 setDirtyForNode(target); //是否递归子节点做相同处理 if (recursive) { const auto& children = target->getChildren(); for (const auto& child : children) { resumeEventListenersForTarget(child, true); } } } //删除关联到某个node上的listener。 void EventDispatcher::removeEventListenersForTarget(Node* target, bool recursive/* = false */) { // Ensure the node is removed from these immediately also. // Don't want any dangling pointers or the possibility of dealing with deleted objects.. _nodePriorityMap.erase(target); _dirtyNodes.erase(target); //从map中找到与该node相关联的所有的listener,然后调用removeEventListener进行删除。这样可以保证删除的比较干净。 auto listenerIter = _nodeListenersMap.find(target); if (listenerIter != _nodeListenersMap.end()) { auto listeners = listenerIter->second; auto listenersCopy = *listeners; for (auto& l : listenersCopy) { removeEventListener(l); } } //把待添加列表中的与该node有关联的listener也删掉 // Bug fix: ensure there are no references to the node in the list of listeners to be added. // If we find any listeners associated with the destroyed node in this list then remove them. // This is to catch the scenario where the node gets destroyed before it's listener // is added into the event dispatcher fully. This could happen if a node registers a listener // and gets destroyed while we are dispatching an event (touch etc.) for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ) { EventListener * listener = *iter; if (listener->getAssociatedNode() == target) { listener->setAssociatedNode(nullptr); // Ensure no dangling ptr to the target node. listener->setRegistered(false); listener->release(); iter = _toAddedListeners.erase(iter); } else { ++iter; } } //是否级联删除子节点 if (recursive) { const auto& children = target->getChildren(); for (const auto& child : children) { removeEventListenersForTarget(child, true); } } } //将Node与关联到它的listener绑定起来。由于一个Node可以对应多个listener,因此这里的value是个vector。 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); } //和associateNodeAndEventListener相反,把某个listener从和它关联的Node的map中删除出去。 void EventDispatcher::dissociateNodeAndEventListener(Node* node, EventListener* listener) { std::vector<EventListener*>* listeners = nullptr; auto found = _nodeListenersMap.find(node); if (found != _nodeListenersMap.end()) { listeners = found->second; auto iter = std::find(listeners->begin(), listeners->end(), listener); if (iter != listeners->end()) {//找到了就把它删掉 listeners->erase(iter); } //如果这个node已经没有关联的listeners了,就把这个node也去掉。 if (listeners->empty()) { _nodeListenersMap.erase(found); delete listeners; } } } //添加监听器的内部主入口函数。 void EventDispatcher::addEventListener(EventListener* listener) { //如果当前不处于事件分发即程序里,那么直接添加。 if (_inDispatch == 0) { forceAddEventListener(listener); } else//如果当前正处于事件分发即程序正处在某个listener的回调函数中,那么就先把这个监听器放到待添加列表中。 { _toAddedListeners.push_back(listener); } //添加好之后retain一次 防止被销毁。 listener->retain(); } //直接添加某一个Listener void EventDispatcher::forceAddEventListener(EventListener* listener) { //首先根据这个listener的ID查到当前map中是否已经有相同ID的listener,没有就新建一个EventListenerVector来管理。 EventListenerVector* listeners = nullptr; EventListener::ListenerID listenerID = listener->getListenerID(); auto itr = _listenerMap.find(listenerID); if (itr == _listenerMap.end()) { //没有就新建一个 listeners = new EventListenerVector(); _listenerMap.insert(std::make_pair(listenerID, listeners)); } else { //有的话直接返回。 listeners = itr->second; } //将这个listener加入到EventListenerVector中。这里EventListenerVector会根据listener的是否是graphic进行不同的操作。 listeners->push_back(listener); if (listener->getFixedPriority() == 0) { //更新下_priorityDirtyFlagMap,将最近一次注册的listener的flag存起来。 setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY); auto node = listener->getAssociatedNode(); CCASSERT(node != nullptr, "Invalid scene graph priority!"); //更新下_nodeListenersMap,将这个listener关联到其对应的node上。 associateNodeAndEventListener(node, listener); if (node->isRunning()) { resumeEventListenersForTarget(node); } } else { //固定优先级别的listener是没有关联的node的,因此无需更新各种map。 //更新下_priorityDirtyFlagMap,将最近一次注册的listener的flag存起来。 setDirty(listenerID, DirtyFlag::FIXED_PRIORITY); } } //添加一个graphic优先级别的监听器。 void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node) { CCASSERT(listener && node, "Invalid parameters."); CCASSERT(!listener->isRegistered(), "The listener has been registered."); if (!listener->checkAvailable()) return; listener->setAssociatedNode(node);//这里把传入的Node作为listener的关联Node listener->setFixedPriority(0);//graphic优先级必须设置为0 listener->setRegistered(true);//防止再次注册。 addEventListener(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没有关联的Node listener->setFixedPriority(fixedPriority);//设置级别,前边的CCASSERT保证了它不为0 listener->setRegistered(true);//防止重复注册 listener->setPaused(false);//listener默认是可以执行的 addEventListener(listener); } //添加自定义级别监听器。 EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback) { //用事件的名称和回调创造出一个listener,然后作为固定级别传入。优先级为1 EventListenerCustom *listener = EventListenerCustom::create(eventName, callback); addEventListenerWithFixedPriority(listener, 1); return listener; } //删除某个listener。 void EventDispatcher::removeEventListener(EventListener* listener) { if (listener == nullptr) return; bool isFound = false; //首先定义一个Lamada表达式,在vector中找到指定的listener,并且删除。 auto removeListenerInVector = [&](std::vector<EventListener*>* listeners){ if (listeners == nullptr) return; for (auto iter = listeners->begin(); iter != listeners->end(); ++iter) { auto l = *iter; if (l == listener)//在vector中找到了这个listener { CC_SAFE_RETAIN(l); l->setRegistered(false);//先解除注册 if (l->getAssociatedNode() != nullptr)//说明是grahphic级别的。 { //和添加相反,graphic级别的必须把它从其关联的Node节点所在的Map中去除。 dissociateNodeAndEventListener(l->getAssociatedNode(), l); //防止悬挂指针。 l->setAssociatedNode(nullptr); // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes. } //如果当前不在分发函数中,直接删除。 if (_inDispatch == 0) { listeners->erase(iter); CC_SAFE_RELEASE(l); } isFound = true;//设置标志位,找到了 break; } } }; for (auto iter = _listenerMap.begin(); iter != _listenerMap.end();) { auto listeners = iter->second;//这里的listeners是EventListenerVector类型的。 //在EventListenerVector中内部的两个vector中都找一次。 auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners(); //先在graphic优先级中查找一次 removeListenerInVector(sceneGraphPriorityListeners); if (isFound) { // fixed #4160: Dirty flag need to be updated after listeners were removed. setDirty(listener->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY); } else {//在graphic中没找到,就在固定优先级别中再找一次。 removeListenerInVector(fixedPriorityListeners); if (isFound) { setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY); } } //如果该listenerID下的所有的listener全都被删掉了,那么就把这个listenerID也清理出map。 if (iter->second->empty()) { _priorityDirtyFlagMap.erase(listener->getListenerID()); auto list = iter->second; iter = _listenerMap.erase(iter); CC_SAFE_DELETE(list); } else { ++iter; } if (isFound) break; } if (isFound) { CC_SAFE_RELEASE(listener); } else { //如果在EventListenerVector中没有找到,就在待添加列表中查找一下,有的话直接删掉。 for(auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ++iter) { if (*iter == listener) { listener->setRegistered(false); listener->release(); _toAddedListeners.erase(iter); break; } } } } //更新某个listener的优先级。注意这个listener不能是graphic级别的,也不能改为graphic级别。 void EventDispatcher::setPriority(EventListener* listener, int fixedPriority) { if (listener == nullptr) return; for (auto iter = _listenerMap.begin(); iter != _listenerMap.end(); ++iter) { auto fixedPriorityListeners = iter->second->getFixedPriorityListeners(); if (fixedPriorityListeners) { auto found = std::find(fixedPriorityListeners->begin(), fixedPriorityListeners->end(), listener); if (found != fixedPriorityListeners->end()) { CCASSERT(listener->getAssociatedNode() == nullptr, "Can't set fixed priority with scene graph based listener."); if (listener->getFixedPriority() != fixedPriority) { listener->setFixedPriority(fixedPriority); setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY); } return; } } } } //按照优先级别分发事件。 //先分发固定优先级中<0的,在分发graphic优先级(优先级为0),再分发固定优先级>0的。 //对固定优先级进行排序时已经记录了第一个大于0的位置Gt0Index。 void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent) { bool shouldStopPropagation = false; auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners(); ssize_t i = 0; // 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; } } } } } void EventDispatcher::dispatchEvent(Event* event) { if (!_isEnabled) return; updateDirtyFlagForSceneGraph(); //通过局部变量的方式来对_inDispatch进行操作,参考DispatchGuard的构造和析构函数。 DispatchGuard guard(_inDispatch); //如果事件是touch事件,直接分发后返回。 if (event->getType() == Event::Type::TOUCH) { dispatchTouchEvent(static_cast<EventTouch*>(event)); return; } auto listenerID = __getListenerID(event); //对指定的ListenerID下的listener进行排序 sortEventListeners(listenerID); auto iter = _listenerMap.find(listenerID); if (iter != _listenerMap.end()) { //找好对应的EventListenerVector auto listeners = iter->second; //设置好lmaba表达式 auto onEvent = [&event](EventListener* listener) -> bool{ event->setCurrentTarget(listener->getAssociatedNode()); listener->_onEvent(event); return event->isStopped(); }; dispatchEventToListeners(listeners, onEvent); } updateListeners(event); } //分发自定义事件。这里主要是把用户的数据放到事件里传下去。 void EventDispatcher::dispatchCustomEvent(const std::string &eventName, void *optionalUserData) { EventCustom ev(eventName); ev.setUserData(optionalUserData); dispatchEvent(&ev); } void EventDispatcher::dispatchTouchEvent(EventTouch* event) { 。。。。。 // 略,以后笔记 } //当外部注册的事件响应函数完成之后返回了EventDispatcher,此时EventDispatcher并没有完成事件响应函数。 //但是此时外部的事件响应函数完成已经完成,这里就可以刷新下本地数据,而不用担心数据错乱的问题。 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(); } }; //如果事件是触摸,那么会调用两次onUpdateListeners 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."); //干掉已经空出来的_listenerMap 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; } } //把待添加的listener加入到正式的列表中。 if (!_toAddedListeners.empty()) { for (auto& listener : _toAddedListeners) { forceAddEventListener(listener); } _toAddedListeners.clear(); } } void EventDispatcher::updateDirtyFlagForSceneGraph() { if (!_dirtyNodes.empty()) { for (auto& node : _dirtyNodes) { auto iter = _nodeListenersMap.find(node); if (iter != _nodeListenersMap.end()) { for (auto& l : *iter->second) { setDirty(l->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY); } } } _dirtyNodes.clear(); } } //对事件进行排序 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; //如果最后一次对某个ListenerID进行更新时是固定优先级的 if ((int)dirtyFlag & (int)DirtyFlag::FIXED_PRIORITY) { sortEventListenersOfFixedPriority(listenerID); } //如果最后一次对某个ListenerID进行更新时是Graphic级别的 if ((int)dirtyFlag & (int)DirtyFlag::SCENE_GRAPH_PRIORITY) { auto rootNode = Director::getInstance()->getRunningScene(); if (rootNode) { sortEventListenersOfSceneGraphPriority(listenerID, rootNode); } else { dirtyIter->second = DirtyFlag::SCENE_GRAPH_PRIORITY; } } } } //graphic优先级的listener进行排序 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; //先把优先级和Map清理干净 // Reset priority index _nodePriorityIndex = 0; _nodePriorityMap.clear(); //核心函数,注意这里的第二个参数是true visitTarget(rootNode, true); // After sort: priority < 0, > 0 std::sort(sceneGraphListeners->begin(), sceneGraphListeners->end(), [this](const EventListener* l1, const EventListener* l2) { return _nodePriorityMap[l1->getAssociatedNode()] > _nodePriorityMap[l2->getAssociatedNode()]; }); #if DUMP_LISTENER_ITEM_PRIORITY_INFO log("-----------------------------------"); for (auto& l : *sceneGraphListeners) { log("listener priority: node ([%s]%p), priority (%d)", typeid(*l->_node).name(), l->_node, _nodePriorityMap[l->_node]); } #endif } //固定优先级的listener进行排序 void EventDispatcher::sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID) {//先获取到与该listenerID有关的EventListenerVector auto listeners = getListeners(listenerID); if (listeners == nullptr) return; //对立面的固定优先级的listener进行排序 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 int index = 0; for (auto& listener : *fixedListeners) { if (listener->getFixedPriority() >= 0) break; ++index; } //排好序之后记录下大于0的第一个数据的位置 listeners->setGt0Index(index); } EventDispatcher::EventListenerVector* EventDispatcher::getListeners(const EventListener::ListenerID& listenerID) { auto iter = _listenerMap.find(listenerID); if (iter != _listenerMap.end()) { return iter->second; } return nullptr; } //移除某种类型的所有的listener,可以参考removeEventListener函数。 void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID) { auto listenerItemIter = _listenerMap.find(listenerID); if (listenerItemIter != _listenerMap.end()) { auto listeners = listenerItemIter->second; auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners(); auto removeAllListenersInVector = [&](std::vector<EventListener*>* listenerVector){ if (listenerVector == nullptr) return; for (auto iter = listenerVector->begin(); iter != listenerVector->end();) { auto l = *iter; l->setRegistered(false); if (l->getAssociatedNode() != nullptr) { dissociateNodeAndEventListener(l->getAssociatedNode(), l); l->setAssociatedNode(nullptr); // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes. } if (_inDispatch == 0) { iter = listenerVector->erase(iter); CC_SAFE_RELEASE(l); } else { ++iter; } } }; removeAllListenersInVector(sceneGraphPriorityListeners); removeAllListenersInVector(fixedPriorityListeners); // Remove the dirty flag according the 'listenerID'. // No need to check whether the dispatcher is dispatching event. _priorityDirtyFlagMap.erase(listenerID); if (!_inDispatch) { listeners->clear(); delete listeners; _listenerMap.erase(listenerItemIter); } } for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end();) { if ((*iter)->getListenerID() == listenerID) { (*iter)->setRegistered(false); (*iter)->release(); iter = _toAddedListeners.erase(iter); } else { ++iter; } } } //删掉指定类型下的所有的listener void EventDispatcher::removeEventListenersForType(EventListener::Type listenerType) { if (listenerType == EventListener::Type::TOUCH_ONE_BY_ONE) { removeEventListenersForListenerID(EventListenerTouchOneByOne::LISTENER_ID); } else if (listenerType == EventListener::Type::TOUCH_ALL_AT_ONCE) { removeEventListenersForListenerID(EventListenerTouchAllAtOnce::LISTENER_ID); } else if (listenerType == EventListener::Type::MOUSE) { removeEventListenersForListenerID(EventListenerMouse::LISTENER_ID); } else if (listenerType == EventListener::Type::ACCELERATION) { removeEventListenersForListenerID(EventListenerAcceleration::LISTENER_ID); } else if (listenerType == EventListener::Type::KEYBOARD) { removeEventListenersForListenerID(EventListenerKeyboard::LISTENER_ID); } else { CCASSERT(false, "Invalid listener type!"); } } //删掉自定义类型的listener void EventDispatcher::removeCustomEventListeners(const std::string& customEventName) { removeEventListenersForListenerID(customEventName); } //删掉所有的listener,注意不能删除内部的自定义【 _internalCustomListenerIDs 】的listener void EventDispatcher::removeAllEventListeners() { bool cleanMap = true; std::vector<EventListener::ListenerID> types(_listenerMap.size()); for (const auto& e : _listenerMap) { if (_internalCustomListenerIDs.find(e.first) != _internalCustomListenerIDs.end()) { cleanMap = false; } else { types.push_back(e.first); } } for (const auto& type : types) { removeEventListenersForListenerID(type); } if (!_inDispatch && cleanMap) { _listenerMap.clear(); } } void EventDispatcher::setEnabled(bool isEnabled) { _isEnabled = isEnabled; } bool EventDispatcher::isEnabled() const { return _isEnabled; } void EventDispatcher::setDirtyForNode(Node* node) { // Mark the node dirty only when there is an eventlistener associated with it. if (_nodeListenersMap.find(node) != _nodeListenersMap.end()) { _dirtyNodes.insert(node); } // Also set the dirty flag for node's children const auto& children = node->getChildren(); for (const auto& child : children) { setDirtyForNode(child); } } //更新_priorityDirtyFlagMap,将最近一次注册的listener的flag存起来。 void EventDispatcher::setDirty(const EventListener::ListenerID& listenerID, DirtyFlag flag) { auto iter = _priorityDirtyFlagMap.find(listenerID); if (iter == _priorityDirtyFlagMap.end()) { _priorityDirtyFlagMap.insert(std::make_pair(listenerID, flag)); } else { int ret = (int)flag | (int)iter->second; iter->second = (DirtyFlag) ret; } } NS_CC_END
发表评论