1. 主菜单的按钮
参考https://alanwalk.github.io/2018/04/17/how-to-add-ue4-editor-menu/
2. Tab上的按钮
3. Tab上的菜单怎么构建呢?
主要是构建菜单栏的SWidge,然后添加到最上面的布局中就可以了。
所有的菜单栏,都是通过FExtender构建的,
TSharedRef< SWidget > FTestEditorModule::Test()
{
inTabMgr = FGlobalTabmanager::Get();
TSharedPtr<FExtender> MenuBarExtender = MakeShareable(new FExtender());
MenuBarExtender->AddMenuBarExtension(
"Help",
EExtensionHook::After,
NULL,
FMenuBarExtensionDelegate::CreateRaw(this, &FTestEditorModule::AddMenuBarExtension));
FTestEditorModule& TestEditorModule = FModuleManager::LoadModuleChecked<FTestEditorModule>(TestEditorTabName);
MenuExtensibilityManager->AddExtender(MenuBarExtender);
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
TSharedRef< SWidget > MenuBarWidget = MainFrameModule.MakeMainTabMenu( inTabMgr, MenuBarExtender.ToSharedRef() );
return MenuBarWidget;
}
这里构建MenuBarExtender之后,使用的是 MainFrameModule.MakeMainTabMenu构建了SWidget,看一下创建的代码
TSharedRef< SWidget > FMainMenu::MakeMainTabMenu( const TSharedPtr<FTabManager>& TabManager, const TSharedRef< FExtender > UserExtender )
{ struct Local
{
static void FillProjectMenuItems( FMenuBuilder& MenuBuilder )
{
MenuBuilder.BeginSection( "FileProject", LOCTEXT("ProjectHeading", "Project") );
{
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().NewProject );
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().OpenProject );
FText ShortIDEName = FSourceCodeNavigation::GetSelectedSourceCodeIDE();
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().AddCodeToProject,
NAME_None,
TAttribute<FText>(),
FText::Format(LOCTEXT("AddCodeToProjectTooltip", "Adds C++ code to the project. The code can only be compiled if you have {0} installed."), ShortIDEName)
);
MenuBuilder.AddSubMenu(
LOCTEXT("PackageProjectSubMenuLabel", "Package Project"),
LOCTEXT("PackageProjectSubMenuToolTip", "Compile, cook and package your project and its content for distribution."),
FNewMenuDelegate::CreateStatic( &FPackageProjectMenu::MakeMenu ), false, FSlateIcon(FEditorStyle::GetStyleSetName(), "MainFrame.PackageProject")
);
/*
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().LocalizeProject,
NAME_None,
TAttribute<FText>(),
LOCTEXT("LocalizeProjectToolTip", "Gather text from your project and import/export translations.")
);
*/
/*
MenuBuilder.AddSubMenu(
LOCTEXT("CookProjectSubMenuLabel", "Cook Project"),
LOCTEXT("CookProjectSubMenuToolTip", "Cook your project content for debugging"),
FNewMenuDelegate::CreateStatic( &FCookContentMenu::MakeMenu ), false, FSlateIcon()
);
*/
FString SolutionPath;
if (FSourceCodeNavigation::DoesModuleSolutionExist())
{
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().RefreshCodeProject,
NAME_None,
FText::Format(LOCTEXT("RefreshCodeProjectLabel", "Refresh {0} Project"), ShortIDEName),
FText::Format(LOCTEXT("RefreshCodeProjectTooltip", "Refreshes your C++ code project in {0}."), ShortIDEName)
);
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().OpenIDE,
NAME_None,
FText::Format(LOCTEXT("OpenIDELabel", "Open {0}"), ShortIDEName),
FText::Format(LOCTEXT("OpenIDETooltip", "Opens your C++ code in {0}."), ShortIDEName)
);
}
else
{
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().RefreshCodeProject,
NAME_None,
FText::Format(LOCTEXT("GenerateCodeProjectLabel", "Generate {0} Project"), ShortIDEName),
FText::Format(LOCTEXT("GenerateCodeProjectTooltip", "Generates your C++ code project in {0}."), ShortIDEName)
);
}
// @hack GDC: this should be moved somewhere else and be less hacky
ITargetPlatform* RunningTargetPlatform = GetTargetPlatformManager()->GetRunningTargetPlatform();
if (RunningTargetPlatform != nullptr)
{
const FName CookedPlatformName = *(RunningTargetPlatform->PlatformName() + TEXT("NoEditor"));
const FText CookedPlatformText = FText::FromString(RunningTargetPlatform->PlatformName());
FUIAction Action(
FExecuteAction::CreateStatic(&FMainFrameActionCallbacks::CookContent, CookedPlatformName),
FCanExecuteAction::CreateStatic(&FMainFrameActionCallbacks::CookContentCanExecute, CookedPlatformName)
);
MenuBuilder.AddMenuEntry(
FText::Format(LOCTEXT("CookContentForPlatform", "Cook Content for {0}"), CookedPlatformText),
FText::Format(LOCTEXT("CookContentForPlatformTooltip", "Cook your game content for debugging on the {0} platform"), CookedPlatformText),
FSlateIcon(),
Action
);
}
}
MenuBuilder.EndSection();
}
static void FillRecentFileAndExitMenuItems( FMenuBuilder& MenuBuilder )
{
MenuBuilder.BeginSection("FileRecentFiles");
{
if (GetDefault<UEditorStyleSettings>()->bShowProjectMenus && FMainFrameActionCallbacks::ProjectNames.Num() > 0)
{
MenuBuilder.AddSubMenu(
LOCTEXT("SwitchProjectSubMenu", "Recent Projects"),
LOCTEXT("SwitchProjectSubMenu_ToolTip", "Select a project to switch to"),
FNewMenuDelegate::CreateStatic(&FRecentProjectsMenu::MakeMenu), false, FSlateIcon(FEditorStyle::GetStyleSetName(), "MainFrame.RecentProjects")
);
}
}
MenuBuilder.EndSection();
#if !PLATFORM_MAC // Handled by app's menu in menu bar
MenuBuilder.AddMenuSeparator();
MenuBuilder.AddMenuEntry( FMainFrameCommands::Get().Exit, "Exit" );
#endif
}
};
FExtensibilityManager ExtensibilityManager;
ExtensibilityManager.AddExtender( UserExtender );
{
TSharedRef< FExtender > Extender( new FExtender() );
IMainFrameModule& MainFrameModule = FModuleManager::GetModuleChecked<IMainFrameModule>("MainFrame");
if (GetDefault<UEditorStyleSettings>()->bShowProjectMenus)
{
Extender->AddMenuExtension(
"FileLoadAndSave",
EExtensionHook::After,
MainFrameModule.GetMainFrameCommandBindings(),
FMenuExtensionDelegate::CreateStatic(&Local::FillProjectMenuItems));
}
Extender->AddMenuExtension(
"FileLoadAndSave",
EExtensionHook::After,
MainFrameModule.GetMainFrameCommandBindings(),
FMenuExtensionDelegate::CreateStatic( &Local::FillRecentFileAndExitMenuItems ) );
ExtensibilityManager.AddExtender( Extender );
}
TSharedRef< SWidget > MenuBarWidget = FMainMenu::MakeMainMenu( TabManager, ExtensibilityManager.GetAllExtenders().ToSharedRef() );
return MenuBarWidget;
}
TSharedRef<SWidget> FMainMenu::MakeMainMenu(const TSharedPtr<FTabManager>& TabManager, const TSharedRef< FExtender > Extender)
{
#define LOCTEXT_NAMESPACE "MainMenu"
// Cache all project names once
FMainFrameActionCallbacks::CacheProjectNames();
FMenuBarBuilder MenuBuilder(FMainFrameCommands::ActionList, Extender);
{
// File
MenuBuilder.AddPullDownMenu(
LOCTEXT("FileMenu", "File"),
LOCTEXT("FileMenu_ToolTip", "Open the file menu"),
FNewMenuDelegate::CreateStatic(&FMainMenu::FillFileMenu, Extender),
"File",
FName(TEXT("FileMenu"))
);
// Edit
MenuBuilder.AddPullDownMenu(
LOCTEXT("EditMenu", "Edit"),
LOCTEXT("EditMenu_ToolTip", "Open the edit menu"),
FNewMenuDelegate::CreateStatic(&FMainMenu::FillEditMenu, Extender, TabManager),
"Edit"
,
FName(TEXT("EditMenu"))
);
// Window
MenuBuilder.AddPullDownMenu(
LOCTEXT("WindowMenu", "Window"),
LOCTEXT("WindowMenu_ToolTip", "Open new windows or tabs."),
FNewMenuDelegate::CreateStatic(&FMainMenu::FillWindowMenu, Extender, TabManager),
"Window"
);
// Help
MenuBuilder.AddPullDownMenu(
LOCTEXT("HelpMenu", "Help"),
LOCTEXT("HelpMenu_ToolTip", "Open the help menu"),
FNewMenuDelegate::CreateStatic(&FMainMenu::FillHelpMenu, Extender),
"Help"
);
}
// Create the menu bar!
TSharedRef<SWidget> MenuBarWidget = MenuBuilder.MakeWidget();
// Tell tab-manager about the multi-box for platforms with a global menu bar
TabManager->SetMenuMultiBox(MenuBuilder.GetMultiBox());
return MenuBarWidget;
}
最后是构建了一个MenuBarWidget,如果需要自定义Menu,可以参考着个代码自己创建一个函数。
这里自动构建了一个Menu bar。
最后添加到Widget中
4. Tab上的ToolBar
// 创建的代码
TSharedRef<FUICommandList> CommandList = MakeShareable(new FUICommandList);
FToolBarBuilder ToolbarBuilder( CommandList, FMultiBoxCustomization::None );
ToolbarBuilder.BeginSection("CurveEditorFit");
{
ToolbarBuilder.AddToolBarButton(FProEditorCommands::Get().OpenPluginWindow);
ToolbarBuilder.AddToolBarButton(FProEditorCommands::Get().OpenPluginWindow);
ToolbarBuilder.AddToolBarButton(FProEditorCommands::Get().OpenPluginWindow);
}
ToolbarBuilder.EndSection();
return SNew(SDockTab)
.TabRole(ETabRole::NomadTab)
[
// Put your tab content here!
SNew(SVerticalBox)
+SVerticalBox::Slot().MaxHeight(50)
[
ToolbarBuilder.MakeWidget()
]
]
也是获取ToolBarBuilder的布局,然后加入父类的布局中