Maya - Node Editor - Align Nodes

Hi there, looking at the documentation for cmds.nodeEditor() I see nothing about setting the position of the node added, except for layoutCommand. And it states it would need a script to do it (which makes sense). But I don’t currently have any examples that I can find for a script like that.

There’s also dotFormat but it says:

Sets the positions of nodes in the graph from a Graphviz output file in *plain* format. Only the node position, width and height information is used.
If the argument starts with "graph ", it will be treated as the plain data instead of a filename.```

I've never used GraphVis, has anyone else? 

Is there any command whether through cmds or API that will allow me to dictate where the node is created in the node editor?

Ah yes. Node editor layout. My old nemesis

I don’t know of a good interface to the node editor. But the UI is written in Qt, so …

You can, with PySide2, get references to the QGraphicsItem objects that are the individual nodes of the NodeEditor. And from there, you can get/set their x/y positions.
Unfortunately because you are looking at the UI objects directly, you can get the node that’s drawn in the NodeEditor, but there’s no sure-fire way to tell which MObject in the Maya scene that the node corresponds to. You can read the current name displayed on the node, but there are NodeEditor options that don’t always show the full name, so it’s not reliable.
You may be able to do things using selection, but that didn’t fit my use-case (and I HATE using selection) so I didn’t do any tests with it.

The thing I wanted was a way to lay out the graph, taking where a node is plugged into another node into account. Hence all the Qt shenanigans.

Unfortunately this is all basically a hack, and is something that’s only partway through development, so there’s a LOT I don’t know, and there’s likely a lot of corner cases that I don’t handle. But this should help you get started.

from shiboken2 import wrapInstance
from maya import OpenMayaUI as mui
from PySide2.QtWidgets import (
    QGraphicsItem,
    QWidget,
    QGraphicsView,
    QStackedLayout,
    QGraphicsSimpleTextItem,
)

def getNodeName(node):
    # This is currently the best way I know of to get the
    # Maya object associated with the node editor node.
    # But it's unreliable
    chis = node.childItems()
    chis = [i for i in chis if isinstance(i, QGraphicsSimpleTextItem)]
    if not chis:
        return None
    nameItem = chis[0]
    return ":".join(nameItem.text().split())


def getCurrentView():
    panel = cmds.getPanel(scriptType="nodeEditorPanel")[0]
    name = pan + "NodeEditorEd"
    ctrl = mui.MQtUtil.findControl(name)
    if ctrl is None:
        raise RuntimeError("Node editor is not open")
    nodeEdPane = wrapInstance(ctrl, QWidget)  # in py2 you will need long(ctrl)
    stack = nodeEdPane.findChild(QStackedLayout)
    graphView = stack.currentWidget().findChild(QGraphicsView)
    scene = graphView.scene()
    return scene


scene = getCurrentView()
items = [item for item in scene.items() if isinstance(i, QGraphicsItem)]

for item in item:
    print(getNodeName(item))
    print(item.pos().x(), item.pos().y())  # setX and setY will set the position
2 Likes

This is awesome @tfox_TD , much appreciated! I will try this out on my side. I couldn’t agree more about “selection”… that’s not acceptable haha.

For my use cases it sounds a lot like yours, where truly it’s just the organization of the graph. I have been looking up the sorting solutions that GraphViz uses. Apparently Dot Clusters is not bad, but I fail to see any automation abilities with it, as most examples are all hard coded that I have found.

Personally I would be interested in how The Foundry’s Nuke does the graphing… that’s sexy haha. But for now I actually already have a wip solution very similar to yours, but in yours you don’t have it as a class. I thought I had to make a class instance of QtWidgets.QWidget in order make it work.

Thanks for the insight, and if you know of any algorithms for sorting graph nodes I’d be interested to hear them. :wink:

Also did you happen to find any bugs/serious issues with messing with the node graph in this manner?

You only need to sublcass from QWidget if you’re making your own new widget. And in the code I shared, I’m interacting with QWidgets that are created in the Maya UI. I’m not creating them, I’m just looking at them, and editing their properties.

I went down a very similar thought process to you (ie. graphviz), but none of the graph layouts really worked for me because because maya didn’t send along enough information, so I rolled my own. It’s certainly not perfect, but it’s better than Maya’s, and you can actually mess with mine.

Here’s the tool I’ve got so far. It’s still VERY WIP, but since I don’t know the next time I’ll get to work on it, I may as well share.

2 Likes

Yeah very true, that makes sense.

Wow! Thank you so much for sharing this. About a year ago I kinda set out to write my own node editor plugin for maya and the sheer breadth of nodes alone deterred me. The fact there’s no real easy way to determine every node that exists in maya and auto create/compile a list of them was enough for me to be like… yeah nah haha.

The idea for me too is to modify what exists, I noticed I can actually do most things Qt will allow you to do, but because of the structure of maya’s UI, it tends to be much more difficult than most Qt UIs. I see you found similar issues.

Thanks for sharing all this knowledge, much appreciated!

BTW, Smart solution using getNodeName(node) in order to iterate over the QGraphicsItem for the text label.

any algorithms for sorting graph nodes

I’ve used this in the past to help with the layout of nodes

1 Like