前言
现在开始转开发UE,UE能找到的参考资料比Unity要少…
后续开发中遇到的坑和解决方法,我会尽可能都放上来和大家一起共享讨论
这次展示一个最基础的编辑器界面是如何实现的。
不会非常深入分析代码,而是给想快速实现功能的同学入门理解。
什么是Slate
Slate是UE的底层UI框架,平时用的最多的UI系统UMG也是继承Slate系统。
编辑器基本都会使用Slate进行界面开发
创建
目标:创建一个在菜单栏有入口的空白窗口界面
-
插件选择新插件,然后选择编辑器独立窗口
-
代码会自动生成,编译后在菜单栏可以看到入口按钮
目录分析
打开VS,可以看到UE已经自动生成好相关的代码了。
Plugins目录:全部插件的根目录
DynamicCreateTool:这是我新建的插件的名称,整个插件的根目录。
Resources:放置资源,例如菜单栏的按钮图片
Source:代码目录。Public和Private是C++常用的代码管理,Public放头文件,Private放cpp文件
还有两个特殊的文件DynamicCreateTool.Build.cs和DynamicCreateTool.uplugin
DynamicCreateTool.Build.cs
这个文件用于配置编译引用关系。公有是指第三方引用这个插件时也包含进去,私有是不包含的。
一个插件也等于一个模块的意义。
可以看到,PrivateDependencyModuleNames已经自动添加上了UE相关的模块,例如这次要讨论的Slate模块。
如果开发过程中,有什么新的模块要引用,就需要在这个文件进行标记。
DynamicCreateTool.uplugin
这个定义这个插件的配置,基本是不需要修改的。
最重要是关注这个名称,和DynamicCreateTool.Build.cs搭配使用。ModuleName要填写的名字,就是这里定义的。
Modules内可以有多个模块,对应就是Source目录下的插件目录。
代码分析
首先先看一下UE自动创建的界面。如下图,就是一个空白窗口加上一行text。
为了要实现上面的窗口,UE生成了三个类。XXX,XXXCommands,XXXStyle。
接下来先将重点放到DynamicCreateToop.cpp。
函数:FDynamicCreateToolModule::OnSpawnPluginTab
。这个函数就是显示界面的核心函数。
在Unity编辑器中,界面的实现有一个OnGUI
的函数,每帧调用进行刷新。
Slate的实现并不是这样的,它通过一个指向SWidget
的智能指针进行界面控制。
返回值
首先关注这个返回值,是TSharedRef<SDockTab>
。这是什么意思呢?
看一下类继承,就可以知道,SDockTab
最终的父类就是SWidget
。
截图的中文是我机翻的,做补充参考。
这样的话,就可以很简单的理解了Slate的基本构成了。
一切界面元素的基类都是SWidget
。SWidget
作为基类,实现了常规的交互接口。
界面编码
类的分析先不发散思考,回过头来看第二个部分。界面的组成。
Slate的语法是UE特意开发的,所以和常规看得有点不一样。例如"[]"方括号就是重写的逻辑。
看这段代码的时候,把分段放到界面元素类上。
我重头写一次这段代码,来分析这里到底做了什么。
定义TSharedRef<SDockTab> dockTabSharedRef
,作为整个界面的根节点。
根节点的界面是SDockTab
,就是标签页界面。
在方括号中,后续需要添加界面内的内容。
最外层的界面方括号记得要加“;”
SNew
函数,是创建WdigetType
的模板函数。只要是继承SWidget
的类就可以
.TabRole
参数配置,控制标签页的样式。
.XXX
这种语法是Slate扩展支持的,支持多个。可以调用函数也可以设置参数。
这个标签页就是SDockTab
所实现的。
接下来,在SDockTab
里添加了一个SBox
界面。
SBox
界面很简单,就是一个包围盒。
HAlign
和VAlign
是水平和垂直的排版参数。
最后,在SBox
界面里面加了STextBlock
界面,用来显示字符内容。
Text
函数定义了我们要显示的字符内容。
OK,我们已经重写完了这段界面。编译且重启UE,看看我们实现的效果。
因为UE也是C++实现的,编译后不重启,效果不会生效的。所以每次编译完想看效果,都必须要重启。
打开看一下,界面已经显示“Hello Slate!”
其他界面设置
标签页的标题
标签页的标题从原本的DynamicCreateTool改为了Entrance。
在FDynamicCreateToolModule::StartupModule()
函数中调用了函数FGlobalTabmanager::Get()->RegisterNomadTabSpawner
,来注册了一个标签页。
内部函数SetDisplayName
用来设置标签页标题。
菜单栏按钮
这里的配置在FDynamicCreateToolCommands::RegisterCommands
函数中。
以下是绑定流程:
UToolMenus::Get()->ExtendMenu
,根据名称获取菜单对象
可以看到,函数绑定了一个对象PluginCommands
。
PluginCommands
对象的定义在DynamicCreateTool.h
在FDynamicCreateToolModule::StartupModule()
可以看到PluginCommands
的初始化。
参数使用了FDynamicCreateToolCommands.OpenPluginWindow
。
OpenPluginWindow
的定义
而OpenPluginWindow
则绑定了按钮的相关内容,这里就是按钮的配置。