top of page
Search
  • nathan960901

Houdini Transform Node Axis Manipulating Tool

For procedurally modelling in Houdini, centering the axis for a transform node is a very common operation. To do that, users have to click “Move Centroid to Origin” button, and then clear the translate channel. To place the axis to bottom or top, users need to calculate bounding box for the object. So, I wrote a python tool to make the process simple.


Here is the snapshot of this tool. All you need to do is to select a node in a SOP network and hit the button. The texts on the button show the relevant position for your axis. You create a new transform node for your object, or just manipulate the axis for an existed transform node.


To install the tool, just copy my codes and paste it in the script tab of a new shelf tool.


Here is the codes:

from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import hou as hou


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(300, 200)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.horizontalLayout = QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.horizontalLayout_2 = QHBoxLayout()
        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
        self.BUT_NEW = QRadioButton(self.centralwidget)
        self.BUT_NEW.setObjectName(u"BUT_NEW")
        self.BUT_NEW.setAutoFillBackground(False)
        self.BUT_NEW.setChecked(True)

        self.horizontalLayout_2.addWidget(self.BUT_NEW)

        self.BUT_ORI = QRadioButton(self.centralwidget)
        self.BUT_ORI.setObjectName(u"BUT_ORI")

        self.horizontalLayout_2.addWidget(self.BUT_ORI)


        self.verticalLayout.addLayout(self.horizontalLayout_2)

        self.gridLayout = QGridLayout()
        self.gridLayout.setObjectName(u"gridLayout")
        self.PB_UP = QPushButton(self.centralwidget)
        self.PB_UP.setObjectName(u"PB_UP")
        self.PB_UP.setEnabled(True)
        self.PB_UP.clicked.connect(self.UpAxis)

        self.gridLayout.addWidget(self.PB_UP, 0, 0, 1, 1)

        self.PB_LEFT = QPushButton(self.centralwidget)
        self.PB_LEFT.setObjectName(u"PB_LEFT")
        self.PB_LEFT.clicked.connect(self.LeftAxis)

        self.gridLayout.addWidget(self.PB_LEFT, 0, 1, 1, 1)

        self.PB_FRONT = QPushButton(self.centralwidget)
        self.PB_FRONT.setObjectName(u"PB_FRONT")
        self.PB_FRONT.clicked.connect(self.FrontAxis)

        self.gridLayout.addWidget(self.PB_FRONT, 0, 2, 1, 1)

        self.PB_DOWN = QPushButton(self.centralwidget)
        self.PB_DOWN.setObjectName(u"PB_DOWN")
        self.PB_DOWN.clicked.connect(self.DownAxis)

        self.gridLayout.addWidget(self.PB_DOWN, 1, 0, 1, 1)

        self.PB_RIGHT = QPushButton(self.centralwidget)
        self.PB_RIGHT.setObjectName(u"PB_RIGHT")
        self.PB_RIGHT.clicked.connect(self.RightAxis)

        self.gridLayout.addWidget(self.PB_RIGHT, 1, 1, 1, 1)

        self.PB_BACK = QPushButton(self.centralwidget)
        self.PB_BACK.setObjectName(u"PB_BACK")
        self.PB_BACK.clicked.connect(self.BackAxis)

        self.gridLayout.addWidget(self.PB_BACK, 1, 2, 1, 1)


        self.verticalLayout.addLayout(self.gridLayout)

        self.PB_CENTER = QPushButton(self.centralwidget)
        self.PB_CENTER.setObjectName(u"PB_CENTER")
        self.PB_CENTER.clicked.connect(self.CentAxis)

        self.verticalLayout.addWidget(self.PB_CENTER)


        self.horizontalLayout.addLayout(self.verticalLayout)

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Manipulate Axis", None))
        self.BUT_NEW.setText(QCoreApplication.translate("MainWindow", u"Create New XFrom", None))
        self.BUT_ORI.setText(QCoreApplication.translate("MainWindow", u"Work on Original XForm", None))
        self.PB_UP.setText(QCoreApplication.translate("MainWindow", u"UP", None))
        self.PB_LEFT.setText(QCoreApplication.translate("MainWindow", u"LEFT", None))
        self.PB_FRONT.setText(QCoreApplication.translate("MainWindow", u"FRONT", None))
        self.PB_DOWN.setText(QCoreApplication.translate("MainWindow", u"DOWN", None))
        self.PB_RIGHT.setText(QCoreApplication.translate("MainWindow", u"RIGHT", None))
        self.PB_BACK.setText(QCoreApplication.translate("MainWindow", u"BACK", None))
        self.PB_CENTER.setText(QCoreApplication.translate("MainWindow", u"CENTER", None))
    # retranslateUi

# ^^ PySide2 UI
#--------------------------------------------------------------------------------------------------------------------
    def showErrorN(self):
        QMessageBox.about(self.centralwidget, "Horrible Error", "Select the fvcking target nodes!!!")

    def showErrorO(self):
        QMessageBox.about(self.centralwidget, "Horrible Error", "Select the fvcking transform nodes!!!")

    def CentAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'centerAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()

                    transformNode.parm("movecentroid").pressButton()
                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})
            else:
                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    tx = transformNode.parm("tx").eval()
                    ty = transformNode.parm("ty").eval()
                    tz = transformNode.parm("tz").eval()

                    transformNode.parm("movecentroid").pressButton()
                    transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})


    def LeftAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'leftAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()
                    transformNode.parm("movecentroid").pressButton()
                    #  ^^  1. move the obj to the world center

                    px = transformNode.parm("px").eval()
                    #  ^^  2. get the transformation value
                    bbox = hou.node(transformNode.path()).geometry().boundingBox().minvec()
                    #  ^^  3. get the bbox value at world center

                    transformNode.setParms({'px': px + bbox[0],})

                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})

            else:

                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    if transformNode.type().name() is not "xform":
                        tx = transformNode.parm("tx").eval()
                        ty = transformNode.parm("ty").eval()
                        tz = transformNode.parm("tz").eval()
                        #  ^^  1. store the original xform

                        transformNode.parm("movecentroid").pressButton()
                        #  ^^  2. move the obj to the world center

                        px = transformNode.parm("px").eval()
                        #  ^^  3. get the transformation value
                        bbox = hou.node(transformNode.path()).geometry().boundingBox().minvec()
                        #  ^^  4. get the bbox value at world center

                        transformNode.setParms({'px': px + bbox[0], })

                        transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})

                    else:
                        self.showErrorO()

    def RightAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'rightAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()
                    transformNode.parm("movecentroid").pressButton()
                    #  ^^  1. move the obj to the world center

                    px = transformNode.parm("px").eval()
                    #  ^^  2. get the transformation value
                    bbox = hou.node(transformNode.path()).geometry().boundingBox().maxvec()
                    #  ^^  3. get the bbox value at world center

                    transformNode.setParms({'px': px + bbox[0],})

                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})

            else:
                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    if transformNode.type().name() is not "xform":
                        tx = transformNode.parm("tx").eval()
                        ty = transformNode.parm("ty").eval()
                        tz = transformNode.parm("tz").eval()
                        #  ^^  1. store the original xform

                        transformNode.parm("movecentroid").pressButton()
                        #  ^^  2. move the obj to the world center

                        px = transformNode.parm("px").eval()
                        #  ^^  3. get the transformation value
                        bbox = hou.node(transformNode.path()).geometry().boundingBox().maxvec()
                        #  ^^  4. get the bbox value at world center

                        transformNode.setParms({'px': px + bbox[0], })

                        transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})

                    else:
                        self.showErrorO()


    def FrontAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'frontAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()
                    transformNode.parm("movecentroid").pressButton()
                    #  ^^  1. move the obj to the world center

                    pz = transformNode.parm("pz").eval()
                    #  ^^  2. get the transformation value
                    bbox = hou.node(transformNode.path()).geometry().boundingBox().maxvec()
                    #  ^^  3. get the bbox value at world center

                    transformNode.setParms({'pz': pz + bbox[2], })

                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})

            else:
                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    if transformNode.type().name() is not "xform":
                        tx = transformNode.parm("tx").eval()
                        ty = transformNode.parm("ty").eval()
                        tz = transformNode.parm("tz").eval()
                        #  ^^  1. store the original xform

                        transformNode.parm("movecentroid").pressButton()
                        #  ^^  2. move the obj to the world center

                        pz = transformNode.parm("pz").eval()
                        #  ^^  3. get the transformation value
                        bbox = hou.node(transformNode.path()).geometry().boundingBox().maxvec()
                        #  ^^  4. get the bbox value at world center

                        transformNode.setParms({'pz': pz + bbox[2], })

                        transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})

                    else:
                        self.showErrorO()

    def BackAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'backAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()
                    transformNode.parm("movecentroid").pressButton()
                    #  ^^  1. move the obj to the world center

                    pz = transformNode.parm("pz").eval()
                    #  ^^  2. get the transformation value
                    bbox = hou.node(transformNode.path()).geometry().boundingBox().minvec()
                    #  ^^  3. get the bbox value at world center

                    transformNode.setParms({'pz': pz + bbox[2], })

                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})

            else:
                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    if transformNode.type().name() is not "xform":
                        tx = transformNode.parm("tx").eval()
                        ty = transformNode.parm("ty").eval()
                        tz = transformNode.parm("tz").eval()
                        #  ^^  1. store the original xform

                        transformNode.parm("movecentroid").pressButton()
                        #  ^^  2. move the obj to the world center

                        pz = transformNode.parm("pz").eval()
                        #  ^^  3. get the transformation value
                        bbox = hou.node(transformNode.path()).geometry().boundingBox().minvec()
                        #  ^^  4. get the bbox value at world center

                        transformNode.setParms({'pz': pz + bbox[2], })

                        transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})

                    else:
                        self.showErrorO()

    def UpAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'upAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()
                    transformNode.parm("movecentroid").pressButton()
                    #  ^^  1. move the obj to the world center

                    py = transformNode.parm("py").eval()
                    #  ^^  2. get the transformation value
                    bbox = hou.node(transformNode.path()).geometry().boundingBox().maxvec()
                    #  ^^  3. get the bbox value at world center

                    transformNode.setParms({'py': py + bbox[1], })

                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})

            else:
                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    if transformNode.type().name() is not "xform":
                        tx = transformNode.parm("tx").eval()
                        ty = transformNode.parm("ty").eval()
                        tz = transformNode.parm("tz").eval()
                        #  ^^  1. store the original xform

                        transformNode.parm("movecentroid").pressButton()
                        #  ^^  2. move the obj to the world center

                        py = transformNode.parm("py").eval()
                        #  ^^  3. get the transformation value
                        bbox = hou.node(transformNode.path()).geometry().boundingBox().maxvec()
                        #  ^^  4. get the bbox value at world center

                        transformNode.setParms({'py': py + bbox[1], })

                        transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})

                    else:
                        self.showErrorO()

    def DownAxis(self):
        selectedNode = hou.selectedNodes()

        if len(selectedNode) is 0:
            self.showErrorN()

        else:
            if self.BUT_NEW.isChecked() is True:
                for node in selectedNode:
                    transformNode = node.parent().createNode('xform', 'bottomAxis')
                    hou.node(transformNode.path()).setInput(0, hou.node(node.path()))
                    transformNode.moveToGoodPosition()
                    transformNode.parm("movecentroid").pressButton()
                    #  ^^  1. move the obj to the world center

                    py = transformNode.parm("py").eval()
                    #  ^^  2. get the transformation value
                    bbox = hou.node(transformNode.path()).geometry().boundingBox().minvec()
                    #  ^^  3. get the bbox value at world center

                    transformNode.setParms({'py': py + bbox[1], })

                    transformNode.setParms({'tx': 0, 'ty': 0, 'tz': 0})

            else:
                for node in selectedNode:
                    transformNode = hou.node(node.path())

                    if transformNode.type().name() is not "xform":
                        tx = transformNode.parm("tx").eval()
                        ty = transformNode.parm("ty").eval()
                        tz = transformNode.parm("tz").eval()
                        #  ^^  1. store the original xform

                        transformNode.parm("movecentroid").pressButton()
                        #  ^^  2. move the obj to the world center

                        py = transformNode.parm("py").eval()
                        #  ^^  3. get the transformation value
                        bbox = hou.node(transformNode.path()).geometry().boundingBox().minvec()
                        #  ^^  4. get the bbox value at world center

                        transformNode.setParms({'py': py + bbox[1], })

                        transformNode.setParms({'tx': tx, 'ty': ty, 'tz': tz})

                    else:
                        self.showErrorO()

# ^^ Houdini Function
# --------------------------------------------------------------------------------------------------------------------


class MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)



mainw = MainWindow()
mainw.show()






31 views0 comments

Recent Posts

See All
bottom of page