cgerchenhp / UE_TAPython_Plugin_Release

Release page for UE TAPython Plugin
https://tacolor.xyz/pages/TAPython.html
GNU Affero General Public License v3.0
342 stars 35 forks source link

TA Python Tools

This is a plugin which tries hard to make Unreal Editor Tools As Easy As Possible.

TAPython WebSite

TAPython Documentation

Overview

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.

Tools Preview

Thank you, TAPython's stargazers✨.😄

Star History Chart

What's New

In latest v1.2.3

Support UE 5.4.4

Slate

PythonLevelLib

PythonLandscapeLib

AliasNames

Add Aliases field in the json file to set aliases. For example, in the following settings, you can use $this_tool in the settings to replace PCG_Bridge.PCG_Bridge.PCG_Bridge() later, and you can use $this_tool in the Json file settings to replace the content after it.

    "Aliases": {
        "$this_tool": "PCG_Bridge.PCG_Bridge.PCG_Bridge()"
    },

Improvement

Fix

Experimental

DetailPanelCustomization

Settings

Add the following settings to control the behavior of DetailPanelCustomization.

[DetailPanelCustomization]
IsDetailCustomizationEnabled=True
IsForceAddDetailCustomization=False
IsReusingWidget=False
ClassName=SomeClassA
ClassName=SomeClassB
ChameleonData

PythonBPLib

v1.2.2

Support UE5.4.1

Note for UE5.4

Unreal Engine 5.4 uses Python 3.11.8, so we need to install the third-party library of Python 3.11.8.

If you are using the default resources provided by the old TAPython, some of the code in the old ObjectDetailViewer is incompatible with 3.11.8. You can find the corresponding file in the DefaultResources of TAPython v1.2.2 and replace the original file. Or you can also find the corresponding file here

PythonTextureLib
Menus

The menu items created through the "MenuEntries" field will be automatically sorted

Fix

Experimental

Below is Experimental. It is only recorded here. There may be major changes later, and it is not recommended to use it in official tools.

Add the ability to modify the content of TextureArray (Experimental)

In latest v1.2.1

New Features

Define menu entry directly in Chameleon Tool's Json file

Add Define menu entry directly in Chameleon Tool's Json file feature. (In contrast, previous versions required defining menu entries in MenuConfig.json)

This feature is similar to the way Unity's MenuItem works, eliminating the need to define menu entries in MenuConfig.json. It is undoubtedly a great help for the migration and merging of tools.

How to use

Add menu entries for the tool through the MenuEntries field in the ChameleonTools json file. For example, in the following example, a menu entry Tools/Image Compare is defined for "Chameleon Tool". Clicking this menu entry will open the Image Compare tool.

138_ChameleonAutoMenu

{
    "TabLabel": "Image Compare",
    "InitTabSize": [1000, 650],
    "InitTabPosition": [200, 100],
    "MenuEntries": ["Tools/Image Compare"],
    "Icon": {"style": "ChameleonStyle", "name": "Picture" },
    "InitPyCmd": "..."
}

139_image_compare

This tool has been added to Default Python Source and can be used directly.

Notes on menu

The menu items are separated by /, for example Tools/Image Comparison, which means that Tools is a menu group and Image Compare is a menu item under the menu group.

The MenuEntries field supports multiple menu entries, although in most cases, a tool only needs one menu entry. Currently, this feature supports adding menu items to the blue Chameleon button in the toolbar, and will support adding menu items to other locations in the future.

Add icon

The Icon field can be used to add icons to menu items, and the specific method is similar to the method of adding icons to menu items in MenuConfig.json.

Feature enable switch

A new configuration item MenuFromToolsJsonEnabled has been added to Config.ini to control whether to enable the function of reading menu entries from Json files. The default value is True.

Slate
Added support for SDPIScaler.

The SDPIScaler widget can control the scaling ratio of its child components. The usage is as follows:

    "SDPIScaler": 
    {
        "Aka": "Scaler",
        "DPIScaler": 1.0,
        "Content": {
            ...
        }
}
Other widgets
ChameleonData
PythonRBFLib (Experimental)

A new module has been added to use RBF (Radial Basis Function) interpolation in Python

PythonTextureLib
Console Command

Add debug command TAPython.OverrideEnable 1

Enter this command in the CMD debug window, and the contents of the DefaultResource directory in the default resource of the plugin will replace the contents of the TA/TAPython directory in the current project.

CAUTION
This command will overwrite the contents of the TA/Python directory and will not delete the contents of the directory. Please make a backup before using it. {: .alert .alert-warning}

Default Python Source
Add example tool Image Compare

139_image_compare

Compare the differences between two images, such as comparing the rendering content of the scene and the rendering content of the wireframe mode

G41_image_compare_scene

Or compare two different textures

G42_image_compare_texture

The Widget Gallery adds examples of SSplitter and SDPI widgets

Add icons

Changes

Config.ini

Set LogOnTickWarnings of config.ini default value to False

Fixed

In latest v1.2.0

Add Support for UE 5.3

ChameleonData

For example, the code used to fill SImage before is:

self.data.set_image_data(self.ui_image, img.data.tobytes(), width, height, channel_num)

change to:

self.data.set_image_data(self.ui_image, zlib.compress(img.data.tobytes()), w, h, channel_num)

with the same result, you will get a faster execution speed, which will be 1/3~20 times faster, depending on the image content.

Note:

    compressor = zlib.compressobj(level=1)  # use fast compression or use zlib.compress()
    compressed_data = compressor.compress(im.tobytes()) + compressor.flush()
    self.data.set_image_data(self.ui_image, compressed_data, w, h, channel_num)

PythonBPLib

Add more viewport and projection matrix related interfaces

Add Struct: TAPythonPrimitiveHitResult

unreal.TAPythonPrimitiveHitResult is used to add more return data for HitResult.

PythonMeshLib

Add more interfaces for DynamicMesh

PythonTextureLib

Menus

Add menu items for Blueprint Editor

    "OnBlueprintEditorMenu": {
        "name": "Python Menu On Control BP",
        "items":
        [
            {
                "name": "TA Python Blurprint Example",
                "items": [
                    {
                        "name": "Print Blueprint",
                        "command": "print(%asset_paths)"
                    }
                ]
            }
        ]
    }

The configuration items in Config.ini: MenuConfigFilePath and PythonContentFolder support absolute paths Request from. Now we can share Chameleon Tools in different projects.

Default Resource

Add two default menu items to the global Context menu of the Chameleon tool. (UE5 only)

Utils.py

Add guess_instance_name method to guess the instance variable name of the current Chameleon tool in Python

Fix

Experimental

Below is Experimental. It is only recorded here. There may be major changes later, and it is not recommended to use it in official tools.

Slate

Add support for SGraphPanel (Experimental), and EdGraphSchema_K2 is used by default.

ChameleonData

Add SGraphPanel related methods (Experimental):

Note: The following methods are "Experimental" functions, which may be removed later. It is only recorded here.

Add a new BPLib to process Blueprint related content

PythonBPAssetLib(Experimental)

In v1.1.0

Dynamic Creating Slate

G33_Splinter_Button

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.

G34_dynamic_widgets

ChameleonData

In v1.0.11

Add Support for UE 5.2

Documentation

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

Slate

Add
Fix

Default Resources

ChameleonData

Python Editor API

Add
Fix

In v1.0.10

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.

Slate

Add support for SWebBrowser

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.

Web_browser

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

SWebBrowser Plugin

Widgets
ChameleonData

Get the current visibility status of the widget.

They are used for getting and setting the color of the widget.

More APIs for SWebBrowser widget though ChameleonData.

ChameleonTool

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.

Menu

Add a configurable menu for PhysicsAssetEditor and ControlRigEditor

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)"
                    }
                ]
           }
        ]
     }
Add menu in ToolMenus Anchor

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: {
        ...
    }
Console Command
TAPython.RefreshToolMenus 

"TAPython.RefreshToolMenus" can be used to refresh the "ToolMenus" menus, other menus will be auto-refreshed and not need this command

Editor Lib

PythonBPLib

GetModifierKeyState Get the modifier key states(Ctrl, Shift, Alt, etc.), so we used it to display an optional dialog or menu.

We can tank a snapshot of the entire Details window via 'snapshot_details'. The file will be saved to \Saved\Screenshots\WindowsEditor\ObjectDetailProperties. Note we need to make sure the focus is on the Details window.

object_detail_snapshot

PythonTestLib

Cancel the specified DelayCall by ID.

Add PhysicsAssetLib

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

Fixed

v1.0.9

Add PythonTestLib

A new editor lib PythonTestLib has been added to TAPython to complete the test cases of all the extended APIs.

gif

In the test cases repo UE_TAPython_Plugin_TestCases, more than 200 PythonLib APIs has been tested.

Get logs from python

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.

Call python command with delay and repetition

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.

Slates

OnMapChangedCmd

Add "OnMapChangedCmd" to the Chameleon tool for executing Python commands when changing maps.

Usage:

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
parameters
SDetailViewer

We can use SDetailViewer for showing the object properties.

G_015_SDetailsView_s

SMultiLineEditableTextBox
SetColorAndOpacity

Add SetColorAndOpacity support for SScrollBox/SImage/STextBlock/SEditableText

PythonBPLib

SetLevelViewportCameraSpeed

Fix

v1.0.8

Support MacOS

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.

0_49_tapython_osx_small

Context Menu for Chameleon Tools (UE5 only)

Global Context Menu

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.

049_images/reload simple example

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)"
        }
    ]
}
Individual Context for each Chameleon Tool

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.

049_development_mode

Tips:

New Content Menu for Material Editor

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.

G013_get_node_as_r

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]))"
                    }
                ]
            }
        ]
    },

Slates

SScrollBox

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.

SButton

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.

More Control with Chameleon Tool's Window

flash 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.

snap gallery

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)

More PythonMaterialLib APIs

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

1.0.7

SImage

Add Mouse Event for SImage

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)"
    }
}

Painter

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.

PaintCloud

Add More Editor APIs

PythonStructLib

PythonBPLib

PythonTextureLib

More information and example about modify RenderTexture2D and SImage can be found here.

Fix

In v1.0.6

Added:

Fixed:

In v1.0.5

PythonEnumLib and PythonStructLib has been added to Python Editor Libs, PythonDataTableLib also adds more python/blueprint callable functions.

PythonEnumLib PythonStructLib PythonDataTableLib
get_display_name_map log_var_desc get_data_table_struct_path
set_enum_items log_var_desc_by_friendly_name get_data_table_struct
get_enum_len get_variable_description get_table_as_json
get_display_name_by_index get_guid_from_friendly_name get_row_names
set_display_name get_guid_from_property_name get_column_names
get_description_by_index get_variable_names get_shape
set_description_by_index get_friendly_names remove_row
get_name_by_index is_unique_friendly_name add_row
move_enum_item add_variable duplicate_row
is_bitflags_type add_directory_variable rename_row
set_bitflags_type remove_variable_by_name reset_row
get_cpp_form rename_variable move_row
change_variable_default_value get_row_name
get_column_name
get_flatten_data_table
get_property_as_string
get_property_as_string_at
set_property_by_string
set_property_by_string_at

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.

v1.0.4

Support more slates:

Now we can create widge: SSplitter

G006_widget_SSplitter

And SExpandableArea

G006_widget_SExpandableArea

Two APIs was added in ChameleonData for SExpandableArea:

  1. bool GetIsExpanded(const FName AkaName)
  2. 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.

Add Context menu in Outline window

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())"
            }
        ]
    },

G009_context_menu_in_outline

Add configurable icons in front the menu item

024_icons_in_menus

The .png and.svg files in the plugin resource directory will be added to "ChameleonStyle" automatically. Then we can use it for menu items.

The Chameleon UI .json file can reference other json files.

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"
            }
        }
    }

pros:

cons:

recommendation:

The number of shortcut keys has been increased to 10

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.

Add "BorderBackgroundColor" of SBorder
    {
        "SBorder": {
            "BorderBackgroundColor": [1, 0.5, 0, 1],
            "BorderImage":
            {
                "Style": "FEditorStyle",
                "Brush": "ErrorReporting.EmptyBox"
            }
        }
    }

Add More API in PythonBPLib:

025_snap_in_editor

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

G008_ue_screen_image_to_pico

Force the viewport Redraw

We can get the EObjectFlags of a UObject.

026_object_flags

Find the actor by it's "label name" not the "actor name"

Config.ini

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.

Fix:

Feature

Sketch Editing Gif

How to Install

Prerequisites

This plugin use UE native Python Script Plugin. The Scripting the Editor using Python is also very useful.

Python

Steps

  1. Download from TAPython release repo @github and unzip the plugin to <Your_UE_Project>\Plugins release

    Your_UE_Project
    ├── Content                         
    ├── ...
    └── Plugins                        
        └── TAPython       # <--- Put Plugin Here
            ├── Binaries                     
            ├── Config                     
            └── Content                   
            └─ ...

  2. Laungch project, open Project settings - Plugin Python - additional path, add <Your_UE_Project>/TA/TAPython/Python to additional path. then restart the editor.

Project Setting Image

  1. click the Gallery icon on main toolbar, you should see a green check box UI like below.

SketchIconOnMainBar

Green sign and text "Python Path Ready" will showing at the top of gallery.

Python Path Is Ready

If a Red Cross is displayed, check the Project Setting above.

Python Path Is not Ready

Quick Start

The plug-in package contains several menu items and four demo tools by default.

The latest DefaultResources is here: DefaultResources@github

Menu Items

menu gifs

Sketch Tool for design/tweaking UI

005_sketch_icon_on_mainbar

The Sketch Tool is a special ui design tool. When the<Your_UE_Project&gt\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.

G000_SketchEditing

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.

012_default_sketch


Example Tools

All the 4 Example tools, are written with python, without any single line of c++ code.

013_Chameleon_menu

Tool 1: MinimalExample

MinimalExample

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))

Tools 2 Shelf

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.

shelf gif

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.


Tool 2 Object Detail Viewer

Object Detail Viewer

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.

Object Detail Viewer use

Tool 3 Chameleon Gallery

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

Gallery Gif

TAPython How to Use

FAQ

Q0. Can UE4 use this plugin?

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.

More FAQ

Links

Contributing and feedback

This Plugin: TAPython is Free for use. The PythonDefaultResource is under MIT license.