Python API 2.0 Reference
python/api2/py2CmdMetaData.py
1 from builtins import range
2 import sys
3 import os
4 
5 import maya.api.OpenMaya as om
6 
7 """
8 To use, make sure that pyMetaDataCmd.py is in your MAYA_PLUG_IN_PATH
9 then do the following:
10 
11 Select a node
12 
13 import maya
14 maya.cmds.loadPlugin("pyMetaDataCmd.py")
15 maya.cmds.pyMetaData()
16 
17 There should now be an extra attribute on your node called:
18 ownerName
19 with your user name as its string value
20 """
21 
22 
23 def maya_useNewAPI():
24  """
25  The presence of this function tells Maya that the plugin produces, and
26  expects to be passed, objects created using Maya Python API 2.0.
27  """
28  pass
29 
30 
31 class PyMetaDataCmd(om.MPxCommand):
32  """
33  Plug-in command named 'pyMetaData'.
34 
35  pyMetaData adds a dynamic string attribute to selected dependency nodes.
36  Or, node names or a list of node names may be passed to the command.
37  Dynamic attributes on nodes can be used as meta-data.
38 
39  The force/f flag is used to specify the command will overwrite existing
40  dynamic string attributes of the same name.
41  False will prevent overwriting pre-existing attributes.
42  (default False)
43 
44  The value/v flag is used to specify a value to be set on the new attribute.
45  (default user name from USERNAME or USER envar)
46 
47  The name/n flag is used to specify a name string used to name the attribute.
48  (default 'userName')
49 
50  Undo/redo are supported.
51 
52  This command is written using Maya Python API 2.0.
53 
54  Example of usage, MEL:
55 
56  pyMetaData;
57  pyMetaData -f;
58  pyMetaData -force -name priorityLevel -value High;
59  pyMetaData -name health -v sick pSphere1 pSphere2;
60 
61  Example of usage, Python:
62 
63  maya.cmds.pyMetaData()
64  maya.cmds.pyMetaData(f=True)
65  maya.cmds.pyMetaData(force=True, name='priorityLevel', value='High')
66  maya.cmds.pyMetaData('pSphere1','pSphere2',name='health', v='sick')
67  maya.cmds.pyMetaData(['pSphere1','pSphere2'],name='health', v='sick')
68  """
69 
70  # Variables to be used in Class
71  #
72  cmdName = 'pyMetaData'
73 
74  nameFlag = '-n'
75  nameFlagLong = '-name'
76 
77  forceFlag = '-f'
78  forceFlagLong = '-force'
79 
80  valueFlag = '-v'
81  valueFlagLong= '-value'
82 
83 
84  def __init__(self):
85  om.MPxCommand.__init__(self)
86 
87  @staticmethod
88  def creator():
89  return PyMetaDataCmd()
90 
91  @staticmethod
92  def createSyntax():
93  """
94  Using kSelectionList in setObjectType
95  and calling useSelectionAsDefault(True),
96  allows us to use either a command line list of nodes,
97  or use the active selection list if no node names are specified.
98 
99  The force/f flag is defined as requiring no arguments.
100  By not specifying any arguments for the flag when we define it,
101  the flag will not require any arguments when used in MEL,
102  it will still require a value of 'True' or 'False' when used in Python.
103  """
104  syntax = om.MSyntax()
105  syntax.setObjectType(om.MSyntax.kSelectionList)
106  syntax.useSelectionAsDefault(True)
107  syntax.addFlag(PyMetaDataCmd.forceFlag, PyMetaDataCmd.forceFlagLong)
108  syntax.addFlag(PyMetaDataCmd.nameFlag, PyMetaDataCmd.nameFlagLong, om.MSyntax.kString)
109  syntax.addFlag(PyMetaDataCmd.valueFlag, PyMetaDataCmd.valueFlagLong, om.MSyntax.kString)
110  return syntax
111 
112  def doIt(self, args):
113  # Use an MArgDatabase to Parse our command
114  #
115  try:
116  argdb = om.MArgDatabase(self.syntax(), args)
117  except RuntimeError:
118  om.MGlobal.displayError('Error while parsing arguments:\n#\t# If passing in list of nodes, also check that node names exist in scene.')
119  raise
120 
121  # SELECTION or LIST of Node Names
122  #
123  selList = argdb.getObjectList()
124 
125  # FORCE
126  #
127  force = argdb.isFlagSet(PyMetaDataCmd.forceFlag)
128 
129  # NAME
130  #
131  if argdb.isFlagSet(PyMetaDataCmd.nameFlag):
132  name = argdb.flagArgumentString(PyMetaDataCmd.nameFlag, 0)
133  else:
134  name = 'ownerName'
135 
136  # VALUE
137  #
138  if argdb.isFlagSet(PyMetaDataCmd.valueFlag):
139  value = argdb.flagArgumentString(PyMetaDataCmd.valueFlag, 0)
140  else:
141  if 'USERNAME' in os.environ:
142  value = os.environ['USERNAME']
143  elif 'USER' in os.environ:
144  value = os.environ['USER']
145  else:
146  value = 'USERNAME'
147 
148 
149 
150  # Use an MDGModifier so we can undo this work
151  #
152  self.dgmod = om.MDGModifier()
153 
154  # Define a function to do most of the work
155  #
156  def addMetaData(dependNode, fnDN):
157  # Check to see if the attribute already exists on the node
158  #
159  if fnDN.hasAttribute(name):
160  if force:
161  plug = om.MPlug(dependNode, fnDN.attribute(name))
162  self.dgmod.newPlugValueString(plug, value)
163  self.dgmod.doIt()
164  else:
165  print ('passing over "' + fnDN.name()+ '": force flag not set to True')
166  else:
167  # Create a new attribute
168  #
169  fnAttr = om.MFnTypedAttribute()
170  newAttr = fnAttr.create(name, name, om.MFnData.kString)
171 
172  # Now add the new attribute to the current dependency node,
173  # using dgmod to facilitate undo
174  #
175  self.dgmod.addAttribute(dependNode, newAttr)
176  self.dgmod.doIt()
177 
178  # Create a plug to set and retrieve value off the node.
179  #
180  plug = om.MPlug(dependNode, newAttr)
181 
182  # Set the value for the plug, using dgmod to facilitate undo
183  #
184  self.dgmod.newPlugValueString(plug, value)
185  self.dgmod.doIt()
186 
187 
188  # Iterate over all dependency nodes in list
189  # add the meta-data attribute if it is not already there
190  #
191  for i in range(selList.length()):
192  # Get the dependency node and create
193  # a function set for it
194  #
195  try:
196  dependNode = selList.getDependNode(i)
197  fnDN = om.MFnDependencyNode(dependNode)
198  except RuntimeError:
199  om.MGlobal.displayWarning('item %d is not a depend node'%i)
200  continue
201  addMetaData(dependNode, fnDN)
202 
203  def redoIt(self):
204  self.dgmod.doIt()
205 
206  def undoIt(self):
207  self.dgmod.undoIt()
208 
209  def isUndoable(self):
210  return True
211 
212 def initializePlugin(plugin):
213  pluginFn = om.MFnPlugin(plugin)
214  pluginFn.registerCommand(
215  PyMetaDataCmd.cmdName, PyMetaDataCmd.creator, PyMetaDataCmd.createSyntax
216  )
217 
218 def uninitializePlugin(plugin):
219  pluginFn = om.MFnPlugin(plugin)
220  pluginFn.deregisterCommand(PyMetaDataCmd.cmdName)
221 
222 #-
223 # ==========================================================================
224 # Copyright (C) 2011 Autodesk, Inc. and/or its licensors. All
225 # rights reserved.
226 #
227 # The coded instructions, statements, computer programs, and/or related
228 # material (collectively the "Data") in these files contain unpublished
229 # information proprietary to Autodesk, Inc. ("Autodesk") and/or its
230 # licensors, which is protected by U.S. and Canadian federal copyright
231 # law and by international treaties.
232 #
233 # The Data is provided for use exclusively by You. You have the right
234 # to use, modify, and incorporate this Data into other products for
235 # purposes authorized by the Autodesk software license agreement,
236 # without fee.
237 #
238 # The copyright notices in the Software and this entire statement,
239 # including the above license grant, this restriction and the
240 # following disclaimer, must be included in all copies of the
241 # Software, in whole or in part, and all derivative works of
242 # the Software, unless such copies or derivative works are solely
243 # in the form of machine-executable object code generated by a
244 # source language processor.
245 #
246 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
247 # AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
248 # WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
249 # NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
250 # PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR
251 # TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS
252 # BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
253 # DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK
254 # AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY
255 # OR PROBABILITY OF SUCH DAMAGES.
256 #
257 # ==========================================================================
258 #+