large textbf{古有小窃者,掩耳可窃铃} / large textbf{今有剧盗者,失业率不明} / large textbf{埋头行大事,食言多自肥} / large textbf{宁可断脊喉,不敢认功勋} /
UToolMenus 是UE5编辑器中用于创建菜单和工具栏的工具。本文主要介绍与 UToolMenus 相关的概念,探索UE5编辑器创建菜单和工具栏的流程,以帮助对自定义菜单和工具栏有需要的开发者快速了解 UToolMenus 全貌。
UToolMenu 是菜单的主体,它的管理者是 UToolMenus,UToolMenus 负责 UToolMenu 的注册和记录,它有一个名为 Menus 的 TMap 成员变量,用于收纳已注册或未注册的 UToolMenu。我们的最终目的是将 UToolMenu 生成为一个 SWidget 以供某个界面显示,这个过程由 UToolMenus 中的 GenerateWidget() 函数发起,它会根据传入 UToolMenu 的 MenuType 创建合适的 Builder,将 UToolMenu 生成为一个 SWidget。
我们本次的探索有两个部分,一部分围绕 UToolMenus 如何组织 UToolMenu 来进行,另一部分则围绕 Builder 如何将 UToolMenu 生成为 SWidget 来进行。
{♡☘♡☘♡ quad今天的捉弄结束了 quad ♡☘♡☘♡}/
在UE5编辑器中,根据菜单生成的方式,可以分为 UToolMenu 生成和 FExtender 生成两种方式。UToolMenu 生成的是相对固定的菜单,这种菜单原则上不经常变动,例如编辑器原生的菜单。FExtender 生成的是动态的菜单,例如插件或一般模块添加的菜单,以及需要根据上下文情况发生变化的菜单。原则上如此,但并非是说 UToolMenu 只能生成固定的菜单,UToolMenu 也有动态生成菜单的能力,甚至有在蓝图中配置菜单的功能。
UToolMenu 与 FExtender 根本上的不同在于它们的配置时机。之前我们提到 Builder 会将传入的 UToolMenu 生成为 SWidget,而 UToolMenu 的菜单结构是在传入 Builder 之前就已经被配置好的,Builder 只会根据 UToolMenu 的菜单结构生成 SWidget,它不会更改这个结构,这也是我们说 UToolMenu 生成的是相对固定的菜单的原因。然后,Builder 会将 FExtender 需要生成的菜单项目根据 Hook 信息插入到 UToolMenu 的菜单中,因此,FExtender 的配置是在生成时的,而 UToolMenu 的配置是在生成前的。
UToolMenus 是一个全局单例,它负责管理所有UE5编辑器可能要生成的 UToolMenu,即配置 UToolMenu 的部分。它有一个名为 Menus 的 TMap 用来记录这些 UToolMenu,我们可以看到 UToolMenus 中的一些关键成员函数都与这个成员变量有关。
一个 UToolMenu 的结构由两个层次组成:Section 和 Entry。UToolMenu 的实际内容是 Entry,Section 是 Entry 的分组和插入点。
UToolMenus 中有两个十分相似的函数:RegisterMenu() 和 ExtendMenu()。ExtenderMenu() 的本意是搜寻存在的 UToolMenu 并加以拓展,但实际它的用法十分的宽松,甚至可以用于添加原本不存在的 UToolMenu,这使得在一般情况下,单参数的 RegisterMenu() 和 ExtendMenu() 几乎可以完成同样的工作,例如下面的代码,两个函数实现的功能是相同的:
UToolMenu* ExsitingMenu = UToolMenus::Get()->FindMenu("LevelEditor.MainMenu");
FToolMenuSection& ExsitingSection = ExsitingMenu->FindOrAddSection(NAME_None);
FToolMenuEntry& NewSubMenuEntry =
ExsitingSection.AddSubMenu(
"NewMenu",
LOCTEXT("New Menu", "New Menu"),
LOCTEXT("", ""),
FNewToolMenuChoice()
);
MakeEntry.InsertPosition = FToolMenuInsert("Help", EToolMenuInsertType::After);
static const FName NewMenuName = "LevelEditor.MainMenu.NewMenu";
UToolMenu* NewMenu = UToolMenus::Get()->RegisterMenu(NewMenuName);
// ExtendMenu() 在此时与 RegisterMenu() 类似
// UToolMenu* NewMenu = UToolMenus::Get()->ExtendMenu(NewMenuName);
FToolMenuSection& NewSection = NewMenu->AddSection("New Section", FText::FromString("New Section"));
NewSection.AddMenuEntry(
"NewMenuEntry",
LOCTEXT("New Menu Entry", "New Menu Entry"),
LOCTEXT("", ""),
FSlateIcon(),
FToolUIActionChoice()
);
<< · Back Index ·>>