转载自:http://www.cnblogs.com/wellbye/p/5366034.html

名字里带viewport/client的类不少,以及相关的类:

FViewportFrame、FViewport

FViewportClient/UScriptViewportClient/UGameViewportClient

UClient/UWindowsClient

UEngine/UGameEngine/UEditorEngine/UUnrealEdEngine

极易混淆,现整理如下:

首先从总体层级上看,UEngine最大,它包含了UClientUGameViewportClient

class UEngine : public USubsystem
{
public:
……class UClient* Client;class UGameViewportClient* GameViewport;
……

UEngine是己只是个抽象类,实际运行时根据是游戏还是编辑器模式,创建相应子类的实例,如是游戏则UGameEngine,如是编辑器则UUnrealEdEngine

它的实例创建出来后就存在全局变量GEngine上。

在UGameEngine::Init里,先后创建了其它对象:

1、先创建了UClient,实际的子类通过“engine-ini:Engine.Engine.Client”配置指定,在windows上是【WinDrv.WindowsClient】,在mac上则是【MacDrv.MacClient】,可见各子类就是对应各平台相关的实现;

2、然后创建UGameViewportClient,实际的类型是通过Engine上的GameViewportClientClass这个globalconfig属性指定的,所以它会自动从配置中读取,配置的默认值是【Engine.GameViewportClient】

3、接着创建FViewportFrame:

ViewportFrame = Client->CreateViewportFrame(ViewportClient,*AppName,GSystemSettings.ResX,GSystemSettings.ResY,GSystemSettings.bFullscreen);
FViewportFrame* UWindowsClient::CreateViewportFrame(FViewportClient* ViewportClient,const TCHAR* InName,UINT SizeX,UINT SizeY,UBOOL Fullscreen)
{return new FWindowsViewport(this,ViewportClient,InName,SizeX,SizeY,Fullscreen,NULL);
}

注意:创建函数(CreateViewportFrame)是UClient上的、并把UGameViewportClient做为参数,由此可略知其从属关系。

做为一般情形,这里创建的是FViewportFrame,所谓-Frame,也就是(操作系统层面的)外包窗口,因为通常程序总是要自己创建“主窗口”。但是在某些模式下(如内嵌于浏览器等),外包主窗口已经有了,就不需要再创建FViewportFrame,取而代之的是通过CreateWindowChildViewport接口来创建一个FViewport。

实际上FViewportFrame接口只有两个函数,一是获取其中的FViewport,二是Resize改变大小,这个Resize更能体现其做为外包窗口的特征。

此外,前面提到UClient的实际类型是UWindowsClient,它创建的FViewportFrame自然也是同一平台体系下的子类即FWindowsViewport。

FWindowsViewport是一个特定于Windows平台相关的实现类,它同时实现了FViewportFrame和FViewport两个接口,当然这只是实现的方便,并不能抹杀这两个接口的差异。

因为3中的创建方式,FViewportFrame在创建时传入了两个关键对象:UClient和UGameViewportClient,这当然都会被记在其成员变量上,以便后续使用。

下面细看UEngine的三大台柱子:(UClient、UGameViewportClient、FViewport)

台柱之一:UClient

看起来它像是对整个app的封装,其中的Tick函数每帧被调用,主要内容就是处理窗口和输入消息。

它的另外一个作用则是用来创建FViewport(Frame),这主要是给平台相关的子类机会,创建同一平台体系的FViewport子类。

UClient、UWindowsClient都是纯c++类(没有相关的脚本类),但是由于手动在声明中添加了DECLARE_ABSTRACT_CLASS_INTRINSIC,所以也遵照UObject/UClass系统规则,可以用StaticLoadClass/ConstructObject等规范函数统一创建。

台柱之二:UGameViewportClient

UGameViewportClient继承自->UScriptViewportClient->(UObject,FViewportClient),这里UScriptViewportClient没啥用,纯粹是打个酱油,把FViewportClient这种纯c++类转换到UClass体系链中而已。

先看FViewportClient基类接口的方法:

看起来它主要是用于消息处理。

但是在UEngine这种高层基类中声明的属性GameViewport,其类型并非FViewportClient基类,而是直接作为UGameViewportClient子类变量,这主要是因为脚本要用,GameViewport属性是在UEngine的脚本类里声明的,在脚本里只用当然只能用符合UObject/UClass体系的东西,而做为继承链中间过渡的UScriptViewportClient就是起了这个作用。

当然UGameViewportClient也添加了很多新方法和属性,如它也有一个Tick函数,也是每帧被调用。还有一个非要重要的成员GlobalInteractions,这个数组存的就是所有的输入消息处理器。

台柱之三:FViewport

这个,实在看不出有什么特点,只能说它是跟渲染器关联最紧密的一个类了,unreal3应该就是用FViewport来抽象一个可以渲染的区域吧。

三者之间彼此关联,纠缠万分。

首先,UEngine上存着由它创建的UClient和UGameViewportClient各一个,并且在Tick中又分别调用了它们的Tick

然后,UGameViewportClient上存着由UClient创建的FViewportFrame(以及其内的FViewport),(UGameViewportClient::SetViewportFrame)

还有,做为子类的UWindowsClient上存着所有由它创建的FWindowsViewport(FViewportFrame,FViewport),(static TArray<FWindowsViewport*> Viewports)

最后,作为最后被创建出来的FWindowsViewport,它当然也要记着创建它的UClient,以及用来初始化它的UGameViewportClient(这个是由基类FViewport记着的)。

在消息处理方面:

首先,系统窗口的消息处理函数是UWindowsClient::StaticWndProc

然后,大部份消息会交给该窗口(HWnd)对应的FWindowsViewport来处理:Viewports(i)->ViewportWndProc

然后,除了需要即时响应的消息被立即处理外,大部份输入类消息被缓存起来:Client->DeferMessage,这样一来消息处理流程又回到了UWindowsClient里

然后,在UWindowsClient::Tick里,会调用ProcessDeferredMessages和ProcessInput,来处理所有的输入消息,前者包括了键盘和鼠标点击,后者是鼠标移动,在Unreal3里比较特别的是,鼠标移动并不通过WM_XXX类的窗口消息来获取,而是用IDirectInputDevice8接口来获取。

ProcessDeferredMessages里面,每个消息又转给它的FWindowsViewport上的同名函数,最终都会交到它里面的FViewportClient(也就是UGameViewportClient)::InputKey/InputChar

ProcessInput里面,取当前活跃的FWindowsViewport(通常也就一个窗口),把鼠标事件都交给它里面的FViewportClient(也就是UGameViewportClient)::InputAxis

可见,键盘和鼠标操作,最终都是到了UGameViewportClient的InputXXX里,而它们里面的分派逻辑,也大致一样:

先是给自己身上的代理处理,UGameViewportClient上的HandleInput(Axis/Key/Char)

然后是给GlobalInteractions里的每一个去处理,这里的每个元素都是一个Interaction,Interaction是Unreal3里用来处理用户操作的基类,它身上也有一套Input(Axis/Key/Char)。

实际运行观察结果 ,GlobalInteractions共有4个元素,分别是:

Console,用来处理调试指令

GFxInteraction,给swf对象分派消息

UIInteraction,这个UI不知是啥了,可能是Unreal3自己的UI模块?

PlayerManagerInteraction:比较逻辑的一层,把输入映射给对应的Player处理,有点难以理解,但是ini里的[Engine.PlayerInput]节中,所有bindings绑定的消息处理函数,就是由它分派的

UE3的各种viewport和client相关推荐

  1. 窗口和元素的大小:offset client scroll

    1.偏移量(offset)只读 offsetHeight:元素垂直方向上占用的空间大小.包括元素内容区高度.元素上下内边距.(可见的)水平滚动条高度.上下边框高度 offsetWidth:元素水平方向 ...

  2. rest api 示例2_REST API教程– REST Client,REST Service和API调用通过代码示例进行了解释

    rest api 示例2 Ever wondered how login/signup on a website works on the back-end? Or how when you sear ...

  3. swoole 异步client redis TP5 微信模板消息 demo版本比较杂 代码注释啥的都没删除 但是可以用作为参考

    tplmsg  发送模板消息的类 <?php namespace app\admin\controller; use app\admin\controller\Base; use think\C ...

  4. 网页特效offset、client、scroll系列属性的作用

    元素偏移量 offset 系列 可以动态的得到元素的位置(偏移).大小等 获得元素距离带有定位父元素的位置 获得元素自身的大小(宽度高度) 注意:返回的数字都不带单位 offset系列属性 作用 el ...

  5. 三大系列总结(offset client scroll)

    元素偏移量offset offset概述 获得元素距离带有定位父元素的位置 如果子元素没有父亲或者父元素没有定位,则以body为准 获得元素自身的大小(包含padding+border+width) ...

  6. Web APIs介绍(四)——offset/client/scroll/轮播图/本地存储

    1.1. 元素偏移量 offset 系列 1.1.1 offset 概述 offset 翻译过来就是偏移量, 我们使用 offset系列相关属性可以动态的得到该元素的位置(偏移).大小等. 获得元素距 ...

  7. 【JavaScript】offset、client、scroll

    1. 元素偏移量offset 1.1 offset介绍 offset:偏移量,可以利用offset动态的获取元素在页面中的位置大小信息. 属性 说明 offsetLeft 返回元素相对于带有定位的父元 ...

  8. js中offset、client、scroll的区别

    偏移量:offset dimension offsetHeight: 元素在垂直方向上占用的空间大小,以像素计.包括元素的高度.(可见的)水平滚动条的高度.上边框高度和下边框高度. offsetWid ...

  9. display:weston的client端绘画[subsurface,fullscreen]

    weston的源代码里面有关于client的绘画例子 建议追踪https://github.com/wayland-project/weston/blob/master/clients/ 增加一种功能 ...

最新文章

  1. mysql 怎么格式化输出_怎么格式化MySQL输出代码
  2. 如何去掉Silverlight应用程序在浏览器中的滚动条
  3. 他们拿走腾讯百万奖金,我有点泪目
  4. 莫名其妙的SqlServer更新错误:OleDbException 必须声明标量变量
  5. 【转】SVM入门(一)SVM的八股简介
  6. Coursera自动驾驶课程第10讲:Feedforward Neural Networks
  7. as_hash ruby_Hash.merge(other_hash)方法与Ruby中的示例
  8. 死磕苹果,小米飘了?
  9. 给想进大厂的同学一条忠告!
  10. 9、网友问答----有关清零问题------------------labview宝典
  11. RFC4568规范:SDP协商SRTP密钥
  12. IDEA Error occurred during initialization of VM
  13. 【智能优化算法-灰狼算法】基于非支配排序灰狼优化器(NS-GWO)算法求解多目标优化算法附matlab代码
  14. obd协议 混动车_OBD协议介绍
  15. 拆书笔记27|孔夫子和机器人
  16. 怎么快速学好大数据开发?
  17. [Vue warn]: Unknown custom element: <mycom> - did you register the component correctly? For recursiv
  18. 无人机相关资料整理-备忘
  19. google论文--mapred中文翻译
  20. 固定资产管理系统的作用和重要意义

热门文章

  1. Numpy——bool运算
  2. Storm的窗口操作
  3. gor实现http流量回放
  4. ZeroMemory 与 memset
  5. 初识Android自定义控件之旋转罗盘的制作
  6. LNMP一键安装包详细安装教程
  7. lnmp一键安装包 安装php-fpm,LNMP一键安装包常用命令及配置文件路径
  8. Alian解读SpringBoot 2.6.0 源码(九):启动流程分析之应用上下文刷新后处理(启动完成事件,Runner运行器,就绪事件)
  9. 可穿戴机器外骨骼设计构想
  10. 联科教育SQL Server 2008 R2管理系列04:创建表