‎Cocos2d-x 学习笔记(15.1) EventDispatcher

摘要:
EventDispatcher管理侦听器并围绕它们工作。建立关联并调用associateNodeAndEventListener方法。在nodeListenersMap中,找到键为node的侦听器容器,并为容器中的每个侦听器执行removeEventListener。

EventDispatcher对监听器进行管理,围绕着监听器工作。可以添加、删除、暂停/恢复监听器、分发事件到监听器。

1. 一些成员

    /** 把ListenerID和同ID监听器的容器对应 */
    std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
    
    /** 把listenerID的对应的DirtyFlag*/
    std::unordered_map<EventListener::ListenerID, DirtyFlag> _priorityDirtyFlagMap;
    
    /** 把node和其监听器对应 key:node, value:存储监听器的容器 */
    std::unordered_map<Node*, std::vector<EventListener*>*> _nodeListenersMap;
    
    /** key: node, value: node优先级 */
    std::unordered_map<Node*, int> _nodePriorityMap;
    
    /** key: Global Z Order, value: 同gzorder排序好的node*/
    std::unordered_map<float, std::vector<Node*>> _globalZOrderNodeMap;
    
    /** 存储待添加的监听器 The listeners to be added after dispatching event */
    std::vector<EventListener*> _toAddedListeners;

    /** 存储待删除的监听器 The listeners to be removed after dispatching event */
    std::vector<EventListener*> _toRemovedListeners;

    /** 被脏标记的node */
    std::set<Node*> _dirtyNodes;

2. 添加监听器:

2.1 添加和场景图优先级一致的监听器 addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)

参数是监听器、关联的node。监听器优先级自动设为0。

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第1张

2.2 添加自定优先级的监听器 addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)

参数是监听器、监听器优先级。监听器优先级自定义,不能为0。

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第2张

两个添加监听器方法都执行了listener->checkAvailable(),在对监听器设置一些成员变量后,调用了addEventListener(listener),下面看addEventListener方法:

2.3.1 addEventListener

该方法用于当分发器正在分发事件时,把监听器用待添加容器存储,而不是直接加到对应的监听器容器里。因为分发事件需要遍历监听器容器,此时不应对容器修改。‎Cocos2d-x 学习笔记(15.1) EventDispatcher第3张

当分发器没有分发时,调用forceAddEventListener(listener)方法:

2.3.2 forceAddEventListener

该方法是把监听器直接添加到监听器容器的核心方法。容器是_listenerMap,监听器ID为key,容器Vector为value。同ID的监听器被统一存储。Vector又包含了两个vector容器,根据监听器优先级是否为0存入不同vector里。

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第4张

监听器优先级为0时,还要用容器建立node和监听器的关联,用容器方便其他方法获取node的所有监听器。建立关联调用associateNodeAndEventListener方法。

2.3.3 associateNodeAndEventListener

用容器_nodeListenersMap存储node关联的所有监听器。

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第5张

2.4 添加自定义监听器addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback)

参数是事件ID、回调函数。优先级自动设为1。

通过ID和回调函数建立自定义监听器对象,调用向容器添加自定优先级监听器方法,把监听器对象加入监听器容器中。

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第6张

_onCustomEvent是我们指定的回调函数,_onEvent是本方法自动设置的对_onCustomEvent调用的函数,参数为分发到的事件event。

3. 删除监听器

3.1 删除指定的监听器 removeEventListener(EventListener* listener)

如果监听器在待删除容器中,直接从容器中删除。否则,在_listnerMap中遍历查找指定的监听器进行删除,分发器分发事件时,暂缓删除。

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第7张

‎Cocos2d-x 学习笔记(15.1) EventDispatcher第8张

dissociateNodeAndEventListener方法,将参数node和参数监听器建立的关联,在容器_nodeListenersMap中删除。

3.2 删除指定类型的监听器 removeEventListenersForType(EventListener::Type listenerType)

该方法对参数listenerType进行判断,再调用removeEventListenersForListenerID,参数为相应监听器类型的LISTENER_ID。

被调用的removeEventListenersForListenerID方法,简要的说,是从_listenerMap查找ID对应的Vector,对Vector的两个存储监听器的容器都清空。清空的操作包括对每个监听器setRegistered(false),删除监听器和node之间的关联,执行release()。之后,删除Vector,还要从_listenerMap中删除。最后,还要从_toAddedListeners容器里删除可能存在的ID监听器。

3.3 删除指定node关联的监听器removeEventListenersForTarget(Node* target, bool recursive/* = false */)

参数为:指定的node,recursive。recursive为true,关联到node子节点的监听器也会被删除,为false则只删除与node关联的。

该方法,简要的说,首先对两个以node为key的容器_nodePriorityMap和_dirtyNodes删除key为node的entry。

再从_nodeListenersMap中找到key为node的监听器容器,对容器中每个监听器执行removeEventListener(EventListener* listener)。

另外,还要在_toAddedListeners中查找有无关联到node的监听器,如有要删除监听器,执行release()。

如果参数recursive为true,对node的所有子节点调用本方法。

3.4 删除指定ID的监听器 removeCustomEventListeners(const std::string& customEventName)

调用了removeEventListenersForListenerID(customEventName)。

3.5 删除所有监听器 removeAllEventListeners()

先获取_listenerMap中所有ID,再调用removeEventListenersForListenerID(type)删除每个ID(type)的监听器。

3.6 删除指定ID的监听器 removeEventListenersForListenerID(listenerID)

先从_listenerMap中获取ID对应的两个监听器容器,再对每个容器的每个监听器setRegistered(false)、删除与node的关联,当没有事件分发时,从容器中删除并执行release(),有事件分发时,在分发事件方法的updateListeners中删除监听器。对_listenerMap中该entry删除。最后还要在_toAddedListeners查找删除对应的监听器。

4. 暂停与恢复监听器

pauseEventListenersForTarget(Node* target, bool recursive/* = false */)

resumeEventListenersForTarget(Node* target, bool recursive/* = false */)

都是对监听器执行setPaused,设置_paused变量。恢复时对node设置脏标记。

5. 进行事件分发 dispatchEvent(Event* event)

这篇文章:事件分发机制

免责声明:文章转载自《‎Cocos2d-x 学习笔记(15.1) EventDispatcher》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【fcntl系统调用】bind函数(c++11)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

nvm安装

使用nvm安装nodeJS之后,node -v命令可以正常使用,但是npm命令一直报“npm不是内部命令”的错误 安装步骤 nvm 安装nvm 下载nvm https://github.com/coreybutler/nvm-windows/releases ,从中选一个版本下载解压并且安装 1、windows用户选择直接安装的nvm-setup.zip版...

css选择器优先级

CSS三大特性—— 继承、 优先级和层叠。继承:即子类元素继承父类的样式; 优先级:是指不同类别样式的权重比较; 层叠:是说当数量相同时,通过层叠(后者覆盖前者)的样式。 css选择符分类   首先来看一下css选择符(css选择器)有哪些? 1.标签选择器(如:body,div,p,ul,li)2.类选择器(如:class="head",class="h...

k8s记一次kubelet启动后master无法获取node信息

  k8s的node启动kubelet后再master端获取不到   node的日志/var/log/messages报错如下 failed to ensure node lease exists, will retry in 7s, error: leases.coordination.k8s.io "172.16.20.227" is forbidde...

postgresql-slony-I同步复制配置步骤

主数据库: 172.16.254.21 端口:5432 从数据库: 172.16.254.22 端口:5432 步骤1:主从均安装slon apt-get install slon-bin 步骤2:主从数据库配置权限,创建语言。 在主数据库中   vi /etc/postgresql/8.3/node/pg_hba.conf 添加一条记录    host ...

VSCode 启动 Vue 项目 npm install 报错

1. 报错后,查看了版本。 查看node版本:node -v 查看npm版本:npm -v 查看Augular版本:ng --version 2. 感觉 Augular CLI版本太低,使用以下方法升级到最新版本: 》 npm uninstall -g @angular/cli 》 npm cache verify (或 npm cache clean -...

Cocos2dx 多线程

多-threaded负荷plist特征。获取知识的必要性: 1.多线程开启:pthread 2.怎样在线程中载入plist 一.多线程开启 当我们想在程序中开多线程中。第一想到的是cocos2d-x有没有自带方法。幸运的是我们找到了CCThread,不幸却发现里面什么都没有。 cocos2d-x自带了一个第三方插件--pthread,在cocos2dx...