Getting a node's unique id


#1

Hi,

Is there a numerical unique ID for nodes (like an internal node handle)? If there is, how can I get it with mel/python?

Thanks,
o


#2

all node names are unique. There are no internal id’s for nodes.


#3

You could however very easily trag your nodes, by for example adding a unique attribute.


#4

There are unique alpha-numeric IDs for each node. I guess you could get them with python. Try the typeId function of the MFnDependencyNode class.
Edit: upon re-reading the first post Im not sure if you look for the ID of an instance or its class`ID, if you look for an ID for each individual instance then it is like Robert has said, there are none.


#5

Thank you for all the replies.

I’m looking for an ID for each instance of the node, and was hoping there’s something built-in so I won’t have to assign a unique attribute myself, but I guess I’ll have to.

Again, Thank you all.

Cheers,
o


#6

Any reason the full name won’t work? It’s essentially a string attribute that uniquely IDs the node.


#7

some more specific info would help : )
Why dont you create a string attribute called "uniqueID" or similar and set its value?


#8

you don’t need to. use the nodes name, it’s already unique. If you insist on wanting to use an integer id, then use a hashing function or map. Alternatively, if you just want to store references to objects, then use message attributes or sets.


#9

Don`t want to be the smart-alec here, but DAG nodes may have the same name if they have a parent and are not under the same parent. The DAG path will make their “name” unique though.


#10

It’s ok i dont think you’re trying to be a smart alec, i’m just pointing out that you’re wrong :wink:


polyCylinder -r 1 -h 2 -sx 20 -sy 1 -sz 1 -ax 0 1 0 -rcp 0 -cuv 3 -ch 1;
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;

parent "pCylinder1" "pCube1";
rename "pCylinder1" "pCube1";

print `ls -type transform`;

names are always unique.


#11

Okay, dont throw me into the Isis! :argh: I didnt say anything wrong, isnt your example showing what I said? Maya is returning the names and adds the DAG path to the front that makes it unique. Or do you consider the DAG path as the name? Its probably just a small technicality that I am missing here. The API docs on DAG nodes says
Unique Names

The use of the DAG path allows for object names to be reused. Object names can be reused as long as the same name does not appear on more than one DAG node with a common parent.

Cheers!


#12

Correct, therefore maya always returns a unique name, so why do you want to create a unique node id when you already have a unique name? I can see little point in adding a tonne of node create / node delete / node rename MMessages into your plug-in to get a system of unique id’s up and running, when

int unique_id = someStringHashingFunction( node_name );

would work just as well for a fraction of the effort. I’d still recommend using sets or messages over this method though.

yes and no. When objects exist in the dag hierarchy in a way such as the script i posted before, then “|pCube” is the nodes name, plain and simple. MFnDependencyNode::name() will return “|pCube”, ls says the same thing, as does listRelatives, hell, everything in maya then refers to that node as “|pCube”.

You can’t do:

select "pCube1";

you can’t do:

delete "pCube1";

you can’t do:

rename "pCube1" "pCubeyThing1";

to put it simply, Maya doesn’t have a clue what you mean when you say “pCube1”, because it is not recognised by Maya as a unique node name.

QED: node names in Maya are always unique.

Dag paths are slightly different to names imho. A node name refers to a single node, eg “joint1”. Dag paths are then used to refer to instances of a node within the DAG.

so,

polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;
instance;

you can still validly call:

select "pCubeShape1";

since it’s name is unique.

you could also call:

select "|pCube2|pCubeShape1";

if you want to select one of the instances of pCubeShape1.


#13

Okay, as in the quote from the docs is stated: Maya names may be reused == object name is not necessarily unique. But Maya adds the DAG path to make it unique and “error-proof” when asking for that node name. Even “ls -sn pCube1” will not give you the short name even though you are asking for it.

BTW I don`t want to create a unique ID, ofer_z asked for it ; )

I usually rely on message connections to get the nodes I want, string names+DAG Paths have the tendency to fail in complex circumstances


#14

for referencing dag paths, you are better off making a matrix attribute connection to the relevent worldMatrix[ index_id ] attribute.


#15

Hi,

Thank you both for this discussion. It’s very informative.
The reason I wanted an integer unique ID, is to write a shader to mask individual objects, and was hoping to get an unique ID directly from the node.
I’m still testing other options, but for now I settled on adding an attribute to the shape nodes.

Cheers,
o


#16

the downside of using the dagpath as a string is that this name is mutable: if the node is grouped, parented, or renamed, the path changes, even though the object is still the same object. what would be best is to have an id that identifies the object independently of it’s name – a truly immutable per-instance id.

i started a similar discussion with the autodesk guys in charge of api and python integration. i was trying to use an MObject as a key in a python dictionary, but was getting strange results, bc two MObjects representing the same maya object produced different hashes:

import maya.cmds as cmds
import maya.OpenMaya as OpenMaya

def toMObject (nodeName):
     """ Get the API MObject given the name of an existing node """
     sel = OpenMaya.MSelectionList()
     obj = OpenMaya.MObject()
     result = None
     sel.add( nodeName )
     sel.getDependNode( 0, obj )
     return obj

t, s = cmds.sphere()
obj1 = toMObject(t)
print obj1.__hash__(), obj1
# 735641424 <maya.OpenMaya.MObject; proxy of <Swig Object of type  
'MObject *' at 0x2cdc6ec0> >

obj2 = toMObject(t)
print obj2.__hash__(), obj2
# 734669968 <maya.OpenMaya.MObject; proxy of <Swig Object of type  
'MObject *' at 0x2cde56c0> >

print obj1 == obj2
# True

so the question is what is the underlying mechanism for MObject
comparison and could this be used as a hash? does (==) simply
lookup the full dagpath of each node as a string and compare them, or
is there some unique per-instance id that is compared?

turns out that the equality tests are performed using the underlying pointer to the maya object, which is not exposed in mel or api. i am kindly applying pressure to have a hash function based on this underlying pointer exposed in the api. if you think this is a useful feature, you should submit a feature request to autodesk for it as well (i’ve been told that posting en masse helps get a feature pushed through).

so, ofer_z, there is an id but you can’t get to it … yet.

and robert, despite all your protests, this IS different from the dagName, with its own set of advantages.

-chad


#17

That’s cool. Should definitely be exposed.

It seems like for rendering purposes, as in this case, the object’s full name should be acceptable as a unique identifier. Presumably an object’s hierarchy or name is not going to animated. MtoR uses the fullname as an identifier, and I’ve never run into problem associating external information with objects in RIB files because of a changing name.


Oh yeah, I just remembered Mental Ray labels objects with an miLabel, which you actually can specify with an attribute on the object. So for that case the attribute is the way to go.


#18

Having “a truly immutable per-instance id” sounds interesting though I think that it is rather unlikely that it wil be exposed, but that is just a personal guess(I also think that it would raise other issues). What I still dont understand under which circumstances it would be a necessity to have such a feature. Can anyone give me an example where such an id would be crucial? I lack a little bit of imagination, as I cant think about a scenario where a dagPath+objectName combination or a dg connection wouldn`t give you the node you are looking for. Thanks


#19

imagine a subversion-style diff for a maya scene:

when a scene is opened you create a dictionary of MObjectHandles --> FullDagName

on scene save you check the current state versus the original dictionary, from which you can determine every node that has been renamed, deleted, or added since the scene was opened. would be infinitely useful for asset tracking:

– ChangeLog –
Added : mySphere
Deleted : superCube
Renamed: polyCylinder --> awesomeTown

this is just one example. generally speaking, if you use an object’s dagPath as a key in a python dictionary it’s only useful as long as the object is not renamed. as soon as it is, you will need to know the original name to retrieve the data again. very inconvenient.

another way to achieve data persistence independent of object name is to store your data on object attributes, but you are limited to storing only data of the type supported by the attribute, whereas a python dictionary can store as complex a structure as you need. also, adding attributes to every object is much slower than using a python dictionary.


#20

While cumbersome, it is possible to catch dagPath changes to objects in order to maintain your dictionary.

I had implemented a geometry cache for a custom viewport that I had implemented using fullPathNames as my hash. Using the MDagMessage callbacks I was able to catch any changes to the object path. It’s holding up quite well. While having a hashing function in the Maya API would make this simpler, fullPathNames still appear to be a viable workaround.