Q100108: How to add custom context menu items to Katana Nodes

SUMMARY

This article describes how to add custom menu items to the context menu (right click menu) of nodes within Katana.

 

MORE INFORMATION

You can add custom menu items to the context menu of a node, by using the NodeActionDelegate module Katana provides.
Below is an example showcasing how you register menu actions for the context menu of a specific node. This example will add two custom menu commands to the context menu of the CameraCreate node.
Katana 8.0
from Katana import UI4, NodegraphAPI
from UI4.FormMaster.NodeActionDelegate import (BaseNodeActionDelegate, RegisterActionDelegate)
from UI4.Manifest import QtCore, QtGui, QtWidgets


class MyNodeActionDelegate(BaseNodeActionDelegate.BaseNodeActionDelegate):
    class _SelectNodeAction(QtGui.QAction):

        def __init__(self, parent, node):
            QtGui.QAction.__init__(self, 'Select "%s"' % node.getName(), parent)

            self.__node = node
            if node:
                self.triggered.connect(self.__triggered)
            self.setEnabled(self.__node is not None
                            and not self.__node.isLocked(True))

        def __triggered(self, checked):
            NodegraphAPI.SetNodeSelected(self.__node, True)

    class _DeselectNodeAction(QtGui.QAction):

        def __init__(self, parent, node):
            QtGui.QAction.__init__(self, 'Deselect "%s"' % node.getName(), parent)

            self.__node = node
            if node:
                self.triggered.connect(self.__triggered)
            self.setEnabled(self.__node is not None
                            and not self.__node.isLocked(True))

        def __triggered(self, checked):
            NodegraphAPI.SetNodeSelected(self.__node, False)

    def addToContextMenu(self, menu, node):
        menu.addAction(self._SelectNodeAction(menu, node))
        menu.addAction(self._DeselectNodeAction(menu, node))
    
    def addToWrenchMenu(self, menu, node, hints=None):
        pass


RegisterActionDelegate("CameraCreate", MyNodeActionDelegate())
Katana 7.5 and older
from Katana import UI4, NodegraphAPI
from UI4.FormMaster.NodeActionDelegate import (BaseNodeActionDelegate, RegisterActionDelegate)
from UI4.Manifest import QtCore, QtGui, QtWidgets


class MyNodeActionDelegate(BaseNodeActionDelegate.BaseNodeActionDelegate):
    class _SelectNodeAction(QtWidgets.QAction):

        def __init__(self, parent, node):
            QtWidgets.QAction.__init__(self, 'Select "%s"' % node.getName(), parent)

            self.__node = node
            if node:
                self.triggered.connect(self.__triggered)
            self.setEnabled(self.__node is not None
                            and not self.__node.isLocked(True))

        def __triggered(self, checked):
            NodegraphAPI.SetNodeSelected(self.__node, True)

    class _DeselectNodeAction(QtWidgets.QAction):

        def __init__(self, parent, node):
            QtWidgets.QAction.__init__(self, 'Deselect "%s"' % node.getName(), parent)

            self.__node = node
            if node:
                self.triggered.connect(self.__triggered)
            self.setEnabled(self.__node is not None
                            and not self.__node.isLocked(True))

        def __triggered(self, checked):
            NodegraphAPI.SetNodeSelected(self.__node, False)

    def addToContextMenu(self, menu, node):
        menu.addAction(self._SelectNodeAction(menu, node))
        menu.addAction(self._DeselectNodeAction(menu, node))
    
    def addToWrenchMenu(self, menu, node, hints=None):
        pass


RegisterActionDelegate("CameraCreate", MyNodeActionDelegate())

 

FURTHER READING

If you'd like to add the same menu commands to the context menus of all the types of nodes, you can replace the final line of the above example with the following:
myNodeActionDelegate = MyNodeActionDelegate()
for nodeTypeName in NodegraphAPI.GetNodeTypes():
    RegisterActionDelegate(nodeTypeName, myNodeActionDelegate)


You can also register the same node action delegate against specific node types, as shown in the following example:

myNodeActionDelegate = MyNodeActionDelegate()
for nodeTypeName in ['AttributeSet', 'CameraCreate', 'OpScript']:
    RegisterActionDelegate(nodeTypeName, myNodeActionDelegate)

ATTACHMENTS

    We're sorry to hear that

    Please tell us why