Evgeniy Zaitsev Technical Artist

28Jul/10Off

Maya: Extra Attributes using Maya API classes

Dealt Maya API. Here I decided to post some example functions. The basic idea was using Maya API Python classes realize workflow with extra attributes at native Maya node. Suppose you want to make a script that stores some data in one native Maya node (in the script node, for example), and if user do not have your script, nothing terrible will happen, node modified by you will work without any troubles. Sorry for my English.

You should get something like this:


import maya.OpenMaya as OpenMaya        # general Maya API module

def addExtraAttrToNode( m_node_name ):
    """
    add custom extra attributes to the node using Maya API
    classes in runtime mode 'on fly'
    INPUT:  m_node_name - node name, like 'lambert1' 
    RETURN: True -  if attributes added properly, False - otherwise
    USAGE:  addExtraAttrToNode('lambert1')    
    """
    # create selection list
    #
    m_selectionList = OpenMaya.MSelectionList() 
    # create MObject
    #
    m_node = OpenMaya.MObject()
    # create a function set to work with MObject
    #                 
    m_node_fn = OpenMaya.MFnDependencyNode()    
    try:
        # add node with name 'lambert2'
        # if node don't exist return exception 
        m_selectionList.add( m_node_name )            
    except:
        return False
    # get first element in the selection list and connect with MObject 
    #
    m_selectionList.getDependNode( 0, m_node )  
    # connect MObject with function set
    # 
    m_node_fn.setObject( m_node )
    #            
    # float attribute
    # 
    fAttr = OpenMaya.MFnNumericAttribute()
    aSampleFloat  = OpenMaya.MObject()
    aSampleFloat = fAttr.create( "sampleFloat", "sf", 
                                 OpenMaya.MFnNumericData.kFloat, 0.0 )
    fAttr.setKeyable( True )
    fAttr.setStorable( True )
    fAttr.setDefault( 1.0 )
    #            
    # string attribute
    # 
    fAttr = OpenMaya.MFnTypedAttribute()
    aSampleTxt = OpenMaya.MObject()
    aSampleTxt = fAttr.create( "sampleTXT", "st", 
                               OpenMaya.MFnData.kString )
    fAttr.setKeyable( True )
    fAttr.setWritable( True )
    fAttr.setReadable( True )
    fAttr.setStorable( True )
    #            
    # boolean attribute
    # 
    fAttr = OpenMaya.MFnNumericAttribute()
    aSampleBool = OpenMaya.MObject()
    aSampleBool = fAttr.create( "sampleBOOL", "sb", 
                                OpenMaya.MFnNumericData.kBoolean, True )
    fAttr.setKeyable( True )
    fAttr.setStorable( True )
    fAttr.setReadable( True )
    fAttr.setWritable( True )
    #            
    # multi compound attribute
    # 
    fAttr = OpenMaya.MFnCompoundAttribute()
    aCompound = OpenMaya.MObject()
    aCompound = fAttr.create( "sampleCompound", "sc" )
    fAttr.addChild( aSampleBool )  # child 0
    fAttr.addChild( aSampleTxt )   # child 1
    fAttr.addChild( aSampleFloat ) # child 2
    fAttr.setArray( True ) # create 'multi' attr
    fAttr.setKeyable( True )
    fAttr.setWritable( True )
    fAttr.setReadable( True )
    fAttr.setStorable( True )
    try:
        # try to add attributes using function set
        m_node_fn.addAttribute( aCompound )
    except:
        return False
    return True

def printExtraAttrData( m_node_name ):
    """
    print's data stored in extra attributes 
    INPUT:  m_node_name - node name, like 'lambert1' 
    RETURN: True -  if well done, False - otherwise
    USAGE:  printExtraAttrData('lambert1')         
    """
    m_selectionList = OpenMaya.MSelectionList() # create selection list
    m_node = OpenMaya.MObject()                 # create MObject
    m_node_fn = OpenMaya.MFnDependencyNode()    # create a function set
    try:
        # add node with name 'lambert2'
        m_selectionList.add( m_node_name )            
    except:
        return False
    # get first element in the selection list and connect with MObject 
    m_selectionList.getDependNode( 0, m_node )  
    # connect MObject with function set 
    m_node_fn.setObject( m_node )
    # find attribute by name using function set class 
    #
    m_attr = m_node_fn.attribute('sampleCompound')
    # create MPlug object fo work with attribute
    # A plug is a point on a dependency node where a 
    # particular attribute can be connected
    m_attr_plug = OpenMaya.MPlug( m_node, m_attr )
    # create int array fo storing indexes of available items
    #
    m_ind = OpenMaya.MIntArray()
    m_attr_plug.getExistingArrayAttributeIndices(m_ind)
    try:
        for i in m_ind:
            print("IND %s BOOL %s STR %s FLOAT %s" 
                %( i,
                   m_attr_plug.elementByLogicalIndex(i).child(0).asBool(),
                   m_attr_plug.elementByLogicalIndex(i).child(1).asString(),
                   m_attr_plug.elementByLogicalIndex(i).child(2).asFloat() ) )
    except:
        return False
    return True 
    
def setExtraAttrValues( m_node_name, m_index, m_tuple ):
    """
    write data to the node 
    INPUT:  m_node_name - node name, like 'lambert1'
            m_index     - index of item where you wont to write
            m_tuple     - tuple, like: ( True , 'Test', 4.2 ) 
                          m_tuple[0] - True
                          m_tuple[1] - 'Test'
                          m_tuple[2] - 4.2                                                  
    RETURN: True -  if well done, False - otherwise
    USAGE:  setExtraAttrValues( 'lambert1', 1, ( False , 'Test', 4.2 )  )       
    """ 
    m_selectionList = OpenMaya.MSelectionList() 
    m_node = OpenMaya.MObject()                 
    m_node_fn = OpenMaya.MFnDependencyNode()    
    try:
        m_selectionList.add( m_node_name )            
        m_selectionList.getDependNode( 0, m_node )  
        m_node_fn.setObject( m_node )
        m_attr = m_node_fn.attribute('sampleCompound')
        m_attr_plug = OpenMaya.MPlug( m_node, m_attr )
        # convert m_index to integer
        #
        m_index = int(m_index)
        # write data stored in tuple to the node
        #
        m_attr_plug.elementByLogicalIndex(m_index).child(0).setBool( m_tuple[0] )
        m_attr_plug.elementByLogicalIndex(m_index).child(1).setString( m_tuple[1] )
        m_attr_plug.elementByLogicalIndex(m_index).child(2).setFloat( m_tuple[2] )         
    except:
        return False
    return True 

How you can use it:

 
addExtraAttrToNode('lambert1')
setExtraAttrValues('lambert1', 1, ( False , 'Test 1', 4.2 )  )
setExtraAttrValues('lambert1', 0, ( True , 'Test Message', 16.2 )  )
setExtraAttrValues('lambert1', 3, ( False , 'Test 2', 0.54 )  )
printExtraAttrData('lambert1')

In Maya console you should get:

IND 0 BOOL True STR Test Message FLOAT 16.2000007629
IND 1 BOOL False STR Test 1 FLOAT 4.19999980927
IND 3 BOOL False STR Test 2 FLOAT 0.540000021458
Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.