前言
关于菜单搭建,我之前就写过一篇文章关于如何使用 Python 搭建 Unreal 主界面的菜单。 链接
但是倘若要实现更为复杂的效果,比如在 Sequencer 的右键菜单上扩展,或者添加工具栏。
要实现这样的功能 Python 就无能为力了。
既然要用 C++ 实现,就必须要推荐一下官方提供的扩展教程。 B站链接 Youtube链接 github链接
教程稍微有点老了,是 2015 年的,不过我把 Github 的代码拉下来,稍微修复一些编译的小问题,基本上是可用的。
作为引擎扩展是绝佳的参考,另外最近逛论坛的时候还发现了一个不错 Python Editor 扩展插件。
在 Unreal 里面实现 Maya 工具栏的效果,也是引擎扩展非常好的参考。 论坛地址 github地址
不过 Python Editor 在 4.25 引擎下编译会出现大量错误,头文件的索引很多都不可用,还有一些代码的小问题。
所以我把这些杂七杂八的错误全部修复了,参见我 Fork 的仓库。 github地址
时间不足,有空要好好研究一下这个插件,做得非常好。
这个需求和我上次研究的 Unreal 自定义快捷键拓展中诸多相似的地方,可以结合到一起看 链接
Sequencer 菜单扩展
虚幻是开源的,所以即使再不济,也可以在源码上进行修改。
但是改动引擎是非常不好的操作,说明架构设计上扩展性不足,堂堂虚幻引擎怎么会沦落到这种地步。
所以在官方论坛上搜索一下,可以看到官方工作人员给出了一些使用提示 链接
官方的回答有提到大部分 Slate 都预留了 FExtender
来进行菜单的扩展,不需要修改源代码。
可以通过 C++ 插件来实现,并且插件实现可以迁移到不同项目的引擎,相比之下更友好。
到这一步可以去查 Unreal 的 C++ API 文档,看看 Sequencer 的 API 有没有提供相关的方法。
通常优先查 I 开头的类,因为这种类属于接口,将内部函数转换到外部使用的。
所以可以在 ISequencerModule
里面找到目标。
这个函数获取到 FExtensibilityManager
基本上就和上次扩展快捷键一样。
需要定制一个 UI_COMMAND 然后通过 AddExtender 将 UI_COMMAND 定义的命令添加进去。
同时 FExtender
构建参数里面 FMenuExtensionDelegate
中定义菜单嵌入的生成代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
ISequencerModule &SequencerModule = FModuleManager::Get().LoadModuleChecked<ISequencerModule>("Sequencer"); TSharedPtr<FExtensibilityManager> Manager = SequencerModule.GetObjectBindingContextMenuExtensibilityManager();
struct Callback { static void ExportCurve() { FString Script = "py \" xxx \""; GEngine->Exec(NULL, Script.GetCharArray().GetData()); }
static void ExtendMenu(FMenuBuilder &MenuBuilder) { MenuBuilder.BeginSection("FXCurve", LOCTEXT("FXCurve", "FXCurve")); { MenuBuilder.AddMenuEntry( LOCTEXT("ExportCurve", "Export Curve"), LOCTEXT("ExportCurveTooltip", "Export Curve to FX Blueprint"), FSlateIcon(), FExecuteAction::CreateStatic(&ExportCurve) ); } MenuBuilder.EndSection(); } };
TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender); MenuExtender->AddMenuExtension( TEXT("Spawnable"), EExtensionHook::Before, TSharedPtr<FUICommandList>(), FMenuExtensionDelegate::CreateStatic(&Callback::ExtendMenu)); Manager->AddExtender(MenuExtender);
|
上面的代码可以在 Sequencer 的 binding 菜单上嵌入 Entry 。
嵌入的 Spawnable
位置是怎么填写的呢?
其实看了官方的引擎扩展教程就可以知道怎么操作 ~
需要在引擎的配置面板上开启显示。
需要在引擎的配置面板上勾选显示。
然后重开引擎。(不重开 动态菜单也可以更新,不过 Toolbar 之类的就不行)
这样就可以看到菜单背后的代码标记了。
方便定位菜单的嵌入。
工具栏嵌入
其实有了菜单功能的嵌入,工具栏嵌入也是大同小异而已。
不逼逼,直接上代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| ISequencerModule &SequencerModule = FModuleManager::Get().LoadModuleChecked<ISequencerModule>("Sequencer"); TSharedPtr<FExtensibilityManager> Manager = SequencerModule.GetToolBarExtensibilityManager();
struct Callback { static void ExportCurve() { FString Script = "py \" xxx \""; GEngine->Exec(NULL, Script.GetCharArray().GetData()); }
static void ExtendToolBar(FToolBarBuilder &ToolBarBuilder) {
ToolBarBuilder.BeginSection("Keys"); { ToolBarBuilder.AddToolBarButton( FPyCommandList::Get().ExportSelectedKeys, NAME_None, TAttribute<FText>(), TAttribute<FText>(), FSlateIcon(FEditorStyle::GetStyleSetName(), "Matinee.ToggleCurveEditor") ); } ToolBarBuilder.EndSection(); ToolBarBuilder.AddSeparator(); } };
TSharedRef<FUICommandList> CommandList = MakeShareable(new FUICommandList); CommandList->MapAction( FPyCommandList::Get().ExportSelectedKeys, FExecuteAction::CreateStatic(&Callback::ExportCurve) );
TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender); MenuExtender->AddToolBarExtension( TEXT("Curve Editor"), EExtensionHook::After, CommandList, FToolBarExtensionDelegate::CreateStatic(&Callback::ExtendToolBar)); Manager->AddExtender(MenuExtender);
|
Toolbar 多了一个操作,需要创建一个 UI_COMMAND
然后通过 CommandList 来映射执行的回调函数。
这里我直接用了 Unreal 内置的图标,具体的名称可以参考引擎源码 SlateEditorStyle.cpp
里面的定义。
总结
可惜目前 Python 还没有暴露出相关的 UObject 类型来调用。
所以没法用 Python 进行扩展,不过也可以参考 Sequencer Scripting 插件的做法,将 FClass 转成 UClass 进行调用。
后续有空再进一步研究吧,c++的开发效率实在是太低了,而且我的基础极其不扎实,需要一些基础教程巩固一下(:з」∠)