This is a plugin which tries hard to make Unreal Editor Tools As Easy As Possible.
TAPython is an editor plugin for Unreal Engine. It provides a framework for creating python editor tools in Unreal Engine, and live Slate editing for developers, which makes creating menus and UE native Slate UI much easier and faster(without any compiling time or restart editor). The plugin also provides 200+ editor tool interfaces to use, making developing UE editor tools very simple and efficient.
Thank you, TAPython's stargazersβ¨.π
The expample project of the "Splinter_Button" above is here:
https://github.com/cgerchenhp/TAPython_ButtonDivision_Example
The biggest change in TAPython v1.1 is the addition of a feature that allows widgets to be directly added, inserted, and deleted through Python code. With this feature, we can dynamically add widgets to the tool during runtime. This function is particularly useful for displaying widgets of an unknown quantity.
- Added
chameleon_data_instance.set_content_from_json
, which is used to set sub-widgets forSBox
,SBorder
,SCheckBox
,SBox
, andSButton
components. - Added
chameleon_data_instance.append_slot_from_json
, which is used to add sub-widgets to Slots forSHorizontalBox
,SVerticalBox
,SScrollBox
,SGridPanel
,SUniformGridPanel
,SUniformWrapPanel
,SOverlay
,SCanvas
, andSSplitter
. - Added
chameleon_data_instance.insert_slot_from_json
, which is used to add sub-widgets at a specified Slot index forSHorizontalBox
,SVerticalBox
. - Added
chameleon_data_instance.remove_widget_at
, which is used to remove the widget at the specified location. This is applicable to all the widgets mentioned above. - Added
chameleon_data_instance.get_all_akas
, which is used to get all Aka names in the chameleon tool. - Added
chameleon_data_instance.get_widget_path
, which is used to get the Slate path of the widget through its Aka name.
In the past two months, TAPython has completed the update of the initial version of the document, and the subsequent documents will be iterated on the existing basis.
The document address in the plugin is updated to the new url: https://www.tacolor.xyz/tapython/welcome_to_tapython.html
- Add "Modal Window", available options: InitTabSize, SizingRule (UserSized, FixedSize, Autosized), TabLabel, SupportsMinimize, SupportsMaximize, IsFloatingWindow. For details, please refer to: Modal Window
- Add the "%SelectionType" field to the OnSelectionChanged of SComboBox. Valid values for the field are: "OnKeyPress", "OnNavigation", "OnMouseClick", "Direct"
- Add support for Font in SMultiLineEditableTextBox
- Add support for ForegroundColor in SMultiLineEditableTextBox
- Add support for ColorAndOpacity in SMultiLineEditableText
- Add support for Font in SEditableTextBox
- Add support for ColorAndOpacity in SEditableTextBox
- Add support for TextStyle in SEditableText, SEditableTextBox, SMultiLineEditableText, and SMultiLineEditableTextBox
- Add support for VAlign and HAlign in SGridPanel
- Add support for BackgroundColor in SEditableTextBox and SMultiLineEditableTextBox
- Set the default
VAlign
of the middle element in SHeader toCenter
- Set the maximum refresh rate for
OnTick
to 60hz - Modify the log level when some Widget properties are missing
- Fix the false warning of unhandled
VAlign
andHAlign
in SCanvas
- Add ModalWindow example resource "./ChameleonGallery/example_modal_window.json"
- Remove the "IsModalWindow" field originally in "ChameleonGallery.json". This field will be exclusively used for "ModalWindow"
- Add "DisUnrealStub.py" to separate the huge unreal.py Stub file into individual files by class for easier viewing and code completion in PyCharm and similar tools, see here
- Modify the default size of Chameleon Sketch to avoid scrollbar's flicker in some cases
-
Add
unreal.ChameleonData.snapshot_sketch
command for capturing the current Sketch panel -
Add
chameleon_data_instance.get_top_scroll_box_offsets(json_path)
for getting the offset of the top scroll box in Chameleon Tool. -
Add
chameleon_data_instance.get_scroll_box_offsets(aka_name)
for getting the offset of the scroll box in Chameleon Tool with the given name. -
chameleon_data_instance::set_image_from_path(aka_name, image_file_path)
supports using absolute paths -
Add SetMinAspectRatio/SetMaxAspectRatio for SBox
-
Add
chameleon_data_instance.set_min_aspect_ratio
andchameleon_data_instance.set_max_aspect_ratio
for setting the min/max aspect ratio of the given SBox
- Add
unreal.PythonBPLib.get_class_path_name
for getting the path name of the given object's class - Add
unreal.PythonBPLib.get_viewport_linear_color_pixels
for getting the pixels of the viewport as a linear color array unreal.PythonBPLib.exec_python_command
, addforce_game_thread
option to allow Python code to execute on the main thread. When we execute code in a sub-thread, if we need to modify the UI content, we can specify to modify it in the main thread through theforce_game_thread
option (the UI content can only be modified in the Game thread).
- Fix the issue with the incorrect IsAltDown behavior in
unreal.PythonBPLib.get_modifier_keys_state()
The Intermediate directory is added to the package and includes UnrealEditor-TAPython.lib (UE4Editor-TAPython.lib in UE4) to make compatibility with the automated build system. At the same time, add the corresponding .dll for DebugGame mode.
Adding support for SWebBrowser allows you to embed WebBrowser in the tool window, which can be helpful in some situations, such as embedding the internal pipeline tool in the python tool in Unreal Editor.
Using the SWebBrowser widget, the web browser plug-in is required. It is disabled by default. We must enable the plug-in before using it
-
Added "SizeRule" attribute for the SSplitter widget. Optional values are "FractionOfParent" and "SizeToContent",
-
And more attributes for SColorBlock and SColorPicker
- GetVisibility
Get the current visibility status of the widget.
- Set/GetColor
They are used for getting and setting the color of the widget.
More APIs for SWebBrowser widget though ChameleonData.
- LoadURL
- GetURL
- LoadPageFromString
- ReloadPage
- GetTitleTextOfPage
- IsPageLoaded
- IsPageLoading
- CanGoBack
- GoBack
- CanGoForward
- GoForward
- BindUobjectToBrowser
- UnbindUobjectToBrowser
- The tool's wind can be set with "IsModalWindow" or "HasMinimizeMaximizeButton" to hide the maximize button.
If IsModalWindow is set to True, Tab is still a nomad type and we can still dock to other Windows.
Known issue: the maximize button reappears after the window is floated from the docked window.
- Add "HasSection" attribute, which defaults to True, used to hide the Section text above the menu item when creating a menu with ToolMenus Anchor.
As the Material Editor, we can add custom menus for Physics Asset Editor and Control Rig Editor now.
"OnPhysicsAssetEditorMenu": {
"name": "Python Menu On Physics Asset Editor",
"items":
[
{
"name": "TA Python Physics Asset Example",
"items": [
{
"name": "Print Physics Asset",
"command": "print(%f)"
}
]
}
]
}
We can add a TAPython menu where the UE ToolMenus can.
"ControlRigEditor.RigHierarchy.ContextMenu": {
"name": "Python Menu On Control Rig Editor",
"items": [
{
"name": "Rigging Tools",
"command": "print('Rigging Tools')",
"icon": {
"style": "ChameleonStyle",
"name": "Resources.Chameleon_32x_png"
}
}
]
}
And we can add a context menu for object's component in Detail views.
Kismet.SubobjectEditorContextMenu: {
...
}
TAPython.RefreshToolMenus
"TAPython.RefreshToolMenus" can be used to refresh the "ToolMenus" menus, other menus will be auto-refreshed and not need this command
- GetModifierKeyState
GetModifierKeyState Get the modifier key states(Ctrl, Shift, Alt, etc.), so we used it to display an optional dialog or menu.
- SnapshotDetails
We can tank a snapshot of the entire Details window via 'snapshot_details'. The file will be saved to <Your_project>\Saved\Screenshots\WindowsEditor\ObjectDetailProperties. Note we need to make sure the focus is on the Details window.
- CancelDelayCallById
Cancel the specified DelayCall by ID.
We got a new editor library: PhysicsAssetLib, as its name, it's for PhysicsAsset Editing.
Function Name | Description | |
---|---|---|
get_selected_bodies_indexes | Get the indexes of the selected bodies in Physics Asset Editor | |
rotate_selected_body | Set the rotation of the selected body in Physics Asset Editor | |
rotate_selected_constraint | Set the rotation of the selected constraint in Physics Asset Editor | |
get_body_center | Get the center value of the specified body | |
set_body_center | Set the center value of the specified body | |
get_body_rotation | Get the rotation value of the first body | |
get_bodies_rotations | Get the rotation value of the first body | |
set_body_rotation | Set the rotation value of the specified body | |
get_body_radius | Get the Radius value of the body | |
set_body_radius | Set the Radius value of the body | |
get_body_length | Get the rotation value of the first body | |
set_body_length | Get the rotation value of the first body | |
get_body_size | Get the Size value of the box body | |
set_body_size | Set the Size value of the box body | |
scale_body | Scale the specified body | |
get_edited_physics_assets | Get all PhysicsAsset currently being tracked with open editors | |
get_physics_asset_from_top_window | Get the PhysicsAsset from the top opened editor window. | |
get_selected_item_names | Get all the selected items name in PhysicsAsset editor window. | |
select_body_by_name | Select the Body by name in PhysicsAsset editor window. | |
select_body_by_names | Select the Bodies by name in PhysicsAsset editor window. | |
select_shape_by_name | Select the Shape by name in PhysicsAsset editor window. | |
select_shape_by_names | Select the Shapes by name in PhysicsAsset editor window. | |
select_constraint_by_name | Select the constraint by name in PhysicsAsset editor window. | |
select_constraint_by_names | Select the constraints by name in PhysicsAsset editor window. | |
add_constraints | Add constraint to specified bodies | |
get_skeleton_hierarchy | Get the bones hierarchy | |
get_bodies_hierarchy | Get all the bodies names and their parent bone's index | |
get_constraints_names | Get all the constraint's display names of PhysicsAsset | |
get_bone_indexes_of_constraint | Get the parent and child bone's indexes of the specified Constraint | |
get_bone_index_from_body | Get the first Body under the specified bone | |
get_bodies_from_bone | Get the Bodies under the specified bone | |
get_constraint_instance_accessor | Get the ConstraintInstanceAccessor from PhysicsAsset | |
reset_constraint_properties | Reset the specified Constraint's values | |
update_profile_instance | Update the Profile according to the specified Constraint | |
break_constraint_accessor | Get the Owner and Constraint Index from ConstraintInstanceAccessor |
- The "Margin" of STextBlock is not working.
- The "OnTextChanged" and "OnTextCommitted" callback are not working when the input text is empty. (delete the text with backspace)
A new editor lib PythonTestLib has been added to TAPython to complete the test cases of all the extended APIs.
In the test cases repo UE_TAPython_Plugin_TestCases, more than 200 PythonLib APIs has been tested.
Now we can get the contents of the Output Log, which we can use to validate the operation result from the editor.
Note that Logs are the same content as Output Log in the editor, but they are separate. Clearing Log in Output Log will not affect what PythonTestLib.get_log() returns, and vice visa
A new setting parameters LogNumberLimit in Config.ini will limit the maximum number of log buffers. The default size is 10240.
In the test case, I used delay_call, pushing the python scripting, then waiting for the editor to complete its asynchronous tasks, or waiting for the window to refresh, and so on.
Add "OnMapChangedCmd" to the Chameleon tool for executing Python commands when changing maps.
Usage:
- Clean references in Chameleon tool when unload map to avoid memory leaks
- Sync the UI when changing map
For example, I fixed the crash when using ObjectDetailViewer tool and then loading another level, as the queried object will referenced by ObjectDetailViewer. :-(
"OnMapChangedCmd": "chemeleon_objectDetailViewer.on_map_changed(%map_change_type)",
def on_map_changed(self, map_change_type_str):
# remove the reference, avoid memory leaking when load another map.
if map_change_type_str == "TearDownWorld":
self.reset(bResetParameter=False)
else:
pass # skip: LoadMap, SaveMap, NewMap
-
%world: Get the world of map operation
-
%map_change_type: Get the operation type of changing map, "LoadMap", "SaveMap", "NewMap" or "TearDownWorld"
We can use SDetailViewer for showing the object properties.
- set_object to SDetailsView
-
Add "AlwaysShowScrollbars" bool field in SMultiLineEditableTextBox
-
Add ScrollTo function, for scrolling the scroll bar to the specified location
Add SetColorAndOpacity support for SScrollBox/SImage/STextBlock/SEditableText
- remove incorrect waring logs when OnContextMenuOpening in SEditableTextBox was set.
- Fix PythonBPLib.SetFolderColor not immediate apply the color with existing directories
- Add more logs for PythonBPLib.SaveThumbnail.
- Remove redundant /All/Game", "/All/EngineData/" in the return value from PythonBPLib.GetSelectedFolder
- Fix PythonBPLib.SetSelectedFolder not work.
- Fix crash when param "comp" is null when calling PythonBpLib.set_anim_blueprint
- Fix PythonDataTableLib.SetPropertyByStringAt not work when "quote" in input values.
- Fix PythonBPLib.FixupRedirectorsInFolder not work when input value is a string.
- Fix create_landscape_proxy not work when SectionSize = 1
- Add Optional parameters QuadsSpaceOffsetX/Y for create_landscape_proxy_with_guid
- Fix crash when input value "asset_input_data" is null when calling PythonMeshLib.get_imported_original_mat_names.
- Fix crash when input value "socket" is null when calling PythonMeshLib.set_static_mesh_socket_name.
- Fix typo PythonMeshLib.get_selection_cast_shadow
- Add Deprecated warning in some PythonLib APIs to warn that some functions can use ue engine native functions instead.
- Add return value for PythonMeshLib.convert_mesh_to_static_mesh
TAPython released its first version of MacOS Monterey (v1.0.8 for UE 5.0.3), although there are far fewer Unreal developers on the MAC than PC. If you have any problems, please let me know.
Now, we can add the global context menu of the Chameleon Tool by adding "OnTabContextMenu" in the MenuConfig.json.
For example, the following example adds a menu item named "Reload This Tool" to all Chameleon Tools. The tool will re-launch when the user clicks the menu. If we use this method to reload the python module when we open the tool, we can quickly reload both the interface and python logic, which is very convenient when developing the tools.
MenuConfig.json:
"OnTabContextMenu":{
"name": "TA Python Tab",
"items": [
{
"name": "Reload This tool",
"command": "unreal.ChameleonData.request_close(%tool_path); unreal.ChameleonData.launch_chameleon_tool(%tool_path)"
}
]
}
Each Chameleon Tool can also add its own context menu. The way of adding menu is similar to the Global Context Menu: add the "OnTabContextMenu" subitem in the Json file of tool's json file, and add the menu content to it.
For example, add a custom context menu for MinimalExample
{
"TabLabel": "Example",
"InitTabSize": [200, 123],
"InitTabPosition": [180, 200],
"InitPyCmd": "import Example; chameleon_example = Example.MinimalExample.MinimalExample(%JsonPath)",
"Root":
{
...
},
"OnTabContextMenu":{
"items": [
{
"name": "Reset Click Count",
"command": "chameleon_example.reset_click_count()"
}
]
}
}
Or a menu item that switches the tool to "Development Mode" for your tool.
Tips:
- These new context menu only support UE5, now
- OnTabContextMenu also support sub menu items
One of the most important features in this release is the addition of support for the Material Editor.
Now we can add custom menu items directly to the material editor and pass the material instance that we are currently editing to the python script so that we can "play with" the material nodes directly in python.
The %asset_paths in the following example will be replaced by the TAPython with an array of paths to the material currently being edited, which usually has only one element.
With the APIs added to PythonMaterialLib in this release, we can fully script the material expression nodes via Python.
MenuConfig.json:
"OnMaterialEditorMenu": {
"name": "Python Menu On Material Editor",
"items":
[
{
"name": "TA Python Material Example",
"items": [
{
"name": "Print Editing Material / MF",
"command": "print(%asset_paths)"
},
{
"name": "Log Editing Nodes",
"command": "editing_asset = unreal.load_asset(%asset_paths[0]); unreal.PythonMaterialLib.log_editing_nodes(editing_asset)"
},
{
"name": "Selected Nodes --> global variable _r",
"command": "_r = unreal.PythonMaterialLib.get_selected_nodes_in_material_editor(unreal.load_asset(%asset_paths[0]))"
}
]
}
]
},
Now we can calculate the size of all content in the whole ScrollBox from the Offset, ScrollOffsetOfEndοΌViewFractionοΌViewOffsetFraction, etc. Then use SnapshotChameleonWindow to capture the contents of the entire tool window, including the parts of ScrollBox that are not shown.
Add %widgetPath keyword in JSON
It will pass the widget path of the current clicked button to python code, so we can figure out which SButton was clicked, when we import the External JONS file multi-times.
-
When we need to remind the user to a specified tool, we can use the flash_chameleon_window.
We can capture the contents of the entire chameleon tool window, including the parts of ScrollBox that are not shown.
For example, the ChameleonGallery tool that comes with the plugin is over 3,000 pixels height and wrapped in ScrollBox, which we can also save as an image at once.
The following code will calculate the size of the contents in the entire tool window, then take the snapshot.
def get_full_size_of_this_chameleon(self):
current_size = unreal.ChameleonData.get_chameleon_window_size(self.jsonPath)
scrollbox_offsets = self.data.get_scroll_box_offsets(self.ui_scrollbox)
height_full = scrollbox_offsets["ScrollOffsetOfEnd"] / (1.0 - scrollbox_offsets["viewFraction"])
height_full += 48 # add title bar
return current_size.x, round(height_full)
def on_button_Snapshot_click(self):
full_size = self.get_full_size_of_this_chameleon()
saved_file_path = unreal.ChameleonData.snapshot_chameleon_window(self.jsonPath, unreal.Vector2D(*full_size))
if saved_file_path:
unreal.PythonBPLib.notification(f"UI Snapshot Saved:", hyperlink_text = saved_file_path
, on_hyperlink_click_command = f'chameleon_gallery.explorer("{saved_file_path}")')
else:
unreal.PythonBPLib.notification(f"Save UI snapshot failed.", info_level = 1)
Now we can iterate, create, and modify Material Expression nodes of Material and Material Function with Python. Including the nodes that cannot be created or modified in the MaterialEditingLibrary. For example, connect properties to World Position Offset, add Get/SetMaterialAttribute nodes, etc.
For more details and examples of material expressions can be found here: How to manipulate Material Expressions Node in Material with Python in Unreal Engine
PythonMaterialLib | Description | Is New added |
---|---|---|
get_static_switch_parameter_values | Get the Static Switch Infos of material instance | |
set_static_switch_parameter_value | Set the Static Switch Infos of material instance | |
set_static_switch_parameters_values | Batch set the Static Switch's status of material instance. | |
get_mf_static_switch_parameter | Get the Static Switch Infos of material function. | |
get_static_parameters_summary | Get the numbers of each StaticSwitchParameter of material instance. | |
log_mat | Log out all the connections in the material | Yes |
get_material_expressions | Log out all the Material Expressions in the material | Yes |
get_all_referenced_expressions | Get Material Expressions in the material with specified feature level | Yes |
get_material_connections | Get all the connections in the material | Yes |
get_material_function_connections | Get all the connections in the material function | Yes |
get_material_expression_input_names | Get the input pin's names of the material expression | Yes |
get_material_expression_output_names | Get the output pin's names of the material expression | Yes |
get_material_expression_captions | The captions of the material expression | Yes |
set_shading_model | Set the shading model of the material, for the hidden shading model | Yes |
get_material_expression_id | Get the ParameterExpressionId of the material expression. | Yes |
log_mf | Log out all the connections in the material function | Yes |
get_material_function_expressions | Get all the expressions in the Material Function | Yes |
get_material_function_output_expressions | Get all the output expressions in the Material Function | Yes |
get_selected_material_nodes | Get the selected nodes in material editor. | Yes |
log_material_expression | Log Detail information of the MaterialExpression, include inputs, outputs etc. | Yes |
log_editing_nodes | Log Detail information of the Material or Material Function | Yes |
get_selected_nodes_in_material_editor | Get the selected nodes in material editor. | Yes |
get_hlsl_code | Get the HLSL code of the Material | Yes |
get_shader_map_info | Get the ShaderMaps infos in string format. | Yes |
get_material_content | Get the material's content in JSON Format | Yes |
get_material_function_content | Get the material function's content in JSON Format | Yes |
connect_material_expressions | Create connection between two material expressions | Yes |
disconnect_expression | Disconnection the material expression's input | Yes |
connect_material_property | Connect a material expression output to one of the material property inputs (e.g. diffuse color, world position offset etc) | Yes |
disconnect_material_property | Disconnect the material property input | Yes |
get_material_proper_str_from_guid | Get EMaterialProperty in string format from a guid | Yes |
gen_guid_from_material_property_str | Generate a Guid from EMaterialProperty | Yes |
add_input_at_expression_set_material_attributes | Add an Attribute Get Type pin for material expression "GetMaterialAttributes" | Yes |
add_output_at_expression_get_material_attributes | Add an Attribute Get Type pin for material expression "GetMaterialAttributes" | Yes |
Add Mouse Event for SImage
- OnMouseMove
- OnMouseEnter
- OnMouseLeave events
With the three mouse events, our python code can use them to perform more complex operations based on the user's mouse input in SImage.
The %uv, %mouse_flags in the following example will be automatically replaced with the UV coordinates of the mouse in SImage and the pressed state of the left, middle and right mouse button
{
"SImage": {
"DesiredSizeOverride": [200, 200],
"Aka": "ImageCanvas",
"OnTick": "your_tool.on_tick()",
"OnMouseLeave": "your_tool.on_mouse_leave(%mouse_flags)",
"OnMouseMove": "your_tool.on_mouse_move(%uv, %mouse_flags)"
}
}
The user's operation in SImage is taken as Stable Fluid function's input, then using result drive the volume cloud with set_render_target_data function of PythonTextureLibs.
-
Two new optional parameters in notifications were added, for adding a specify hyperlinks and the custom python function that executes when click. So we can quickly jump to a specific location or open a hyperlink.
More information and example about modify RenderTexture2D and SImage can be found here.
- PythonStructLib.get_guid_from_friendly_name not return the correct guid.
Added:
- Support Unreal Engine 5.0.3
- Support Unreal Engine 4.27.2
- Support Unreal Engine 4.26.2
- Add an optional parameter: "friendly name" to PythonStructLib.add_variable and PythonStructLib.add_directory_variable
- Better warning message for PythonDataTableLib.set_property_by_string when "row_name" or "column_name" not exists in datatable
Fixed:
- The Chameleon tab's reference not released when the project closes.
PythonEnumLib and PythonStructLib has been added to Python Editor Libs, PythonDataTableLib also adds more python/blueprint callable functions.
In short, we can use Python to do almost everything you did manually in the editor with User defined ENum, User Defined Struct and DataTable. More details and examples can be found here.
Support more slates:
Now we can create widge: SSplitter
And SExpandableArea
Two APIs was added in ChameleonData for SExpandableArea:
- bool GetIsExpanded(const FName AkaName)
- void SetIsExpanded(const FName AkaName, bool bExpanded, bool bAnimated=false)
data.get_is_expanded(aka_name) -> bool
Get the Expanded state of Specified SExpandableArea
note: Supported widgets: SExpandableArea.
note: added in v1.0.4
Args:
aka_name (Name): The aka name of the widget
Returns:
bool: Is Expanded or not.
data.set_is_expanded(aka_name, expanded, animated=False) -> None
Set the Expanded state of Specified SExpandableArea
note: Supported widgets: SExpandableArea.
note: added in v1.0.4
Args:
aka_name (Name): The aka name of the widget
expanded (bool): Is Expanded or not.
animated (bool): Expanded with animation or not.
Now we can add context menu in Outline window, with the "OnOutlineMenu" field in MenuConfig.ini.
"OnOutlineMenu": {
"name:": "Python Menu On OutlineMenu",
"items":
[
{
"name": "Print selected actors",
"command": "print(unreal.get_editor_subsystem(unreal.EditorActorSubsystem).get_selected_level_actors())"
}
]
},
The .png and.svg files in the plugin resource directory will be added to "ChameleonStyle" automatically. Then we can use it for menu items.
- We can specify the icon of a menu item with a relative path of the icon image in the plug-in resource directory.
{
"name": "Chameleon Shelf Tool",
"ChameleonTools": "../Python/ShelfTools/Shelf.json",
"icon": {
"ImagePathInPlugin": "Resources/briefcase_32x.png"
}
},
- Or use ImageBrush directly in the style. For instance, the image brushes in FEditorStyle, FCoreStyle
{
"name": "Minimal Example",
"ChameleonTools": "../Python/Example/MinimalExample.json",
"icon": {
"style": "ChameleonStyle",
"name": "Flash"
}
}
Now the Chameleon UI json file can reference other Json files. Nested references are supported, but circular references need to be avoided
{
"autoWidth": true,
"SBox": {
"WidthOverride": 480,
"Content": {
"ExternalJson": "ZeldaWorldMapEditor_Buttons.json"
}
}
}
- Reduce the complexity and size of a single json file
- reuse part ui code
- The UI json files becomes less intuitive and more obscure
- The Widget path logged in the console window is not the same as the Json crumb path shown in PyCharm. As PyCharm don't know that another json content has being "import" here.
- Put the repetitive ui code (such as 16x16 map buttons) or the ui code which generated by other script into an "external" json file.
The number of shortcuts that can be configured in ExitorSettings has now been increased to 10. It will be a configurable number in later version.
{
"SBorder": {
"BorderBackgroundColor": [1, 0.5, 0, 1],
"BorderImage":
{
"Style": "FEditorStyle",
"Brush": "ErrorReporting.EmptyBox"
}
}
}
- GetViewportPixels Now we can grab and get the content of viewport. Use it in tools widgets:
Or send it to other device, for example, I send the viewport content to my MacroKeyboard. I think this is the smallest screen which displays Unreal Engine viewport content :D
- ViewportRedraw
Force the viewport Redraw
- GetObjectFlags
We can get the EObjectFlags of a UObject.
-
GetLevelViewportCameraFov
-
GetActorsFromFolder Get the actors in Specified folder in outline
-
FindActorsByLabelName
Find the actor by it's "label name" not the "actor name"
- add LogOnTickWarnings in config.ini
LogOnTickWarnings=True
This option controls whether a warning is printed when the user uses the keyword OnTick.
ChameleonTools has a hidden keyword that has not been mentioned: "OnTick". The python code in it is executed during Slate updates, which are much more frequent than viewPort updates, So the py code can easily lower the editor's FPS.
"OnTick" is hidden because 99.9% of the time it is not needed and there are better ways to do it if there is a "real" need. So I don't recommend using OnTick and changing the LogOnTickWarnings setting.
-
Fixed RequestClose failing after Chameleon dock to another window.
-
Fixed unreal.PythonBp.get_all_objects crash, when some objects don't have "world"
-
Fixed the incorrect display of the Breadcrumb in Python Tool: ObjectDetailViewer
-
Fixed chameleonData.get_float_value failed with SSpinBox
-
Fixed incorrect Padding setting in SBox
- Use UE4 and UE5 native Python
- Create UE Slate UI dynamically, support 39+ Slate widgets.
- Configurable main menu/toolbar/Content Brower menu.
- Slate like syntax interface description file, real-time preview UI result, without any reload.
- Bind Python command to Slate UI widget, and change the UI content with python.
- No enging source code modified, compatible with lower versions of UE4(4.21, release later) and latest UE5
- 100+ Extra Editor Command for Python and Blutility.
This plugin use UE native Python Script Plugin. The Scripting the Editor using Python is also very useful.
- Download from TAPython release repo @github and unzip the plugin to <Your_UE_Project>\Plugins
Your_UE_Project
βββ Content
βββ ...
βββ Plugins
βββ TAPython # <--- Put Plugin Here
βββ Binaries
βββ Config
βββ Content
ββ ...
- Laungch project, open Project settings - Plugin Python - additional path, add <Your_UE_Project>/TA/TAPython/Python to additional path. then restart the editor.
- click the Gallery icon on main toolbar, you should see a green check box UI like below.
Green sign and text "Python Path Ready" will showing at the top of gallery.
If a Red Cross is displayed, check the Project Setting above.
The plug-in package contains several menu items and four demo tools by default.
The latest DefaultResources is here: DefaultResources@github
- Context Menu Items in Content Browser
- Context Menu Items for selected asset
- Menu Item in Main menu
- Menu icons on Mainbar
The Sketch Tool is a special ui design tool. When the<Your_UE_Project>\TA\TAPython\Python\ChameleonSketch\ChameleonSketch.json file is modified, the content of the ui will be updated immediately(see below gif). This can be very useful when writing tool interfaces, and will save a lot of time when tweaking the interface layout or parameters.
The default sketch tool looks like below. Try to modify the content of ChameleonSketch.json with any text editor, and save it. Don't worry about the json keywords and syntax, it's easy to learn and has lots of examples, will be described below.
All the 4 Example tools, are written with python, without any single line of c++ code.
This is a tool demonstrating the creation of a standard UE Slate UI with python and a json file. The Button calls Python code, then the python code sends the results(click count) back to the UI.
The tool includes a 30-lines Json file and a 15-lines Python file. In fact, it can be shorter.
I will call this kind of tool which creates Slate interfaces in this way "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))
Shelf is a Maya-like shortcut shelf tool, showing how to set visibility of widget and the usage of SDropTarget widget.
Users can drag and drop items to the shelf, and execute custom Python Code, launch Chameleon tool when clicking the item on the shelf.
Type | Action |
---|---|
assets | select saved assets in content Brower |
folder | enter saved folder in Content Brower |
actors | select saved actors in level |
textοΌpython snippetοΌ | execute as python code |
chamelon tool json file | launch the Chameleon tool |
You can modify the python code, and make it better.
Object Detail Viewer is an inspector Tool for UE object. It shows all the functions and property in any UObject. Double click the property will query the child property. The image above shows the detail values of Floor_14(actor).static_mesh_component.static_mesh.static_materials[0].
In compare mode, the differences of two UObjects will be highlighted. It's very useful for being familiar with all kinds of UObject.
Chameleon Gallery shows the most common widgets, and how to describe them in a json file. All the supported widgets and API documents can be found here
A: Yes, at the beginning this plugin was developed with UE 4.21. We have released this plugin for UE 4.26, 4.27, UE5.0EA, UE5.0Preview1.
This Plugin: TAPython is Free for use. The PythonDefaultResource is under MIT license.
- Any suggestions and comments are welcome. Please don't hesitate to leave your message.
- If you encounter difficulties or problems. EMail me with the problem description, screenshot and the log.
- If you find any English ambiguities or language errors on this page, please feel free to contact me as well.