예제 #1
0
def getMetaData(node, className=None):
    """
    Return meta data from a node. If `className` is given
    returns only meta data for that meta class type.

    Args:
        node: A PyMel node or string node name
        className: A string name of the meta class type.

    Returns:
        A dict or python object representing the stored meta data
    """
    mfnnode = utils.getMFnDependencyNode(node)
    try:
        plug = mfnnode.findPlug(METADATA_ATTR)
        datastr = plug.asString()
    except RuntimeError:
        return
    else:
        refNode = None
        if pm.cmds.referenceQuery(str(node), isNodeReferenced=True):
            refNode = pm.cmds.referenceQuery(str(node), rfn=True)
        data = decodeMetaData(datastr, refNode)
        if className is not None:
            return data.get(className, None)
        else:
            return data
예제 #2
0
def setAllMetaData(node, data, undoable=True):
    """
    Set all meta data on a node. This is faster because the
    existing data on the node is not retrieved first and then
    modified. The data must be first indexed by strings that
    are valid meta class names, otherwise errors may occur
    when retrieving it later.

    New meta class attributes will be added automatically,
    but existing meta class attributes will not be removed.
    If old meta class attributes on this node will no longer
    be applicable, they should be removed with removeAllData
    first.

    Args:
        node (PyNode or str): The node on which to set data
        data (dict): The data to serialize and store on the node
        undoable (bool): When True, the operation will be undoable
    """
    mfnnode = utils.getMFnDependencyNode(node)
    plug = _getOrCreateMetaDataPlug(mfnnode, undoable)

    # add class attributes
    if data:
        for className in data.keys():
            _addMetaClassAttr(mfnnode, className, undoable)

    # set meta data
    newValue = encodeMetaData(data)

    if undoable:
        cmds.setAttr(plug.name(), newValue, type='string')
    else:
        plug.setString(newValue)
예제 #3
0
def setMetaData(node, className, data, undoable=True, replace=False):
    """
    Set the meta data for the a meta class type on a node.

    The className must be a valid attribute name.

    Args:
        node (PyNode or str): The node on which to set data
        className (str): The data's meta class type name
        data (dict): The data to serialize and store on the node
        undoable (bool): When True, the operation will be undoable
        replace (bool): When True, will replace all data on the node
            with the new meta data. This uses setAllMetaData and can
            be much faster with large data sets.
    """
    if replace:
        setAllMetaData(node, {className: data}, undoable)
        return

    mfnnode = utils.getMFnDependencyNode(node)
    plug = _getOrCreateMetaDataPlug(mfnnode, undoable)
    _addMetaClassAttr(mfnnode, className, undoable)

    # update meta data
    refNode = None
    if cmds.referenceQuery(str(node), isNodeReferenced=True):
        refNode = cmds.referenceQuery(str(node), rfn=True)
    fullData = decodeMetaData(plug.asString(), refNode)
    fullData[className] = data
    newValue = encodeMetaData(fullData)

    if undoable:
        cmds.setAttr(plug.name(), newValue, type='string')
    else:
        plug.setString(newValue)
예제 #4
0
def removeMetaData(node, className=None):
    """
    Remove meta data from a node. If no `className` is given
    then all meta data is removed.

    Args:
        node: A PyMel node or string node name
        className: A string name of the meta class type.

    Returns:
        True if node is fully clean of relevant meta data.
    """
    if not isMetaNode(node):
        return True

    mfnnode = utils.getMFnDependencyNode(node)

    if className is not None:
        # remove meta data for the given class only

        # make sure data attribute is unlocked
        dataPlug = _getMetaDataPlug(mfnnode)
        if dataPlug and dataPlug.isLocked():
            return False

        # make sure class attribute is unlocked
        classPlug = _getMetaClassPlug(mfnnode, className)
        if classPlug and classPlug.isLocked():
            return False

        data = decodeMetaData(plug.asString())
        if className in data:
            del data[className]
            plug.setString(encodeMetaData(data))

    else:
        # remove all meta data from the node

        # make sure data attribute is unlocked
        dataPlug = _getMetaDataPlug(mfnnode)
        if dataPlug and dataPlug.isLocked():
            return False

        # make sure all class attributes are unlocked
        classPlugs = [
            _getMetaClassPlug(mfnnode, c) for c in getMetaClasses(node)
        ]
        for cp in classPlugs:
            if cp and cp.isLocked():
                return False

        # remove all attributes
        if dataPlug:
            mfnnode.removeAttribute(dataPlug.attribute())
        for cp in classPlugs:
            if cp:
                mfnnode.removeAttribute(cp.attribute())

    return True
예제 #5
0
def setMetaData(node, className, data, undoable=True):
    """
    Set the meta data for the a meta class type on a node.

    Args:
        node: A PyMel node or string node name
        className: A string name of the meta class type.
        data: A python object to serialize and store as meta data
        undoable: A bool, when True the change will be undoable
    """
    # get meta data plug
    mfnnode = utils.getMFnDependencyNode(node)
    try:
        plug = mfnnode.findPlug(METADATA_ATTR)
    except:
        if undoable:
            cmds.addAttr(mfnnode.name(), ln=METADATA_ATTR, dt='string')
        else:
            mfnattr = api.MFnTypedAttribute()
            attr = mfnattr.create(METADATA_ATTR, METADATA_ATTR,
                                  api.MFnData.kString)
            mfnnode.addAttribute(attr)
        plug = mfnnode.findPlug(METADATA_ATTR)

    # ensure node has meta class type attribute
    if not VALID_CLASSATTR.match(className):
        raise ValueError('Invalid meta class name: ' + className)
    classAttr = METACLASS_ATTR_PREFIX + className
    try:
        mfnnode.attribute(classAttr)
    except RuntimeError:
        if undoable:
            cmds.addAttr(mfnnode.name(), ln=classAttr, at='short')
        else:
            mfnattr = api.MFnNumericAttribute()
            attr = mfnattr.create(classAttr, classAttr,
                                  api.MFnNumericData.kShort)
            mfnnode.addAttribute(attr)

    # update meta data
    refNode = None
    if cmds.referenceQuery(str(node), isNodeReferenced=True):
        refNode = cmds.referenceQuery(str(node), rfn=True)
    fullData = decodeMetaData(plug.asString(), refNode)
    fullData[className] = data
    newValue = encodeMetaData(fullData)

    if undoable:
        cmds.setAttr(plug.name(), newValue, type='string')
    else:
        plug.setString(newValue)
예제 #6
0
def setMetaData(node, className, data):
    """
    Set the meta data for the a meta class type on a node.

    Args:
        node: A PyMel node or string node name
        className: A string name of the meta class type.
        data: A python object to serialize and store as meta data
    """
    # get meta data plug
    mfnnode = utils.getMFnDependencyNode(node)
    try:
        plug = mfnnode.findPlug(METADATA_ATTR)
    except:
        mfnattr = api.MFnTypedAttribute()
        attr = mfnattr.create(METADATA_ATTR, METADATA_ATTR,
                              api.MFnData.kString)
        mfnnode.addAttribute(attr)
        plug = mfnnode.findPlug(METADATA_ATTR)
    # ensure node has meta class type attribute
    if not VALID_CLASSATTR.match(className):
        raise ValueError('Invalid meta class name: ' + className)
    classAttr = METACLASS_ATTR_PREFIX + className
    try:
        mfnnode.attribute(classAttr)
    except RuntimeError:
        mfnattr = api.MFnNumericAttribute()
        attr = mfnattr.create(classAttr, classAttr, api.MFnNumericData.kInt)
        mfnnode.addAttribute(attr)
    # update meta data
    refNode = None
    if pm.cmds.referenceQuery(str(node), isNodeReferenced=True):
        refNode = pm.cmds.referenceQuery(str(node), rfn=True)
    fullData = decodeMetaData(plug.asString(), refNode)
    fullData[className] = data
    plug.setString(encodeMetaData(fullData))
예제 #7
0
def removeMetaData(node, className=None, undoable=True):
    """
    Remove meta data from a node. If no `className` is given
    then all meta data is removed.

    Args:
        node: A PyMel node or string node name
        className: A string name of the meta class type.
        undoable: A bool, when True the change will be undoable

    Returns:
        True if node is fully clean of relevant meta data.
    """
    if not isMetaNode(node):
        return True

    mfnnode = utils.getMFnDependencyNode(node)

    # this may become true if we find there are no
    # classes left after removing one
    removeAllData = False

    if className is not None:
        # remove meta data for the given class only

        # make sure class attribute is unlocked
        classPlug = _getMetaClassPlug(mfnnode, className)
        if classPlug and classPlug.isLocked():
            return False

        # make sure data attribute is unlocked
        dataPlug = _getMetaDataPlug(mfnnode)
        if dataPlug and dataPlug.isLocked():
            return False

        # remove class attribute
        if classPlug:
            if undoable:
                cmds.deleteAttr(classPlug.name())
            else:
                mfnnode.removeAttribute(classPlug.attribute())

        # remove class data
        data = decodeMetaData(dataPlug.asString())
        if className in data:
            del data[className]
            newValue = encodeMetaData(data)

            if undoable:
                cmds.setAttr(dataPlug.name(), newValue, type='string')
            else:
                dataPlug.setString(newValue)

        # check if any classes left
        if len(data) == 0:
            removeAllData = True

    else:
        # no className was given
        removeAllData = True

    if removeAllData:
        # remove all meta data from the node

        # make sure all class attributes are unlocked
        classPlugs = [
            _getMetaClassPlug(mfnnode, c) for c in getMetaClasses(node)
        ]
        for cp in classPlugs:
            if cp and cp.isLocked():
                return False

        # make sure data attribute is unlocked
        dataPlug = _getMetaDataPlug(mfnnode)
        if dataPlug and dataPlug.isLocked():
            return False

        # remove class attributes
        for classPlug in classPlugs:
            if classPlug:
                if undoable:
                    cmds.deleteAttr(classPlug.name())
                else:
                    mfnnode.removeAttribute(classPlug.attribute())

        # remove data attribute
        if dataPlug:
            if undoable:
                cmds.deleteAttr(dataPlug.name())
            else:
                mfnnode.removeAttribute(dataPlug.attribute())

    return True