编辑器扩展:自定义菜单栏

前言

常见的自定义编辑器菜单类的内容有 菜单(Menu), 菜单栏(MenuBar), 工具栏(ToolBar)

效果如下

image-20210809100140206

image-20210809100206177

image-20210809100220457

实现方式

这里主要分为两种方式扩展

  • FExtender
  • UToolMenu

后者为较为新的方式,在老版本和多数博客资料里都没有这个方式

FExtender可以实现3种类型的扩展, 而UToolMenu对于部分扩展比如新的菜单栏添加这种并不支持(4.26)

菜单栏 MenuBar

1
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
1
2
3
4
5
//顶部菜单
TSharedPtr<FExtender> MenuBarExtender = MakeShareable(new FExtender());
MenuBarExtender->AddMenuBarExtension("Help",
EExtensionHook::After, PluginCommands, FMenuBarExtensionDelegate::CreateRaw(this, &FAdvancedFrameworkEditorModule::AddMenuBarExtension));
LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuBarExtender);

上述代码的意思即为在Help栏后面添加一个新的菜单栏分类, 然后我们通过函数AddMenuBarExtension来实现

1
2
3
4
5
6
7
8
9
10
void FAdvancedFrameworkEditorModule::AddMenuBarExtension(FMenuBarBuilder& Builder)
{
Builder.AddPullDownMenu(
LOCTEXT("PullMenu", "AdvancedFramework"),
LOCTEXT("PullMenu Tips", "AdvancedFramework Menu"),
FNewMenuDelegate::CreateRaw(this, &FAdvancedFrameworkEditorModule::MenuBarPullDown)

);

}
1
2
3
4
5
6
void FAdvancedFrameworkEditorModule::MenuBarPullDown( FMenuBuilder& Builder)
{
Builder.AddMenuEntry(FAFE_Commands::Get().LoginMap);
Builder.AddMenuEntry(FAFE_Commands::Get().TransitionMap);
Builder.AddMenuEntry(FAFE_Commands::Get().MapInfoSetup);
}

image-20210809100206177

菜单 Menu

菜单就是上述菜单栏内添加的一个MenuEntry, 我们注意到我们用的方式是Builder.AddMenuEntry(FAFE_Commands::Get().LoginMap);

这里就要稍微提一下Commands

1
UI_COMMAND(LoginMap, "Open Login Map", "Open Login Map", EUserInterfaceActionType::Button, FInputGesture());

在该类里需要声明并用宏定义这个FUICommandInfo对象, 还要注意的是, 如果使用了自定义图标, 那么在Style类里的名称要与这个FUICommandInfo对象的名称要匹配, 比如

1
2
Style->Set("AFE.LoginMap", new IMAGE_BRUSH(TEXT("Map_40x"), Icon40x40));
Style->Set("AFE.LoginMap.Small", new IMAGE_BRUSH(TEXT("Map_16x"), Icon16x16));

我们在Windows菜单栏里添加我们的几个测试按钮

1
2
3
4
5
6
7
8
9
UToolMenu* Menu =  UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Window");
{
FToolMenuSection& Section = Menu->FindOrAddSection("AdvancedFramework");
{
Section.AddMenuEntryWithCommandList(FAFE_Commands::Get().LoginMap, PluginCommands);
Section.AddMenuEntryWithCommandList(FAFE_Commands::Get().TransitionMap, PluginCommands);
Section.AddMenuEntryWithCommandList(FAFE_Commands::Get().MapInfoSetup, PluginCommands);
}
}

这里要UToolMenu比较方便, 当然也可以用FExtender来添加, 方法类似于菜单栏的使用

工具栏 ToolBar

默认创建一个独立窗口插件就会自动生成一个工具栏的插件按钮, 当然我们也可以参考他的实现方式, 用UToolMenu来添加一个Button的方式.

这里我们用传统的FExtender来添加一个下来菜单

1
2
3
4
5
6
//工具栏
TSharedPtr<FExtender> ToolBarExtender = MakeShareable(new FExtender());
ToolBarExtender->AddToolBarExtension("File",
EExtensionHook::Before, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FAdvancedFrameworkEditorModule::AddToolBarExtension));

LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolBarExtender);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void FAdvancedFrameworkEditorModule::AddToolBarExtension(FToolBarBuilder& Builder)
{
auto ContextMenu = []()
{

return SNew(SAFE_Hud);
};



Builder.AddSeparator("AdvancedFramework");
Builder.AddComboButton(FUIAction(), FOnGetContent::CreateLambda(ContextMenu),
TAttribute<FText>(FText::FromString("AdvancedFramework")),
TAttribute<FText>(FText::FromString("AdvancedFramework Menu")),
FSlateIcon(FAFE_Style::GetStyleSetName(), "AFE.OpenPluginWindow"));

}

这里稍微复杂一点, 通过添加一个ComboButton, 同时返回一个Slate对象来实现

image-20210809102049841