欢迎光临散文网 会员登陆 & 注册

godot gui_input event处理机制

2023-07-21 23:17 作者:JACKADUX  | 我要投稿

在这里记录并分享一下 godot 的 gui 中 event 是如何被传递和处理的 。

简单设置如下图场景,并使用同一个脚本用于在鼠标左键点击时捕获对应信息。

事件处理函数

godot主要有三种事件处理函数 input(), gui_input(), unhandled_input()
并且会依次按照 input() -> gui_input() -> unhandled_input() 的顺序执行, 即所有对象执行完 input() 后才会调用 gui_input(),所有对象 gui_input() 判定结束后再调用 unhandled_input()。
==在事件处理代码中使用 accept_event() 会强制停止事件继续传递。==

注意:gui_input() 方法是 Control 对象的方法,而 input() 和 unhandled_input() 都是 Node 对象的方法。(Control 继承自 Node)。
逻辑上其他 Node 对象虽然没有gui_input() 方法,但用 input()方法可以拦截传往 Control 的事件(通过accept_event())进而阻止 gui_input() 的调用,
所以官方推荐在非 Control 节点中使用 unhandled_input() 而非 input()方法。

1. input()

反向遍历所有节点。

测试:在空白处点击鼠标查看 Input 函数的执行结果

# 打印出来的结果Input : P4-Blue Input : P3-Green Input : P2-Red Input : P1-White Input : Root

可以看到事件是从节点树的根部依次向上传递的,P4 -> P3 -> P2 -> P1 -> Root 。
==gui_input() 和 unhandled_input() 的执行顺序也是如此。==

2. gui_input()

gui_input() 就开始变的稍微复杂了。
不像input() ,并不是所有对象都会调用 gui_input()。
是否调用 gui_input() 由 mouse_filter 属性决定的,并且 触发事件时 鼠标位置必须在对象范围内部 ( ’触发事件时‘ 这个前提很重要,因为鼠标不在区域内也有可能调用 gui_input(),下面会讲到 )。

mouse_filter 有三个值分别为:
Stop: 事件在当前节点调用 gui_input() 后停止继续传递。
Pass: 当事件可以传递到当前对象,调用 gui_input() 之后再将事件上传给父级处理。
注意:这里是直接传给父级,在事件被处理前会一层一层向上传直到节点树的 Root 对象
Ignore: 无视当前对象,gui_input()不会被调用。

个人感觉这里面 Pass 最容易翻车,通过测试来说明。
测试:蓝色(P4) mouse_filter 改成 Pass, 其余全部改成Stop, 点击蓝色(P4)和白色(P1)相叠加的区域(下图中的红色叉位置),事件是怎么传递的呢?

# 打印出来的结果Input : P4-Blue Input : P3-Green Input : P2-Red Input : P1-White Input : Root  gui_input : P4-Blue  mouse_filter: Pass  gui_input : P3-Green  mouse_filter: Stop

在我一开始的想法里既然蓝色Pass了那应该是白色接受这个事件,但Pass的作用不是穿透对象而是在调用 gui_input() 后直接把事件传递给父级(P3 绿色)判定。
父级是Stop所以调用父级的gui_input后直接停止传递。
如果我把父级(P3 绿色)也改成Pass呢?答案是显而易见的,P4 蓝色 -> P3 绿色 -> Root ,事件最终转交给Root。
当事件没有被任何 gui_input() 使用时事件开始传递到 unhandled_input () 中。

注意: Clip Contents会影响事件的捕获。

3. unhandled_input

unhandled_input() 就非常简单了。只有事件没有被任何 input() 或者 gui_input() 消费(accept_event() 或者在 gui_input() 中被 stop),unhandled_input()才会开始执行 。

如有错误或者更多有用的内容,欢迎其他朋友补充指正~


godot gui_input event处理机制的评论 (共 条)

分享到微博请遵守国家法律