前言

  去年有比较详细地研究如何通过 Python 生成 Unreal 的菜单 链接
  但是其实还有复杂的调用方法,可以实现更多的菜单项功能。
  这个就是本次探索的 ToolMenuEntryScript 对象了

用法

alt

  ToolMenuEntryScript 无法直接声明。
  需要用 Class 来继承它方能使用

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@unreal.uclass()
class ScirptMenu(unreal.ToolMenuEntryScript):

@unreal.ufunction(override=True)
def execute(self,context):
super(self.__class__,self).execute(context)
print("context",context)

@unreal.ufunction(override=True)
def get_label(self,context):
super(self.__class__,self).get_label(context)
return u'测试 entry script'

@unreal.ufunction(override=True)
def get_tool_tip(self,context):
super(self.__class__,self).get_label(context)
return u'测试 entry script tooltip '

@unreal.ufunction(override=True)
def is_visible(self,context):
assets = unreal.EditorUtilityLibrary.get_selected_assets()
return bool(assets)

@unreal.ufunction(override=True)
def can_execute(self,context):
# NOTE 只有选择了场景的 ACtor 才可以调用
actors = unreal.EditorLevelLibrary.get_selected_level_actors()
return bool(actors)

@unreal.ufunction(override=True)
def get_icon(self,context):
# NOTE 只有选择了资源才会出现选项
icon = unreal.ScriptSlateIcon("EditorStyle","ContentBrowser.AssetActions.Delete")
return icon


menus = unreal.ToolMenus.get()

menu_name = "ContentBrowser.AddNewContextMenu"
menu = menus.find_menu(menu_name)

# NOTE 如果已经注册则删除
if menus.is_menu_registered(menu_name):
menus.remove_menu(menu_name)

menu = menus.register_menu(menu_name)

# NOTE 注册 ToolMenuEntry
entry = unreal.ToolMenuEntry(type=unreal.MultiBlockType.MENU_ENTRY)
entry.set_label("测试 entry")
entry.set_icon("EditorStyle","ContentBrowser.AssetActions.Edit")
entry.set_string_command(unreal.ToolMenuStringCommandType.PYTHON,"",'import unreal;unreal.log("menu call")')
menu.add_menu_entry('',entry)

# NOTE 注册 ToolMenuEntryScript
script = ScirptMenu()
menu.add_menu_entry_object(script)

  开门见山,这是我自己研究出来可以使用的调用方法。
  Unreal Python 的函数重载需要用 Unreal 内置的装饰器进行包裹,可以参考 蓝图库封装

alt

  通过对 can_execute is_visible 的函数进行重载。
  我可以让菜单项根据选择的情况进行禁用和取消显示。
  比如我要做一个功能,只针对选择的 Texture2D 资源进行处理,那么我可以通过上面两个功能来禁用菜单选项。
  在用户交互方面更加友好。

alt

  根据上面的代码逻辑,没有选中资源不会出现选项。

alt

  选中资源没有选择场景的对象也无法执行。
  普通 entry 也可以接入 script_object 来扩展上述的功能。


  icon 图标接入 python 下可以通过 set_icon 或者 get_icon 里面构建 ScriptSlateIcon 对象来实现配置。
  但是 Python 下无法注册自定义的图标,只能用引擎内置的图标。

alt

  引擎内置图标可以参考 SlateEditorStyle.cpp 脚本。
  里面有大量引擎的内置图标。

alt

  查看 C++ 的源码调用可以看到大部分调用都是诸如 FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.CreateEventBinding") 的形式。
  后面的命名已经知道了,关键是 FEditorStyle::GetStyleSetName() 这个 set 的名称是啥。
  一开始我尝试在 Python 下不填写的,然而为空的话就什么图标都没有设置上。
  无奈只好做了一个 Unreal 蓝图节点打印一下这个字符串,返回的值是 EditorStyle
  所以官方的图标加上这个 Set 名称就可以用 Python 来调用了。

总结

  以上就是 ToolMenuEntryScript 的研究
  ToolMenuEntry 对象也有 script_object 可以进行设置,因此可以设置起来很灵活。
  这些功能 ToolMenuEntryScript ToolMenuEntry 都是专门给 Python 扩展提供的类,因此和 C++ 的扩展方式是不太一样的。