Universally Unique Identifiers Are Not Necessarily Unique

Maya 2016 introduced Universally Unique Identifiers, or UUIDs on all nodes. Each scene node generated is now registered with a unique serial number identifying the node, used as an alternative lookup method. Decoupling string names from object access permits node renaming without breaking tools which manage node collections. Instead of having to rely on API object handles to achieve this, UUID is now native to maya.cmds:

# get the UUID of the selected object
cmds.ls(sl=True, uuid=True)

# get the node name from a UUID
cmds.ls(someUuid)

The Problem

According to the help docs, and by design, UUIDs are unique only at the time of creation. This is fine in a single scene, but what about in a reference heavy pipeline? Nope, sorry. In the 2017 help doc update, which coincidentally appeared after filing bug #BSPR-24807, Autodesk clarifies :

When an object is referenced multiple times, the source object's unique identifier (UUID) is inherited by each reference object. This results in multiple objects having the same UUID.

But isn't being unique the entire point of the universal identifier?

Let's say you have a cinematic pipeline which utilizes heavy referencing, and scenes purposely referencing the same rig over and over to assemble crowds. Congratulations! You have created a scene filled with actors whose parts can no longer be accessed via UUID, as they now all share identical ids. The root node of Bill contains the same id as the root node of Frank, Bob, and Sally. In other words, every referenced character is "Sharon".

Easy fix, right? Just change the UUID string attribute on the offending node(s). Wrong! That attribute is read-only.


OpenMaya to the rescue

Thankfully, OpenMaya has your back. The code below demonstrates how to re-issue UUIDs, bypassing the design restriction placed upon reference objects:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import maya.cmds as cmds
import maya.api.OpenMaya as api2
from functools import partial


def reissue_uuids(request=None):
    """
    Generates new UUIDs for the requested dependency nodes, including 'read-only' nodes.

    Request resolution order
        1. requested node or list of nodes
        2. selected nodes
        3. all dependency nodes loaded in scene

    :param request: Nodes to issue new UUIDs
    :type request: list|str|unicode

    :returns: Nothing
    :rtype: None
    """
    get_depends = partial(cmds.ls, dep=True)
    depend_nodes = get_depends(request) or get_depends(selection=True) or get_depends()

    selection_list = api2.MSelectionList()
    [selection_list.add(node) for node in depend_nodes]

    iter_selection = api2.MItSelectionList(selection_list)  # MItDag unavailable until Maya 2016 SP6 ext 2
    while not iter_selection.isDone():
        node = api2.MFnDependencyNode(iter_selection.getDependNode())
        uuid = api2.MUuid().generate()
        node.setUuid(uuid)
        iter_selection.next()