| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 【UE·底层篇】Slate源码分析——点击事件的触发流程梳理 -> 正文阅读 |
|
[游戏开发]【UE·底层篇】Slate源码分析——点击事件的触发流程梳理 |
我们都知道Slate是UE4的UI底层框架。但是UE4的UMG和Unity的UGUI比起来还是有很多不足,所以在实际开发的过程中经常需要对Slate进行改造。本文将带大家由浅入深地阅读Slate源码里关于点击事件相关的部分。 基础知识回顾SetFocusSetFocus是UWidget类里面的方法,最终会调用到FSlateApplication的SetUserFocus方法。SetFoucs顾名思义,就是设置聚焦,当widget获得聚焦或失去聚焦时会触发相关事件。功能说明如图,首先有两个面板A和B,按下A的按钮时调用A面板的SetFocus,按下B的按钮时调用B面板的SetFocus。 游戏运行,按下A的按钮,Focus相关事件调用顺序如下:
此时再按下B的按钮,Focus相关事件调用顺序如下:
注意SetFocus并不会引起改变任何widget的响应功能,这点和等会要提的CaptureMouse有很大不同。 CaptureMouseCaptureMouse是FReply里的方法,参数为TSharedRef,用于锁定某个Widget。调用CaptureMouse后整个游戏将只能和锁定的Widget进行响应,该Widget的父级和子级也是不能响应的,直到调用ReleaseMouseCapture。(需要注意的是如果在ue4编辑器下调用了CaptureMouse,那编辑器自己的按钮也是不能响应的。) FakingTouch在ue4里,鼠标点击和Touch(移动设备的触屏)是两种不同的操作。为了在编辑器下模拟Touch,通常会勾选ProjectSettings里的UseMouseForTouch。这个情况下要想判断是真正的Touch还是模拟的Touch,可以调用FSlateApplication的IsFakingTouchEvents。 FPointerEventFPointerEvent 点输入事件类, 用于处理鼠标以及移动设备的触摸按键,继承自FInputEvent输入事件类。 PreviewMouseButtonDownPreviewMouseButtonDown事件的调用时机在MouseButtonDown和TouchStart前面,和其他事件不同的地方是它是从后往前遍历的。如图,B面板在A面板上面,两个面板都接入了OnMouseButtonDown事件并且都返回Handle,同时A面板接入了PreviewMouseButtonDown事件也返回FReply::Handle。 运行游戏,点击B面板,结果为:
调用栈总览下面以UserWidget为例,看一下它的TouchStart事件在PC上的调用流程。 首先是平台层,根据不同的硬件设备和操作系统调用不同平台的API。window平台调用的是WindowsApplication类。在这个类里面会接受玩家输入,判断玩家输入类型,最终来到Slate层的SlateApplication的OnMouseDown并且传入玩家输入相关的数据。 OnMouseDown判断了一下是FakingTouch,接着调用了OnTouchStarted。 ProcessTouchStartedEvent调用了SlateUser的NotifyTouchStarted,这里面会记录每根手指头的Touch位置信息。然后调用ProcessMouseButtonDownEvent。
RoutePointerDownEvent最后也会调用FEventRouter::Route。 FEventRouter::Route里则会调用SWidget的OnTouchStarted。SWidget是SObjectWidget的基类,OnTouchStated里面默认不会做任何事情。SObjectWidget重写了OnTouchStarted,最终调用了UserWidget的NativeOnTouchStarted。 这里面最复杂且最核心的三个方法为ProcessMouseButtonDownEvent、RoutePointerDownEvent以及FEventRouter::Route,后面将进行更深入的分析。 Slate中几个重要类的含义在细读源码之前,还需要把几个重要类的概念搞明白。 FSlateUserSlateUser用于处理每个玩家的输入。对于手游来说,SlateUser只有一个。对于主机和PC游戏来说,本地每多一个硬件输入设备(比如插多个手柄),SlateUser就会多一个。SlateUser里方法的功能主要分为以下几部分:
FWidgetPath、FArrangedChildren、FArrangedWidget我们都知道,UI是一个树形结构。使用编辑器下的WidgetReflector可以清楚地看到当前选中的widget所在的树形结构。
ArrangedWidget是树的单个节点,包含一个SWidget和一个Geometry。 ArrangedChildren是节点数组的封装,它包含了一个ArrangedWidget的TArray,里面还有一些增删查的方法。 WidgetPath代表着一个Widget树的分支,它不仅包含了一个ArrangedChildren,还包含了一个树根节点的SWindow指针。(如果根节点不是SWindow则为空) 它们的关系如下: FDirectPolicy、FToLeafmostPolicy、FTunnelPolicy、FBubblePolicy这四个类位于FEventRouter内部。代表着遍历WidgetPath的四种策略。每一种策略类构造函数里都有WidgetPath。 这四种遍历策略的区别如下:
在FEventRouter::Route里会根据遍历策略进行遍历,当RoutingPolicy的ShouldKeepGoing返回false且Reply为Handle时结束遍历。 FHittestGridFHittestGrid,是用于检测玩家当前会点击哪个widget的网格。包含在SWindow里面。FHittestGrid里的格子是FCell类。如图,最大的网格才是FHittestGrid,每个小格子是FCell。 相关的方法是FSlateApplication的LocateWidgetInWindow。
核心方法分析接下来将对调用栈里最核心的三个方法进行分析。 ProcessMouseButtonDownEvent由于代码量较多,接下来用伪代码进行说明。
RoutePointerDownEvent注意遍历策略和上面的方法使用的是不一样的。
FEventRouter::RouteRoute里面就很简单了。根据传入的策略进行遍历,每次遍历后执行委托,委托返回的Reply为Handle时且遍历策略的ShouldKeepGoing返回false时结束遍历。
(注:UI的Navigation是只使用键盘或者手柄的游戏才有的一种系统) 总结以上就是Widget收到点击事件的全流程分析。总结如下,在没有开启Capture的情况下 ,流程为:
学习资料关于作者
CSDN博客:https://blog.csdn.net/j756915370 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 20:58:04- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |