cocosCreator 事件系统
概述:
DOM的输入事件通过CCInputManager转化成cocos的输入事件,由CCEventManager 分发给监听器。
监听器在通过回调函数(begin/move/end/cancel)告知事件派发对象(eventTarget)派发事件。
重要类:
event:事件信息对象,主要有触摸信息、鼠标信息、键盘信息等。
eventTarget: 是一个事件派发的对象,有注册,删除和派发等功能,等同于订阅-发布模式。
eventListener:是一个事件监听器的对象,主要用于创建触摸、鼠标、键盘等监听器。包含了类型、回调函数、优先级等。
eventManager:是一个管理监听器的类,主要是对监听器进行排序、分发等。
eventManager
属性:
了解属性可以很好的知道这个类都有做了那些操作,结合函数可以知道是监听器的存储方式,划分监听器的,对监听器都会做什么处理。
_listenersMap: {}, //key:listenerID value:_EventListenerVector_priorityDirtyFlagMap: {},//用来存储所有脏数据标记位的事件监听器,key:listenerID value:boolean_nodeListenersMap: {},//key:node._id,value:listeners[] 存储节点的所有事件监听器_toAddedListeners: [],//存储将要添加的事件监听器_toRemovedListeners: [],//存储将要删除的事件监听器_dirtyListeners: {},//key:listenerID value: boolean_inDispatch: 0,//是否正在处理事件分派标记。 0 表示没有正在处理分派事件_isEnabled: false,//事件管理器是否开启_currentTouch: null,//当前正在处理的触摸事件对象_currentTouchListener: null,//当前正在处理的事件监听器对象_internalCustomListenerIDs: [],//用来存储自定义事件监听器ID
实现功能描述:
- 该类是监听器的管理者,因事件监听器有多种类型(总共五个),因此会对每种类型进行管理。
- 因事件监听器有触发的先后,所以在对事件监听器管理的时候加入了优先级概念。分为固定优先级、场景图优先级(渲染顺序)。
所以每种事件监听器类型,都有下列存储结构是:
_listenersMap:
- _fixedListeners 用于存储固定优先级的监听器(自定义监听器的优先级)
- _sceneGraphListeners 用于存储场景图优先级的监听器(就是node的)
- gtOIndex 用于标记固定优先级小于大于0的界限索引值。因为场景图优先级默认等于0,自定义优先级可=0
事件监听器触发顺序如下:
- 自定义优先级 priority<0
- 场景图优先级 listener 触发
- 自定义优先级 priority>=0的listener 最后触发。(gtOIndex的索引等于排序后监听器的priority等于0时在数组中的索引。)
自定义优先级时,priority值越小,优先级越高,值越小,优先级越低。场景图优先级_localZOrder越大,优先级越高。反之优先级越低。
-
为了可以管理节点上所有的事件监听器,有一个以下数据结构
_nodeListenersMap:
该数据存储着节点的所有类型的监听器,方便对节点上的所有监听器进行选择性的暂停、恢复、删除等功能。
在分发事件监听器时有个很重要的排序过程,其目的为了确定事件监听器的触发先后顺序。具体过程如下:
与排序相关的几个属性:
- _priorityDirtyFlagMap:这个map映射存储的是事件监听器类型与脏标记的映射。key=ListenerID;value=dirtyFlag;
- _dirtyListeners:暂时记录了有新的场景图优先级的监听器添加,或者是恢复了被暂停的监听器。key=Listener; value=boolean;
因为每种监听器都有固定优先级和场景图优先级之分。如果有新的事件监听器添加或者恢复,都会影响到新监听器相同类型的map数据排序顺序。
所以在每次dispatch的之前,都会对脏数据进行更新,暂时标记那种类型的监听器脏了。在具体的分发之前,会依据标记进行重新排序后再分发。
排序完成之后,_priorityDirtyFlagMap的value值都会标记位非脏数据。
同时有个optimize 点,只在真正分发时,进行一次排序,并非在加入监听器或恢复监听器时排序。
另外需要注意的是,节点的zIndex值被修改后,不单单影响渲染顺序,同时也会影响监听器的分发优先级。(sortAllchildren)
监听器的排序代码解析
- 自定义优先级排序算法就是根据设置的priority进行升序排序。priority 数值越小,越早被分发。
- 以下是场景图优先级的降序排序算法,层级越高,越早触发,与自定义优先级相反。
其主要考虑的问题又如下几个:1,祖父孙关系。2,非同父关系。3,同父关系
/**
sort的compare函数。降序
compare(a,b){if(a>b)return -1;if(a<b)return 1;return 0;
}
**/
_sortEventListenersOfSceneGraphPriorityDes: function (l1, l2) {let node1 = l1._getSceneGraphPriority(),node2 = l2._getSceneGraphPriority();//此l1优先if (!l2 || !node2 || !node2._activeInHierarchy || node2._parent === null)return -1;//l2 优先else if (!l1 || !node1 || !node1._activeInHierarchy || node1._parent === null)return 1;/**1,如果是祖孙关系节点,则层级较浅的节点a会在查询一圈之后与层级较深节点b同时汇合在自己初始位置2,如果是非祖孙关系节点,与上述一致,层级较浅的节点a优先到达"祖父"节点为空,到达后从深层级节点初始位置开始最终循环d-s后,ab的祖父节点相同。3,如果是同父节点 直接退出循环总次数计算:node1循环次数为空次数等于a,node2循环次数为空次数等于bconst max = Math.max(a,b);const min = Math.max(a,b);第一次循环min次之后,其中一个节点开始从另一个节点的起始位置开始。接着在循环(max-min)次之后,较深节点会再循环一个差值之后与层级浅的节点 有着共同的祖父节点。总循环次数等于 max。**/let p1 = node1, p2 = node2, ex = false;while (p1._parent._id !== p2._parent._id) {p1 = p1._parent._parent === null ? (ex = true) && node2 : p1._parent;p2 = p2._parent._parent === null ? (ex = true) && node1 : p2._parent;}//node1 与node2 是祖父孙关系,//同祖父孙关系,较浅的节点a会一圈之后在自己初始位置与较深节点b重合。if (p1._id === p2._id) {if (p1._id === node2._id)// p1不等于node1(l1),p1比较深 l1优先return -1;if (p1._id === node1._id)//p1等于node1,p1比较浅,l2优先return 1;}//到这一步已经确定不是祖孙关系了,那就存在 同父或不同父//1,ex=true;p1与p2 是不同父节点,直接对比节点_localZOrder。//2,ex=false; 是同父节点,因为降序所以反向减return ex ? p1._localZOrder - p2._localZOrder : p2._localZOrder - p1._localZOrder;}
这里需要注意的是:_localZOrder 与zIndex、siblingIndex 区别
- _localZOrder 是一个32位的数字,前16存储着zIndex节点顺序,后16位存储着子节点相对于在父节点下的索引位置。
- 渲染顺序由_localZOrder 决定,节点排序是比较_localZOrder值进行升序排序。
- _localZOrder 前16位存储的是zIndex,后16位存储的事siblingIndex(setSiblingIndex)。
- zIndex权重比siblingIndex大,如果zIndex 相同,渲染顺序由siblingIndex决定。反之如果修改了zIndex,再次修改siblingIndex毫无效果。
- 修改zIndex时,_localZOrder值是在下一帧才会改变,当前帧并不会改变。
在事件监听器触发的过程中,可能会添加新的监听器或者删除监听器。因此有了下列属性
_toAddedListeners:当在添加新的监听器时,遇到正在触发事件监听器时,新的监听器或暂存在该数组中。
_toRemovedListeners:当在添加新的监听器时,遇到正在触发事件监听器时,新的监听器或暂存在该数组中。
_inDispatch:正在分发时>1; 不在分发时=0;
什么时候这些暂存的数据与总数据合并呢?每帧的时候都会去检测是否有暂存数据存在,如果有则与总数据合并(即添加、删除)。
监听器的吞噬与不吞噬,监听的的吞噬情况由三种条件控制
- 事件的stopPropagation、stopPropagationImmediate 如果事件设置了停止派发,则监听器的不吞噬也会暂停,其他监听器也不会接受到信息。
- 节点的hitTest 返回值 与 监听器的 swallowTouches 值设置。
- swallowTouches=true;吞噬 只会分发到自身监听器其他监听器不会被分发。
- swallowTouches=false; 不吞噬 下一个监听器也会被分发 依次循环, 直到有一个监听器设置吞噬才不会往下传
参考代码:_dispatchEventToListeners,shouldStopPropagation
eventManager 分发流程
CCEvent、CClistener、event-target
相关文章:

cocosCreator 事件系统
概述: DOM的输入事件通过CCInputManager转化成cocos的输入事件,由CCEventManager 分发给监听器。 监听器在通过回调函数(begin/move/end/cancel)告知事件派发对象(eventTarget)派发事件。 重要类: event࿱…...
刷题_20:字符串反转 and 公共子串计算
一.字符串反转 题目链接: 字符串反转 题目描述: 接受一个只包含小写字母的字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000) 输入描述: 输入一行,为一个只包含小写字母的字符串…...

如何在 Linux 命令行中比较两个目录,我教你五个命令!
在 Linux 命令行中比较两个目录是一项常见的任务,特别是当你需要确保两个目录之间的文件完全相同时。在本文中,我们将介绍一些在 Linux 命令行中比较两个目录的方法。 方法一:使用 diff 命令比较两个目录 diff 命令可以比较两个文件或目录之…...

多元算力如何满足万千本土化场景需求,解析第四代至强核心加速器设计
作者 | 宋慧 出品 | CSDN 云计算 2023 年初,英特尔重磅发布了企业级芯片领域重要的产品——第四代英特尔 至强 可扩展处理器。当时报道中,我们就重点提到了其中重要的七大内置加速器,这也是英特尔为千行百业多种创新场景去提供算力支持的底气…...
SPI主模式切换为从模式
一、SPI主模式切换为从模式在SPI总线上,要将主设备转换为从设备或者将从设备转换为主设备,需要通过改变SPI控制寄存器的配置来实现。下面分别介绍SPI主模式切换为从模式的步骤:配置从设备的SPI控制寄存器首先需要配置从设备的SPI控制寄存器。…...

IMX6ULL学习笔记(21)——MMDC接口使用(DDR3测试)
一、MMDC简介 MMDC 接口与 STM32 的 FSMC 接口类似,只不过 MMDC 接口专用于外接 DDR,并且 MMDC 外部引脚不复用。MMDC 是一个多模的 DDR 控制器,可以连接 16 位宽的 DDR3/DDR3L、16 位宽的 LPDDR2。 MMDC 是一个可配置、高性能的 DDR 控制器。…...
机器学习——无监督学习
机器学习的分类一般分为下面几种类别:监督学习( supervised Learning )无监督学习( Unsupervised Learning )强化学习( Reinforcement Learning,增强学习)半监督学习( Semi-supervised Learning )深度学习(Deep Learning)Python Scikit-learn. http: // …...

python+opencv生成较真实的车牌号码图片
本文参考github代码:https://github.com/loveandhope/license-plate-generator 效果: 一、代码目录结构: background目录下存放各种背景图片 font目录下存放车牌中文、字符的ttf字体 images目录下存放蓝色底牌、新能源绿色底牌、污渍&#…...
3.26周报
周报 代码行数: 周一 581 周二 601 周三 615 周四 591 周五 570 周六 561 周日 577 遇到的问题: 项目启动很慢,要将近5分钟才能开启项目,对开发造成很大困扰。 断点打在奇怪的地方,造成启动缓慢。断点…...
从0开始学python -69
Python math 模块 Python math 模块提供了许多对浮点数的数学运算函数。 math 模块下的函数,返回值均为浮点数,除非另有明确说明。 如果你需要计算复数,请使用 cmath 模块中的同名函数。 要使用 math 函数必须先导入: import…...
HashMap中HashCode的实现原理
代码 static final int hash(Object key) {int h;return (key null) ? 0 : (h key.hashCode()) ^ (h >>> 16);}1. h >>> 16 是什么,有什么用? h是hashcode。h >>> 16是用来取出h的高16,(>>>是无符号右移) 如下展…...

Redis —Set、ZSet介绍和应用场景
Set 概念 Redis的set是一个不重复、无序并唯一的键值集合。(方便管理无序集合)它支持交集、并集、差集等等 set和list区别 List 可以存储重复元素,Set 只能存储非重复元素;List 是按照元素的先后顺序存储元素的,而…...

【产品人卫朋】内容运营:文章点击量少的可怜,该怎么做?
今天来谈谈内容运营这个话题。 随着自媒体进入视播时代,也就是短视频的时代。 无论你打开任何一个短视频应用,每一个主题下面都会有成千上万个视频。 最为致命的是,大家停留的时间也越来越短了。 如果你不能在2秒的时间内吸引眼球,…...

【K8S系列】深入解析无状态服务
目录 序言 1. 无服务介绍 1.1 优点 1.2 使用场景 1.3 资源类型 1.4 总结 2 使用介绍 2.1 Deployment 使用场景: 2.2 ReplicaSet 使用场景 2.3 pod Pod 资源定义示例 2.4 service 创建一个Deployment: 创建一个Service: 总结…...
Node基础--命令窗口
1.Windows命令行窗口(叫做:小黑屏、cmd窗口、终端、shell) (1).如何打开命令行窗口 开始菜单 -- 运行 --- cmd --- enter win R -- cmd --- enter (2).cmd窗口常用指令 dir 列出当前目录下的所有文件 cd 目录名 进入到指定的目录 md 目录名 …...
一些有趣的项目
一个支持交互的展示卷积过程的可视化工具 https://github.com/pwwang/cnn-convoluter 一款简单易用基于 Python scikit 的推荐系统https://github.com/NicolasHug/Surprise 一个封装了 7 种启发式算法的 Python 代码库。分别是:差分进化算法、遗传算法、粒子群算法…...

教你精通JavaSE语法之第六章、数组的使用
一、数组的定义与使用 😁1.1数组的概念📌数组:可以看成是相同类型元素的一个集合。在内存中是一段连续的空间,可以同来存储同种数据类型的多个值。但是数组容器在存储数据的时候,需要结合隐式转换考虑。比如࿱…...

基于51单片机AT89C51的小型音乐喷泉控制系统设计
wx供重浩:创享日记 对话框发送:单片机小喷泉 获取完整无水印论文报告(内含电路原理图和程序) 根据目前音乐喷泉的发展现状,介绍了一个以AT89C51单片机为核心的小型音乐喷泉控制系统。给出了一个简洁的单片机控制电路&a…...

【Nacos】Nacos原理详解(注册中心,配置中心)
文章目录一、背景二、CAP理论三、什么是NacosNacos 服务注册需要具备的能力:Nacos的实现原理:四、Nacos原理Nacos 服务注册与订阅的完整流程服务领域模型五、注册中心原理六、配置中心原理七、Nacos 的关键特性包括:八、 面试分析一、背景 服务注册中心…...

蓝桥杯刷题冲刺 | 倒计时11天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.质因子2.蓝桥王国1.质因子 题目 链接: 1545. 质因子 - AcWing题库 给定一个整数 N…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...