TA Python Tools¶
一款努力让“开发虚幻引擎编辑器工具”如同“开发Max脚本工具”一样简单的插件
Extended Python Editor interfaces
Overview¶
TAPython是一个虚幻引擎的工程插件,通过TAPython,可以快速为Python工具创建菜单、基于UE原生Slate的界面,同时该插件提供了160+个常用的编辑器工具接口,使得开发UE编辑器工具变得非常简单和高效。
功能特色¶
- 使用UE4原生Python
- 动态创建UE Slate控件窗口,支持39+控件类型
- 可配置的主菜单/工具栏/Content Brower 菜单
- 类Slate语法的界面描述文件,动态实时预览界面效果
- 不改引擎,无需Editor UMG支持,兼容低版本UE4
- 160+ 额外的编辑器常用接口
如何安装¶
依赖¶
本插件使用UE 内置Python插件:官方文档 Scripting the Editor using Python
安装步骤¶
- 从 TAPython release repo @github 页面右侧的release中下载对应版本的插件,并解压到<Your_UE_Project>\Plugins
Your_UE_Project
├── Content
├── ...
└── Plugins
└── TAPython # <--- 插件放这里
├── Binaries
├── Config
└── Content
└─ ...
- 启动工程, 打开项目设置 - 插件 python - additional path, 将 <Your_UE_Project>/TA/TAPython/Python 添加到addition path. 重启编辑器
- 当点击主菜单上的Sketch或者Gallery工具后,点击:
正确情况应该能看到如下图的绿色标志,和“Python Path Ready” 字样
如看到红色叉叉,请检查上面的设置项。正确的情况下,看到的是应是如下绿色的提示
快速开始¶
在插件包中,默认包含了若干菜单项和4个演示用的工具
最新的DefaultResource也可以在DefaultResources@github 下载
菜单项¶
- 右键选中目录或空白处时 Content Browser 中的右键菜单
- 右键选中资源时 Content Browser 中的右键菜单
- 主菜单项
- 工具栏上的图标
Sketch Tool 工具¶
Sketch Tool 是一个特别的界面草稿工具,当 <Your_UE_Project>\TA\TAPython\Python\ChameleonSketch\ChameleonSketch.json 这个文件被修改时,界面的内容会实时更新。这个在编写工具界面时候会非常有用,它把调整界面布局和参数的时间降低到最小。
默认的Sketch Tools 长成这样,打开ChameleonSketch.json 修改其中的内容试试,不用担心json中的语法和关键字。json和slate的语法关系在下文会由介绍
范例工具¶
以下所有的范例工具都是用这个插件TAPython的功能和Python编写的
Tool 1: MinimalExample 最小范例¶
这是工具演示了,创建标准的UE Slate界面,界面调用Python代码,Python代码中完成计数,并将结果反馈给界面。
这个工具的一共包括了一个30行的.json文件,一个一个15行的python文件
在下文中,我们将这种通过本插件创建Slate的界面的工具统称为Chameleon Tools
MinimalExample.json:
{
"TabLabel": "Example",
"InitTabSize": [200, 123],
"InitTabPosition": [680, 150],
"InitPyCmd": "import Example; chameleon_example = Example.MinimalExample.MinimalExample(%JsonPath)",
"Root":
{
"SVerticalBox":
{
"Slots": [
{
"SButton": {
"Text": "Click Me",
"HAlign": "Center",
"VAlign": "Center",
"OnClick": "chameleon_example.on_button_click()"
}
},
{
"SEditableTextBox":
{
"IsReadOnly": true,
"Aka": "InfoOutput",
"Text": ""
}
}
]
}
}
}
MinimalExample.py
# -*- coding: utf-8 -*-
import unreal
from Utilities.Utils import Singleton
class MinimalExample(metaclass=Singleton):
def __init__(self, jsonPath:str):
self.jsonPath = jsonPath
self.data = unreal.PythonBPLib.get_chameleon_data(self.jsonPath)
self.ui_output = "InfoOutput"
self.clickCount = 0
def on_button_click(self):
self.clickCount += 1
self.data.set_text(self.ui_output, "Clicked {} time(s)".format(self.clickCount))
Tools 2 Shelf 工具栏¶
Shelf 是一个快捷栏工具演示,类似于Maya的shelf工具。
用户可以把多种类型的内容拖拽到工具栏中,点击按钮,可以执行对应的功能
Type | Action |
---|---|
asset | 在content Brower中选中该资源 |
folder | 在Content Brower中进入该目录 |
actors | 在场景中选中这些actors |
text(python snippet) | execute as python code |
chamelon工具的json文件 | 打开Chameleon 工具 |
当然你也可以修改点击的这些按钮的行为,做出更丰富的工具
Tool 2 Object Detail Viewer 物体详细信息查看工具¶
Object Detail Viewer 是一个快速现实物体内属性及其数值的工具,双击可以进入其子属性查看子属性的数值。并且支持两个物体之间的比较,这对快速熟悉UE UObject对象是很有帮助的。该工具主要演示SListView的使用
Tool 3 Chameleon Gallery 控件大全¶
Gallery 工具演示了常用的控件及其在json文件中的写法,其他具体支持的控件和API可以参考here
使用文档¶
Entry 入口¶
所有菜单项和菜单的配置入口在 <Your_UE_Project>\TA\TAPython\UI\MenuConfig.json 这个文件中。
添加菜单项¶
下面这个MenuConfig.json中的片段将在主菜单中创建过一个按钮
```
"OnMainMenu":
{
"name": "Python Menu On Main Menu",
"items":
[
{
"name": "TA Python Example",
"items": [
{
"name": "Example (4): Waiting for your tools",
"command": "print('Hello world')"
}
]
}
]
},
```
Keywords in MenuConfig.json:¶
"OnSelectFolderMenu": ContentBrower中选中目录,或点击空白区域时右键菜单入口
"OnSelectAssetsMenu": ContentBrower中选中资源时右键菜单入口
"OnMainMenu": 主菜单中的菜单项入口
"OnToolbar": 主工具栏菜单入口,图标为Python,通常只在其中放置没有界面的python 工具
"OnToolBarChameleon": Chameleon 工具图标入口,图标是个绿色的变色龙,通常在其中放置有界面的Chameon 工具
"items": Array 类型,其中的各元素为子菜单项,可嵌套成树状
"name": 菜单项显示名
"command": 绑定到菜单项的python代码,支持import文件,并调用其中的函数
"ChameleonTools" 需要调用的Chameleon Tools是json文件相对路径
"ChameleonTools": "../Python/Example/MinimalExample.json"
"enabled": 是否启用该菜单项,设置为false时会隐藏该菜单项
"canExecuteAction": Python Code,该菜单项是否可被执行,用于对根据上下文(例如选中不同的资源),设置菜单项是否可被执行
"tooltip": 鼠标悬停时的工具提示
创建Chameleon Tools¶
该功能可以根据UI文件(.json)动态创建使用原生Slate代码的UE4编辑器界面。并将界面于Python工具代码绑定,实现数据的双向互通。无需编译,可实时预览。
支持的控件¶
当前支持41个常用控件,后续还在持续添加中。
C++ Slate链式编程语法转Json Slate的方法¶
简单来说有以下几条规则:
-
省略SNew,直接写控件名,SAssignNew(ButtonPicture, SImage); 转换成"SImage":{"Aka": "ButtonPicture"}
-
对于通过 "SAssignNew"来赋值的控件,使用"Aka" 关键字来替代。例如:SAssignNew(ButtonPicture, SImage) 将变成 "SImage":{"Aka": "ButtonPicture"}
-
Slate中支持单个子组件的Widget中的 [] 转换成 "Content":{ }
-
支持多个Slots的Widget中的 +SSomewidget::Slot 转换成 "Slots": [{...}, {...} ...], 每个Slot中的子控件为Slots数组中的一个JsonObjectValue
-
从Style中获取Brush的写法,将转换成Style和Brush两个值
-
Vector2, Vector4 转换成数组形式 如[1,2,3,4]
例如:
C++ code:
SNew(SBorder)
.BorderImage(FEditorStyle::Get().GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(SSpacer)
.Size(FVector2D(100, 50))
]
等同于 json code:
"SBorder":{
"BorderImage":
{
"Style": "FEditorStyle",
"Brush": "ToolPanel.DarkGroupBorder"
},
"Content":
{
"SSpacer": { "Size": [100, 50] }
}
}
另一个例子, c++ Slate code:
SNew(SGridPanel)
.FillColumn(0, 0.5f)
.FillColumn(1, 0.5f)
+ SGridPanel::Slot(0, 0)
[
SNew(STextBlock)
.Text(LOCTEXT("SBorderLabel", "SBorder"))
]
+ SGridPanel::Slot(1, 0)
.Padding(0.0f, 4.0f)
[
SNew(SBorder)
[
SNew(SSpacer)
.Size(FVector2D(100, 50))
]
]
等同于:
"SGridPanel":
{
"FillColumn": [[0,0.5],[1,0.5]],
"Slots":
[
{
"Column_Row": [0,0],
"STextBlock": { "Text": "SBorder" }
},
{
"Column_Row": [1,0],
"SBorder":
{
"Content":
{
"SSpacer": { "Size": [100, 50] }
}
}
}
]
}
其他具体可参见 控件大全 中的示例及范例中的实际应用,当然也可以联系我
Slate 控件与Python之间的通信¶
以MinimalExample 为例,来看下具体是如何实现的
- 在MenuConfig.json中,添加了一个名为"Minimal Example"的菜单项,点击它是会调用 "../Python/Example/MinimalExample.json" 中定义的工具
"OnToolBarChameleon": {
"name": "Python Chameleon on toolbar",
"items": [
{
"name": "Minimal Example",
"ChameleonTools": "../Python/Example/MinimalExample.json"
}
]
}
- 当点击步骤1中的菜单项时,在 MinimalExample.json 中,"InitPyCmd"中的内容将被当作python代码来执行。此时会创建一个 python 类:MinimalExample的实例,并将它保存在变量chameleon_example中。注意这个变量现在在python的全局空间中,所以不同的工具要使用独特的,不容易与其他全局变量重名的变量名
"InitPyCmd": "import Example; chameleon_example = Example.MinimalExample.MinimalExample(%JsonPath)",
- Chameleon Tool的基类,为 Utilities.Utils中的Singleton 单例。并在构造函数获取传入的Json文件的路径。该路径会作为该工具的唯一标识符,用于获取该工具的ChameleonData实例。同时该ChameleonData会保存在工具的变量"self.data"中, "self.data" 是重要的中介,用于和界面控件的通信,包括获取和设置控件属性等。
from Utilities.Utils import Singleton
class MinimalExample(metaclass=Singleton):
def __init__(self, jsonPath:str):
self.jsonPath = jsonPath
self.data = unreal.PythonBPLib.get_chameleon_data(self.jsonPath)
- 在按钮被点击是,"OnClick"中的内容,会被执行。此时 MinimalExample 中的 on_button_click会被调用。
"OnClick": "chameleon_example.on_button_click()"
- "on_button_click" 函数中,会完成按键计数,并将结果通过步骤2中提到的 "self.data" 返回给界面
def on_button_click(self):
self.clickCount += 1
self.data.set_text(self.ui_output, "Clicked {} time(s)".format(self.clickCount))
在这个例子中,我们通过"self.data.set_text"修改了界面中的文字,用类似的方法,也可以获取和设置界面上的其他内容。其他更多的API可以参看 ChemeleonDataAPI
扩展的编辑器Python接口¶
本插件扩展了 100+ python 可调用的接口, 包括各种消息窗口,资源修改,编辑器命令等的.
完整的文档在这里
使用快捷键¶
- 修改HotkeyConfig.json中配置的内容,将ChameleonTools,或者一段Python代码绑定到快捷键上
../TA/TAPython/UI/HotkeyConfig.json
{
"Hotkeys":
{
"HotkeyA": {
"ChameleonTools": "../Python/ChameleonGallery/ChameleonGallery.json"
},
"HotkeyB": {
"command": "unreal.EditorLevelLibrary.set_selected_level_actors([actor for actor in unreal.EditorLevelLibrary.get_all_level_actors() if len(str(actor.get_name())) > 60])"
},
"HotkeyC": {
"command": "print('Hotkey C')"
},
"HotkeyD": {
"command": "print('Hotkey D')"
},
"HotkeyE": {
"command": "print('Hotkey E')"
}
}
}
- 在ProjectSetting - Keyboard Shortcuts 中的TAPython Plugin中指定快捷键
在这个例子中,当按下 "Alt + Shift + G"时,就会打开"ChameleonGallery" 工具
Configs¶
<Your_UE_Project>TA\TAPython\Config\config.ini¶
[Settings]
MenuConfigFilePath=/TA/TAPython/UI/MenuConfig.json
ChameleonDataFolder=/Game/TA/ChameleonTools
[Advanced]
MainbarExtensionHookName=Game
MainMenuExtensionHookName=WindowLayout
MenusOnToolbarEnabled=True
SketchToolsEnabled=True
名称 | 用途 |
---|---|
MenuConfigFilePath | 工具配置文件的总入口 |
ChameleonDataFolder | 废弃了 |
MainbarExtensionHookName | 主工具栏图标位置 |
MainMenuExtensionHookName | 主菜单项创建的位置 |
MenusOnToolbarEnabled | 是否显示主工具栏上的菜单项 |
SketchToolsEnabled | 是否启用Sketch工具,谁会想要关掉这么好的功能呢?Doge |
<Your_UE_Project>\Plugins\TAPython\Config\Plugin_Config.ini¶
[Advanced]
CopyInitialResource=True
名称 | 用途 |
---|---|
CopyInitialResource | 是否将初始内容包拷贝到工程目录 |
当插件启动时,如果在工程目录中找不到"TA"目录,就会将<Your_UE_Project>\Plugins\TAPython\Resources\DefaultPythonSource 目录中的初始资源拷贝到工程目录下,以确保插件能够有基本的功能和正常运行
强烈建议不要修改这个选项,除非你是高手,使用初始包作为开始,然后修改和添加i自己的工具,是快速熟悉这个插件最快的方法。
FAQ¶
Q0. 支持UE4吗?¶
A: 支持, 事实上这个插件是从4.21开始开发的. 如果不出意外,很快将放出4.26和4.27版本的插件.
Q1. 打开工程时遇到如下弹窗提示¶
这是因为本地工程使用的引擎的BuidID,与我发布这个插件时使用的引擎不同。
可以通过修改插件中的BuildId来避免弹窗,前提是引擎的大版本与发布的插件版本相同。
具体步骤步骤来处理(当然,如果你的引擎改了很多的底层代码,比如修改了CreatePackage的函数签名,那就无法用这个方式来解决了)
1. 在上面的弹出对话框中选"否"
2. 找到当前使用的引擎的BuildId,具体做法:用文本工具打开
{
"BuildId": "16433597",
"Modules":
{
...
}
...
}
```
3. 打开<Your_UE_Project>\Plugins\TAPython\Binaries\Win64\UnrealEditor.modules(UE4 工程的话是UE4Editor.modules).将其中**BuildId**项中的内容指定为步骤3 中获取的**BuildId**,保存文件. 重新打开工程即可
```json
{
"BuildId": "16433597",
"Modules":
{
"TAPython": "UE4Editor-TAPython.dll"
}
...
}
问题2. 执行菜单项后,没有反应¶
检查Project Setting - Plugin Pyhton 确保当前工程 <Your_UE_Project>/TA/TAPython/Python 目录已经被添加到了additional python path中 Steps 这里
检查方法:
- 打开Chameleon Gallery,在窗口的最上方应该能看到绿色对勾和Python Path Ready的字样
- 在Python console窗口中,执行import Example后,应没有任何报错
Q3. 这个插件是否包含引擎内的python编辑器?¶
A: 不包含. Pycharm 社区版和 VS Code 已经非常强大了, 用它们可以搞定开发中的一切需求
Q4. 如何调试¶
A: 可以通过这个帖子中的方法和使用VSCode进行调试 HowToDebugChameleon.
Q5. 其他还有那些文档?¶
下面这些应该会有帮助
提供支持和反馈¶
本插件,现在为免费试用。其中DefaultResources为开源内容。这个仓库的使用 MIT license
- 任何建议,意见都是受欢迎的
- 如果在使用过程中,遇到困难,或者问题,请将问题描述,截图,log一并发送给我
- 如果你在浏览本网页的英文版内容的时,如果发现任何英文的歧义或者语病,也非常欢迎联系我