【UE4】编辑器开发(一)关卡编辑器拓展

一、菜单栏或工具栏中创建拓展项

在StartModule中创建拓展项:

//加载LevelEditor模块,LevelEditor模块负责的就是打开UE4编辑器首先映入眼帘的各个编辑窗口。其中包括菜单栏、工具栏、视窗、详情面板、Modes面板、世界大纲面板等GUI功能。
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
{	//创建菜单栏项
	//创建拓展
	FTSharedPtr<FExtender> Extender = MakeShareable(new FExtender());
	/**
	@Param FName ExtensionHook. 项所在位置
	@Param EExtensionHook::Position HookPosition. 更具体的表示在ExtensionHook的相对位置:Before、After、First
	@Param const TSharedPtr< FUICommandList >& CommandList. 触发命令
	@Param const FMenuBarExtensionDelegate& MenuBarExtensionDelegate. 单播委托。绑定一个方法,方法是关于返回拓展项的信息。
	*/
	MenuExtender->AddMenuBarExtension("Help", EExtensionHook::After, PluginCommands, FMenuBarEtensionDelegate::CreateRaw(this, &FStandaloneWinModule::AddMenuBarExtension));
	//添加拓展项到关卡编辑器
	LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
}
{	//创建菜单拓展项,就是菜单栏内的子项
	FTSharedPtr<FExtender> Extender = MakeShareable(new FExtender());
	MenuExtender->AddMenuExtension("WindowLayout", EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FStandaloneWinModule::AddMenuExtension));
	LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
}
{	//创建工具栏拓展项
	FTSharedPtr<FExtender> Extender = MakeShareable(new FExtender());
	MenuExtender->AddMenuExtension("Settings", EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FStandaloneWinModule::AddToolBarExtension));
	LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
}

拓展想项委托方法:

//此方法是创建一个菜单栏拓展项的委托方法,其它两个方法与此类似。
void AddMenuBarExtension(FMenuBarBuilder& Builder)
{
	//AddMenuEntry有多个重载方法。可以通过其设置显示文本、提示文本、图标等参数。
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
}

void AddMenuExtension(FMenuBuilder& Builder)
{
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
}

void AddToolbarExtension(FToolBarBuilder& Builder)
{
	Builder.AddToolBarButton(FStandaloneWinCommands::Get().OpenPluginWindow);
}

菜单栏拓展项:
创建菜单栏拓展项
创建的菜单拓展项:
菜单子项
工具栏拓展项:
工具栏子项
上面构建菜单栏、菜单和工具栏拓展项的显示参数分别使用FMenuBarBuilder、FMenuBuilder和FToolBarBuilder。他们的继承关系为:

FMultiBoxBuilder
FBaseMenuBuilder
FMenuBarBuilder
FMenuBuilder
FToolBarBuilder

二、菜单栏拓展项(Menu Bar Exntender)

创建下拉菜单

我们刚刚通过AddMenuEntry创建的是一个按钮项,下面我们创建一个下拉菜单:

void AddMenuBarExtension(FMenuBarBuilder& Builder)
{
	/**
		@Param const FText& InMenuLabel. 第一个参数是菜单栏拓展项的显示名称。
		@Param const FText& InToolTip.	第二参数是菜单栏拓展项的提示名称。
		@Param const FNewMenuDelegate& InPullDownMenu.	第三个是下拉菜单显示的委托绑定,我们这里绑定了刚刚的菜单拓展项委托方法。
		@Param FName InExtensionHook.	第四个参数是菜单栏拓展项的Hook名称。
	*/
	Builder.AddPullDownMenu(
		LOCTEXT("PullMenu", "PullMenu"),
		LOCTEXT("This_Is_Pull_Menu", "This is Pull Menu"),
		FNewMenuDelegate::CreateRaw(this, &FStandaloneWinModule::AddMenuExtension),
		"AfterHelp"
	);
}

菜单栏拓展项:
菜单栏拓展项
菜单栏拓展项,菜单项我们绑定了下面的菜单委托方法,所以会显示一个分割栏和两个菜单项:
菜单栏拓展项

三、菜单拓展项(Menu Extender)

1. 创建分隔栏


void AddMenuExtension(FMenuBuilder& Builder)
{
	//第一个参数是分隔栏的Hook名,第二参数是分隔栏的显示名称
	Builder.BeginSection("CustomSection", LOCTEXT("CustomArea", "CustomArea"));
	//AddMenuEntry执行两遍,将在分隔栏添加两次拓展项
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
	Bilder.EndSection();
}

这个是最上面绑定的此方法,所以在Window菜单显示:
下拉菜单分隔栏
这个是上面创建的菜单拓展项绑定此委托方法后,显示的菜单项:
菜单栏拓展项

2. 创建分割线

void AddMenuExtension(FMenuBuilder& Builder)
{
	//第一个参数是分隔栏的Hook名,第二参数是分隔栏的显示名称
	Builder.BeginSection("CustomSection", LOCTEXT("CustomArea", "CustomArea"));
	//AddMenuEntry执行两遍,将在分隔栏添加两次拓展项
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
	//创建简单的分割线
	Builder.AddMenuSeparator("SeparatorHook");
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
	Bilder.EndSection();
}

带Hook的分割线:
带Hook的分割线

3. 创建子下拉菜单

菜单栏下拉菜单内还可以创建子下拉菜单

void FStandaloneWinModule::AddMenuExtension(FMenuBuilder& Builder)
{
	Builder.BeginSection("CustomSection", LOCTEXT("CustomArea", "CustomArea"));

	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
	Builder.AddMenuSeparator("SubMenuSp");
	/**
	创建子下拉菜单,与创建下拉菜单相似,该方法有多个重载方法
	@Param 子下拉菜单的父拓展项的显示名称
	@Param 提示名称
	@Param 子下拉菜单项的委托
	@Param true-点击显示下拉菜单,false-鼠标移上去即显示下拉菜单
	@Param 显示图标,这里没有设置
	@Param 当一个子项被选择后,是否关闭子下拉菜单
	@Param Hook名称
	*/
	Builder.AddSubMenu(
		LOCTEXT("SubMenu", "SubMenu"),
		LOCTEXT("This_is_Sub_Menu", "This is Sub Menu!"),
		FNewMenuDelegate::CreateRaw(this, &FStandaloneWinModule::AddSubMenuExtension),
		false,
		FSlateIcon(),
		true,
		"SubMenuHook"
	);
	Builder.EndSection();
}

void FStandaloneWinModule::AddSubMenuExtension(FMenuBuilder& Builder)
{
	Builder.AddMenuEntry(FStandaloneWinCommands::Get().OpenPluginWindow);
}

子下拉菜单:
子下拉菜单

4. 添加其它拓展项

自定义UI

/**
FMenuBuilder方法,添加自定义Slate控件
@param	InWidget			要显示在下拉菜单的UI控件
@param	InLabel				控件前面显示的标签文本
@param	bNoIndent			如果为true,移除UI控件左边的边距,默认为false
@param	bSearchable			如果为true,则Widget组件可被搜索到,默认为true
*/
void AddWidget( TSharedRef<SWidget> InWidget, const FText& Label, bool bNoIndent = false, bool bSearchable = true );

输入框

/**
添加一个可编辑文本框(输入框)
@param	InLabel				显示文本
@param	InToolTip			提示文本
@param	InIcon				显示图标
@param	InTextAttribute		编辑的文本内容
@param	InOnTextCommitted	文本提交触发委托
@param	InOnTextChanged		文本修改触发委托
@param	bInReadOnly			文本是否只允许可读,默认为false,表示文本框可编辑
*/
void AddEditableText( const FText& InLabel, const FText& InToolTip, const FSlateIcon& InIcon, const TAttribute< FText >& InTextAttribute, const FOnTextCommitted& InOnTextCommitted = FOnTextCommitted(), const FOnTextChanged& InOnTextChanged = FOnTextChanged(), bool bInReadOnly = false );

四、工具栏拓展项

1. 添加分隔栏和分割线

//添加分隔栏,参数为Hook名称
ToolBarBuilder.BeginSection("CustomHook");
ToolBarBuilder.AddToolBarButton(FStandaloneWinCommands::Get().OpenPluginWindow);
//添加分割线,参数为Hook名称
ToolBarBuilder.AddSeparator("ToolBarSep");
ToolBarBuilder.AddToolBarButton(FStandaloneWinCommands::Get().OpenPluginWindow);
ToolBarBuilder.EndSection();

分隔栏和分割线效果:
分隔栏和分割线

2. 创建下拉菜单

/**
 * 创建下拉菜单按钮,其实这个方法不止可以创建下拉菜单,主要是可以创建一个带有下拉图标的按钮
 *
 * @param	InAction				FUIAction类型,可以先通过其设置拓展项参数然后传给此方法调用,也可以直接设置下面的参数
 * @param	InMenuContentGenerator	当拓展项被触发,将会调用此委托,生成一个菜单
 * @param	InLabelOverride			标签显示名称,参数如果省略,将会使用Action中的参数
 * @param	InToolTipOverride		按钮提示名称,参数如果省略,将会使用Action中的参数
 * @param	InIconOverride			按钮图标,参数如果省略,将会使用Action中的参数
 * @param	bInSimpleComboBox		如果为true,标签和图标将不会被显示,默认为false
 * @param	InTutorialHighlightName	这个组件的标识名称,在教程说明中将会高亮显示,这个参数一般不用
 */

ToolBarBuilder.AddComboButton(
	FUIAction(),		//拓展项的设置我们使用下面的参数去设置
	FOnGetContent::CreateRaw(this, &FStandaloneWinModule::ToolBarCombox),	//绑定下面的UI委托方法
	LOCTEXT("ComboBox", "ComboBox"),					//标签内容
	LOCTEXT("This_Is_ComboBox", "This is Combo Box!"),	//提示信息
	FSlateIcon(),			//不使用图标
	false, 	//true-不显示图标和标签,false-显示图标和标签
);

//一个带显示文本框和输入文本框的UI,将其绑定到工具栏的菜单内容生成委托上
TSharedRef<SWidget> FStandaloneWinModule::ToolBarCombox()
{
	TSharedPtr<SWidget> Combox = SNew(SBox).WidthOverride(150.f).HeightOverride(200.f)
		[
			SNew(SVerticalBox)+SVerticalBox::Slot().HAlign(HAlign_Fill).VAlign(VAlign_Top).AutoHeight()
			[
				SNew(STextBlock).Text(LOCTEXT("ThisComboBox", "This is Combo Box!"))
			]+SVerticalBox::Slot().HAlign(HAlign_Fill).VAlign(VAlign_Top).AutoHeight()
			[
				SNew(SEditableTextBox)
			]
		];
	return Combox.ToSharedRef();
}

工具栏下拉菜单是否显示标签和图标的对比(第六个参数):
工具栏下拉菜单对比
创建的工具栏菜单效果:
工具栏菜单

五、 Viewport选中Actor的菜单拓展

//获取Level Editor模块
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
//获取Viewport菜单上下文拓展项(Viewport中选中物体的右击菜单拓展项),是一个委托数组
auto& LVCMExtenders = LevelEditorModule.GetAllLevelViewportContextMenuExtenders();
//在数组中添加一个新的拓展项,当右击选中Actor并弹出菜单时,将会遍历此数组并执行绑定的委托方法
LVCMExtenders.Add(FLevelEditorModule::FLevelViewportMenuExtender_SelectedActors::CreateRaw(this, &FStandaloneWinModule::LVCMExtender));
//委托方法,第一个参数是命令列表,第二个是选中的Actor数组,返回菜单拓展项(即显示内容)
TSharedRef<FExtender> FStandaloneWinModule::LVCMExtender(const TSharedRef<FUICommandList> CommandList, const TArray<AActor*> Actors)
{
	//加载LevelEditor模块
	FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
	//创建一个拓展项,与上一章中用法相似,用其拓展菜单项
	TSharedPtr<FExtender> Extender = MakeShareable(new FExtender());
	//设置菜单拓展项显示内容,绑定的委托是上章创建的委托方法
	Extender->AddMenuExtension("ActorAsset", EExtensionHook::After, CommandList, FMenuExtensionDelegate::CreateRaw(this, &FStandaloneWinModule::AddMenuExtension));
	//auto& LVCMExtenders = LevelEditorModule.GetAllLevelViewportContextMenuExtenders();
	//LVCMExtenders.Pop();			//如果将最后一个(我们刚刚创建的)Extender移除,则将会在第一显示菜单后,下次不会再显示此项
	//返回拓展项,将会被显示在菜单栏
	return Extender.ToSharedRef();
}

Viewport中选中物体的菜单效果:
场景中显示菜单
World Outline中选中Actor的菜单效果:
世界大纲中选中Actor的菜单效果

六、其它常用可拓展编辑器模块

类型 菜单栏拓展 工具栏拓展
AnimationBlueprintEditor
AnimationEditor
BehaviorTreeEditor
Cascade
CurveAssetEditor ×
CurveTableEditor ×
DataTableEditor ×
DestructibleMeshEditor
EnvironmentQueryEditor
FontEditor
Kismet ×
LevelEditor
MaterialEditor
Matinee
NiagaraEditor
Persona ×
PhysicsAssetEditor
SkeletalMeshEditor
StaticMeshEditor
StringTableEditor ×
TextureEditor
TranslationEditor ×
UMGEditor

加载模块时,注意有些模块的注册名和类名不一致,比如Kistmet和FBlueprintEditorModule等。还要注意某些模块的加载顺序和时间。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章