Some new Features for unreal engine Editor workflow with python and extension to improve workflow for Unreal Houdini Engine. PySide Layout Tool is an alternative to Unreal Engines Utility Widgets if a TA/TD would rather work in python and also bridged to work with UE Houdini Engine to reconstruct a HDA UI when placed in the level to be coherent with how it is layout in Houdini.
There is still a lot of work to do, but I think its in a decent phase to get some feedback.
-
Must have PySide2 installed on your UE_4.27 build.
pip install PySide2to../UE_4.27/Engine/Binaries/ThirdParty/Python3/Win64/python.exe
-
Using Houdini Engine Plugin
H18.5.672
Create New UI: Creates a new UI LayoutLoad: This will construct and display .qui files saved.Loaded UI: quick access to loaded and newly constructed UI.
- Name of the UI in general.
- Path to save in.
- Category to help with organization.
- Click
Create
- All set just start drag and dropping into the layout tree.
View: Openes UI Layout window.Apply: Saves and updates the Layout Window and keep the editor open.Discard: Remove all non saved items.Accept: Saves and updates the Layout Window but closes the editor window.Cancel: Closes window without saving anything.
- On Parameter/Folder Callback to work with script:
ui.editor('Name of UI', 'Category Name').pyModule('Module Name').func() - Special arguments that can be passed to invoked callback function:
kwargs['parm']: return widget object the callback was invoked.kwargs['layout']: return parent layout window object.
- To get other parameter objects :
ui.layout('Name of UI', 'Category Name').parm('parameter Name')
name(): return string name of the parameter.label(): return string display name that is shown on layout.callback(): return string of script or empty string.type(): return namedtuplecurrentItem_name,currentItem_index.disable_when(): return string of expression or empty string.hiden_when(): return string of expression or empty string.invisible(): return bool.eval(): return value of a parameter.set_value(value): set value for parameter.
bNeighbor(): return bool parameter as another parameter next to it.default_value(): return string of default value of parameter.
tab_hide(): return string of tab hide expression.tab_disable(): return string of tab disable expression.
For an expression to work for a parameter e.g :( { parameter_name == 5 } ).
If you have experince with Houdini digital asset its the same format expression.
Root Save: where created UI layout will be saved.Houdini and Python UI: enable to reconstruct HDA UI using PySide Tool.warningnot all HDA will work still early WIP.
Keep Jsondoesnt do anything yet.Save PathPath Json file is saved.
- Make new Dictionary in Plugins
- Must have file *.uiplugin
"Categories": [ { "Name": "Common", "Modules": [ "WidgetTestClass" ] } ]
- Add Plugin Folder name to UIEditorProject.uiproject
{ "Name" : "TestingWidgetPlugin", "Enable" : true }
- See Plugins/TestingWidgetPlugin for setup example.
from PySideLayoutTool.UIEditorLib.UIEditorFactory import WidgetFactory
from PySideLayoutTool.UIEditorLib import LayoutTemplate, TemplateBuildClass
from PySideLayoutTool.UIEditorLib.UIEditorProperty import UIProperty
from PySide2 import QtWidgets
# Class to layout your widgets
class WidgetDemoLayout(QtWidgets.QWidget):
def __init__(self):
super(WidgetDemoLayout, self).__init__()
self._base_layout = QtWidgets.QVBoxLayout()
self._base_layout.setSpacing(0)
self._base_layout.setContentsMargins(0,0,0,0)
self._hbox_layout = QtWidgets.QHBoxLayout()
self._hbox_layout.setSpacing(0)
self._hbox_layout.setContentsMargins(0, 0, 0, 0)
self._line_widget = QtWidgets.QLineEdit('Testing')
self._button_widget = QtWidgets.QPushButton("Push")
self._hbox_layout.addWidget(self._line_widget)
self._hbox_layout.addWidget(self._button_widget)
self._base_layout.addLayout(self._hbox_layout)
self.setLayout(self._base_layout)
# Base widget class template
"""
LayoutTemplate.ParmSetup : is for most common parameters.
LayoutTemplate.FolderSetup : is good for folder type templates.
"""
class WidgetDemoClass(LayoutTemplate.ParmSetup):
def __init__(self,parent=None):
super(WidgetDemoClass, self).__init__(parent)
self._widget = WidgetDemoLayout()
self._layout.addWidget(self._widget)
"""
UIProperty decorator which will add a widget info filler
for the widget description.
Current Widget Properties supported:
- CheckProperty
- ClampProperty
- ComboProperty
- DictionaryProperty
- LineEditProperty
Can also make your own Property Widget and register to the system.
"""
@UIProperty(metaWidget='CheckProperty',label='Check Demo', category='Solo')
def demo_check(self):
pass
# Class for properly building the widget with the application.
"""
TemplateBuildClass.ParameterBuild: for most common parameters.
TempalteBuildClass.FolderBuild: good for folder types, handling items within items
"""
class WidgetDemoBuild(TemplateBuildClass.ParameterBuild):
def widgetClass(self):
return WidgetDemoClass
"""
Register widget to be shown in supported templates.
"""
def register():
WidgetFactory.register('Demo Widget', WidgetDemoBuild)- Not all HDA will work depending on their UI Layout this is still early WIP.
- Houdini Custom Viewport serialization/package does not save properly yet.
- Checking vertexs, normals, binormals can get very computational depending on the complexity of an HDA.
- UE Editor crashes without warning if Houdini Engine is started first and than creating a new UI Layout.
- Testing.qui file is there to currently avoid that.
- importing modules from text editor will fail depending on scope.
- text editor will be reworked completely with jedi or kite plugin.
- Multiparm folder currently does not work yet.
- Ramp callback not yet implemented.
- Serialization for HDA UI work but lose wrapping instance when reopen project.
- Not all interpolation are yet implemented.
- Sometimes Ramp graph doesnt resize properly.
- Callback not implemented.
- Needs more testing.










