目标
上一篇《学习虚幻引擎UMG的基础》中已经对UMG的基础有些了解了。
本篇目标是,学习使用UMG作为编辑器控件(之前往往是使用Slate做编辑器控件),然后对一些感兴趣的地方进行观察和实验。
1. 试用基础功能
正如官方文档所展示的,其功能的使用很简单。
首先创建一个 Editor Utility Widget 型蓝图。
然后正常编辑UMG
然后,右键这个蓝图点击 Run Editor Utility Widget
即可显示界面:
同时也可以发现它注册了一个能打开窗口的菜单:
2. 观察继承关系
正如《学习虚幻引擎UMG的基础》中提到的。每个蓝图不仅有作为蓝图资源的继承关系,也有它新定义的一个类的继承关系。
比如这里创建的蓝图,它的蓝图类是UEditorUtilityWidgetBlueprint
可以通过 Copy Reference 获得引用字符串。
字符串显示:
EditorUtilityWidgetBlueprint’/Game/yaksueEditorUtilityWidgetBlueprint.yaksueEditorUtilityWidgetBlueprint’
因此类型是EditorUtilityWidgetBlueprint
在 \Engine\Source\Editor\Blutility\Classes\EditorUtilityWidgetBlueprint.h 可看到它的继承关系,是一种更特殊的UMG蓝图类:
而这个蓝图新定义的类继承自UEditorUtilityWidget
。
在 \Engine\Source\Editor\Blutility\Classes\EditorUtilityWidget.h 中可看到它也是一种更特殊的UMG类:
3. 尝试用C++代码调用UMG内容作为控件
在UEditorUtilityWidgetBlueprint
中,可以看到一个关键的函数是CreateUtilityWidget
,因为这个函数负责将UMG控件转换为了Slate控件。
接下来,我想在C++中通过这个接口来调用它,因为这样我就可以用C++控制这个UMG出现在编辑器中的位置与时机了。
但是注意: 这个类或这个函数并没有加XXX_API
的宏,因此(在不改变引擎代码的情况下)不能在模块外调用。所以,只能参考这个函数中的代码在外部写一个类似的了。
以Editor Standalone Window为模板创建插件。
之所以用这个模板是因为它提供了一个按钮,点击就会创建一个窗口,而要想改变窗口中的内容就需要改变这里:
内容改变为:
TSharedRef<SDockTab> FTestCallUMGModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
{
//加载UMG的BP
UBlueprint* UMGBP = LoadObject<UBlueprint>(nullptr, L"/Game/yaksueEditorUtilityWidgetBlueprint");
//仿照 UEditorUtilityWidgetBlueprint::CreateUtilityWidget() 再实现一遍
TSharedRef<SWidget> TabWidget = SNullWidget::NullWidget;
{
UEditorUtilityWidget* CreatedUMGWidget = nullptr;//创建的UMG控件
UClass* BlueprintClass = UMGBP->GeneratedClass;
TSubclassOf<UEditorUtilityWidget> WidgetClass = BlueprintClass;
UWorld* World = GEditor->GetEditorWorldContext().World();
if (World)
{
if (CreatedUMGWidget)
{
CreatedUMGWidget->Rename(nullptr, GetTransientPackage());
}
CreatedUMGWidget = CreateWidget<UEditorUtilityWidget>(World, WidgetClass);
}
if (CreatedUMGWidget)
{
TabWidget = SNew(SVerticalBox)
+ SVerticalBox::Slot()
.HAlign(HAlign_Fill)
[
CreatedUMGWidget->TakeWidget()
];
}
}
return SNew(SDockTab)
.TabRole(ETabRole::NomadTab)
[
// Put your tab content here!
TabWidget
];
}
为了让代码认识UEditorUtilityWidget
需要补上include:
#include "Editor/Blutility/Classes/EditorUtilityWidget.h"
为了让一些函数的实现能找到需要补上 “UMGEditor”,“Blutility”,“UMG” 这三个模块:
最后,成功调用: