scripted/motionTraceCmd.py

scripted/motionTraceCmd.py
1 #-
2 # ==========================================================================
3 # Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All
4 # rights reserved.
5 #
6 # The coded instructions, statements, computer programs, and/or related
7 # material (collectively the "Data") in these files contain unpublished
8 # information proprietary to Autodesk, Inc. ("Autodesk") and/or its
9 # licensors, which is protected by U.S. and Canadian federal copyright
10 # law and by international treaties.
11 #
12 # The Data is provided for use exclusively by You. You have the right
13 # to use, modify, and incorporate this Data into other products for
14 # purposes authorized by the Autodesk software license agreement,
15 # without fee.
16 #
17 # The copyright notices in the Software and this entire statement,
18 # including the above license grant, this restriction and the
19 # following disclaimer, must be included in all copies of the
20 # Software, in whole or in part, and all derivative works of
21 # the Software, unless such copies or derivative works are solely
22 # in the form of machine-executable object code generated by a
23 # source language processor.
24 #
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
26 # AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
27 # WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
28 # NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
29 # PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR
30 # TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS
31 # BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
32 # DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK
33 # AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY
34 # OR PROBABILITY OF SUCH DAMAGES.
35 #
36 # ==========================================================================
37 #+
38 
39 ########################################################################
40 # DESCRIPTION:
41 #
42 # Produces the Python command "spMotionTrace".
43 #
44 # This plug-in traces the position of an animated object and creates a curve
45 # showing the object's path.
46 #
47 # To use this plug-in, you must first create an object and animate it by setting
48 # keyframes. An easy way to do this is to just create a primitive, then set several
49 # keyframes on it.
50 #
51 # Once this is done, select the animated object and invoke the spMotionTrace command.
52 #
53 # Options:
54 #
55 # s=<frame> The start frame. Default to 1.
56 # e=<frame> The end frame. Default to 60.
57 # b=<frame> The by frame. Default to 1.
58 #
59 # Example:
60 #
61 # From Python:
62 # import maya
63 # maya.cmds.spMotionTrace(s=1, e=100, b=2)
64 #
65 # From Mel:
66 # spMotionTrace -s 1 -e 100 -b 2
67 #
68 # The object will move along its animated path under control of the plug-in and when the
69 # animation is complete, the plug-in will draw a curve in the scene that represents
70 # the motion path of the object.
71 #
72 ########################################################################
73 
74 #
75 # Creation Date: 27 September 2006
76 #
77 
78 import maya.OpenMaya as OpenMaya
79 import maya.OpenMayaMPx as OpenMayaMPx
80 import math, sys
81 
82 kPluginCmdName="spMotionTrace"
83 
84 kStartFlag = "-s"
85 kStartLongFlag = "-startFrame"
86 kEndFlag = "-e"
87 kEndLongFlag = "-endFrame"
88 kByFlag = "-b"
89 kByLongFlag = "-byFrame"
90 
91 # command
92 class motionTrace(OpenMayaMPx.MPxCommand):
93  def __init__(self):
94  OpenMayaMPx.MPxCommand.__init__(self)
95  # setup private data members
96  self.__start = 1
97  self.__end = 60
98  self.__by = 1
99 
100 
101  def doIt(self, args):
102  """
103  This method is called from script when this command is called.
104  It should set up any class data necessary for redo/undo,
105  parse any given arguments, and then call redoIt.
106  """
107  argData = OpenMaya.MArgDatabase(self.syntax(), args)
108 
109  if argData.isFlagSet(kStartFlag):
110  self.__start = argData.flagArgumentInt(kStartFlag, 0)
111  if argData.isFlagSet(kEndFlag):
112  self.__end = argData.flagArgumentInt(kEndFlag, 0)
113  if argData.isFlagSet(kByFlag):
114  self.__by = argData.flagArgumentInt(kByFlag, 0)
115 
116  self.redoIt()
117 
118 
119  def redoIt(self):
120  """
121  This method performs the action of the command.
122  This method iterates over all selected items and
123  prints out connected plug and dependency node type
124  information.
125  """
126  picked = OpenMaya.MObjectArray()
127  dependNode = OpenMaya.MObject() # Selected dependency node
128 
129  # Create a selection list iterator
130  slist = OpenMaya.MSelectionList()
132  iter = OpenMaya.MItSelectionList(slist)
133 
134  # Iterate over all selected dependency nodes
135  # and save them in a list
136  while not iter.isDone():
137  # Get the selected dependency node
138  iter.getDependNode(dependNode)
139  picked.append(dependNode)
140  iter.next()
141 
142  # sample the animation using start, end, by values
143  pointArrays = [ OpenMaya.MPointArray() for i in range(picked.length()) ]
144 
145  time = self.__start
146  while (time <= self.__end):
147  timeval = OpenMaya.MTime(time)
149 
150  # Iterate over selected dependency nodes
151  for i in range(picked.length()):
152  # Get the selected dependency node
153  dependNode = picked[i]
154 
155  # Create a function set for the dependency node
156  fnDependNode = OpenMaya.MFnDependencyNode(dependNode)
157 
158  # Get the translation attribute values
159  txAttr = fnDependNode.attribute("translateX")
160  txPlug = OpenMaya.MPlug(dependNode, txAttr)
161  tx = txPlug.asDouble()
162 
163  tyAttr = fnDependNode.attribute("translateY")
164  tyPlug = OpenMaya.MPlug(dependNode, tyAttr)
165  ty = tyPlug.asDouble()
166 
167  tzAttr = fnDependNode.attribute("translateZ")
168  tzPlug = OpenMaya.MPlug(dependNode, tzAttr)
169  tz = tzPlug.asDouble()
170 
171  print "adding", tx, ty, tz, "\n"
172  pointArrays[i].append(OpenMaya.MPoint(tx, ty, tz))
173 
174  time += self.__by
175 
176  # make a path curve for each selected object
177  for i in range(picked.length()):
178  self.__jMakeCurve(pointArrays[i])
179 
180 
181  def __jMakeCurve(self, cvs):
182  """
183  Make a degree 1 curve from the given CVs.
184 
185  Note that in Python, a double underscore in front of a member name
186  make the method "private" to the class through name-mangling
187  """
188  deg = 1
189  knots = OpenMaya.MDoubleArray()
190 
191  for i in range(cvs.length()):
192  knots.append(i)
193 
194  # Now create the curve
195  nullObj = OpenMaya.MObject()
196  curveFn = OpenMaya.MFnNurbsCurve()
197  curveFn.create(cvs, knots, deg, OpenMaya.MFnNurbsCurve.kOpen, False, False, nullObj)
198 
199 
200 # Creator
201 def cmdCreator():
202  return OpenMayaMPx.asMPxPtr(motionTrace())
203 
204 
205 # Syntax creator
206 def syntaxCreator():
207  syntax = OpenMaya.MSyntax()
208  syntax.addFlag(kStartFlag, kStartLongFlag, OpenMaya.MSyntax.kLong)
209  syntax.addFlag(kEndFlag, kEndLongFlag, OpenMaya.MSyntax.kLong)
210  syntax.addFlag(kByFlag, kByLongFlag, OpenMaya.MSyntax.kLong)
211  return syntax
212 
213 
214 # Initialize the script plug-in
215 def initializePlugin(mobject):
216  mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")
217  try:
218  mplugin.registerCommand(kPluginCmdName, cmdCreator, syntaxCreator)
219  except:
220  sys.stderr.write("Failed to register command: %s\n" % kPluginCmdName)
221  raise
222 
223 
224 # Uninitialize the script plug-in
225 def uninitializePlugin(mobject):
226  mplugin = OpenMayaMPx.MFnPlugin(mobject)
227  try:
228  mplugin.deregisterCommand(kPluginCmdName)
229  except:
230  sys.stderr.write("Failed to unregister command: %s\n" % kPluginCmdName)
231  raise
232 
233