Reputation: 35
I'm trying to update some attribute values in Maya via code and I'm having a really tough time accessing them.
I need the attributes displayed name, (I'm pretty sure this is supposed to be their 'Nice Name'), but I can't seem to get them in any way. Using listAttr or using OpenMaya's MFnAttribute both don't give me what I want - they pass back long names and short names and cleaned up 'Nice Names' but none of those are the displayed UI name to the attributes.
As an example my node contains an attribute with the name 'Horizontal Damping Factor' under a drop down titled 'Advanced Anchor Controls.' When I query the node for a list of attribute nice names I get the similar name 'Anchor HDamping Factor', but that is not the displayed name. This is true for 23 other attributes as well.
Do you have any ideas on what's going on?
(All of these attributes are located in fields two dropdowns deep as well, is that a problem?)
EDIT: It's definitely because the attributes are two dropdowns deep... I still have no idea what these dropdowns are called or how to access the attributes contained inside of them.
EDIT 2: Well, I was wrong, the name of the attribute IS different from the name that's displayed, (when I adjust a slider the editor window shows the name of the value I just changed, which is different from the displayed name, and it's not just a 'Nice' name version of it either.) Still trying to figure this out.
EDIT 3: Not sure how clear this is but it shows the discrepancy between the UI label of the attribute and the 'Nice Name.' There is no 'Horizontal Damping Factor' in the list of attribute names.
FINAL EDIT: Looks like it's not possible to change the value of an attribute by querying the UI name if the attribute was given a different UI name then the authoritative name on creation. Created my own mappings in code instead.
Upvotes: 0
Views: 6467
Reputation: 12208
The authoritative names are the ones in listAttr
; the names you see in the UI are not reliable because an AETemplate can override them in any way it wishes. The AE often presents fake attributes which are used to calculate the real values -- for example, cameras have an angleOfView
in the attribute editor, but setting it actually changes the focalLength
attribute; there is no angleOfView
on the camera node.
So, you may need to do some detective work to figure out what the visible UI is really doing. Playing with the sliders and watching the history is the usual first step.
FWIW
dict(zip(cmds.listAttr(), cmds.listAttr(sn=True)))
will give you a dictionary mapping the long names to the short names, which can be handy for making things more readable.
Upvotes: 2
Reputation: 2620
If you knew the longName
of the attribute in question and the name of the node it is part of, you can use attributeQuery
with the longName
, shortName
or niceName
to get the it's long name, short name and nice name respectively.
From what I understand from your question, you want to be able to look at ll of this information for all the attributes of the node so you can make the right decision of which attribute to choose to do what you are doing. Here is a quick script I wrote, a simple query of sorts, to give you just that: (Interspersed generously with explanation as comments)
import maya.cmds as cmds
def printAttributes(node, like=''):
''' Convinience function to print all the attributes of the given node.
:param: node - Name of the Maya object.
:param: like - Optional parameter to print only the attributes that have this
string in their nice names.
'''
heading = 'Node: %s' % node
# Let's print out the fancy heading
print
print '*' * (len(heading)+6)
print '** %s **' % heading
print '*' * (len(heading)+6)
# Let's get all the attributes of the node
attributes = cmds.listAttr(node)
# Let's loop over the attributes now and get their name info
for attribute in attributes:
# Some attributes will have children. (like publishedNodeInfo)
# We make sure we split out their parent and only use the child's name
# because attributeQuery cannot handle attributes with the parentName.childName format.
attribute = attribute.split('.')[-1]
# Let's now get the long name, short name
# and nice name (UI name) of the atribute.
longName = cmds.attributeQuery(attribute, node=node, longName=True)
shortName = cmds.attributeQuery(attribute, node=node, shortName=True)
niceName = cmds.attributeQuery(attribute, node=node, niceName=True)
# if we the 'like' parameter has been set, we'll check if
# the nice name has that string in it;
# else we skip this attribute.
if like and like.lower() not in niceName.lower():
continue
# Now that we have all the info we need, let's print them out nicely
heading = '\nAttribute: %s' % attribute
print heading
print '-' * len(heading)
print 'Long name: %s\nShort name: %s\nNice name: %s\n' % (longName,
shortName,
niceName)
if __name__ == '__main__':
# Let us get a list of selected node(s)
mySelectedNodes = cmds.ls(sl=True)
# Let us do the printAttributes() for every selected node(s)
for node in mySelectedNodes:
# Just for example, just printing out attributes that
# contain the word 'damping' in their nice (UI) name.
printAttributes(node, like='damping')
Note that we use the command listAttr()
to get a list of all the attributes of the node. Note that we can also use attributeInfo()
to get a list of the attributes also. The advantage of attributeInfo()
over listAttr()
is that attributeInfo()
has more filter flags to filter out the list based on various parameters and properties of the attributes.
It is worth it to go check out the documentation for these: attributeQuery attributeInfo listAttr
Upvotes: 2