scripted/circleNode.py

scripted/circleNode.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 # Autodesk Script File
41 # MODIFY THIS AT YOUR OWN RISK
42 #
43 # Creation Date: 27 September 2006
44 #
45 # Example Plugin: circleNode.py
46 #
47 # This plug-in is an example of a user-defined dependency graph node.
48 # It takes a number as input (such as time) and generates two output
49 # numbers one which describes a sine curve as the input varies and
50 # one that generates a cosine curve. If these two are hooked up to
51 # the x and z translation attributes of an object the object will describe
52 # move through a circle in the xz plane as time is changed.
53 #
54 # See circleNodeTest.py for an example of how to use the node. The script will
55 # create a new "Circle" menu with a single item. Selecting this will build
56 # a simple model (a sphere which follows a circular path) which can be played back,
57 # by clicking on the "play" icon on the time slider. Note: the circleNode
58 # plugin needs to be loaded before the "Circle" menu item can be executed
59 # properly.
60 #
61 # The node has two additional attributes which can be changed to affect
62 # the animation, "scale" which defines the size of the circular path, and
63 # "frames" which defines the number of frames required for a complete circuit
64 # of the path. Either of these can be hooked up to other nodes, or can
65 # be simply set via the command "maya.cmds.setAttr" operating on the circle node
66 # "circleNode1" created by the Python script. For example:
67 #
68 # import maya.cmds as cmds
69 # cmds.setAttr("circleNode1.scale", #)
70 #
71 # will change the size of the circle and:
72 #
73 # cmds.setAttr("circleNode1.frames", #)
74 #
75 # will cause objects to complete a circle in indicated number of frames.
76 #
77 
78 import math, sys
79 
80 import maya.OpenMaya as OpenMaya
81 import maya.OpenMayaMPx as OpenMayaMPx
82 
83 kPluginNodeTypeName = "spCircle"
84 kPluginNodeId = OpenMaya.MTypeId(0x87005)
85 
86 
87 # Node definition
88 class circle(OpenMayaMPx.MPxNode):
89  # class variables
90  aInput = OpenMaya.MObject()
91  aScale = OpenMaya.MObject()
92  aFrames = OpenMaya.MObject()
93  aSOutput = OpenMaya.MObject()
94  aCOutput = OpenMaya.MObject()
95 
96 
97  def __init__(self):
98  OpenMayaMPx.MPxNode.__init__(self)
99 
100 
101  def compute(self, plug, data):
102  # Check that the requested recompute is one of the output values
103  if (plug == circle.aSOutput or plug == circle.aCOutput):
104  # Read the input values
105  inputData = data.inputValue(circle.aInput)
106  scaleData = data.inputValue(circle.aScale)
107  framesData = data.inputValue(circle.aFrames)
108 
109  # Compute the output values
110  currentFrame = inputData.asFloat()
111  scaleFactor = scaleData.asFloat()
112  framesPerCircle = framesData.asFloat()
113  angle = 6.2831853 * (currentFrame/framesPerCircle)
114  sinResult = math.sin(angle) * scaleFactor
115  cosResult = math.cos(angle) * scaleFactor
116 
117  # Store them on the output plugs
118  sinHandle = data.outputValue(circle.aSOutput)
119  cosHandle = data.outputValue(circle.aCOutput)
120  sinHandle.setFloat(sinResult)
121  cosHandle.setFloat(cosResult)
122  data.setClean(plug)
123  else:
124  return OpenMaya.kUnknownParameter
125 
126  return None
127 
128 
129 # creator
130 def nodeCreator():
131  return OpenMayaMPx.asMPxPtr( circle() )
132 
133 
134 # initializer
135 def nodeInitializer():
136  nAttr = OpenMaya.MFnNumericAttribute()
137 
138  # Setup the input attributes
139  circle.aInput = nAttr.create("input", "in", OpenMaya.MFnNumericData.kFloat, 0.0)
140  nAttr.setStorable(True)
141 
142  circle.aScale = nAttr.create("scale", "sc", OpenMaya.MFnNumericData.kFloat, 10.0)
143  nAttr.setStorable(True)
144 
145  circle.aFrames = nAttr.create("frames", "fr", OpenMaya.MFnNumericData.kFloat, 48.0)
146  nAttr.setStorable(True)
147 
148  # Setup the output attributes
149  circle.aSOutput = nAttr.create("sineOutput", "so", OpenMaya.MFnNumericData.kFloat, 0.0)
150  nAttr.setWritable(False)
151  nAttr.setStorable(False)
152 
153  circle.aCOutput = nAttr.create("cosineOutput", "co", OpenMaya.MFnNumericData.kFloat, 0.0,)
154  nAttr.setWritable(False)
155  nAttr.setStorable(False)
156 
157  # Add the attributes to the node
158  circle.addAttribute(circle.aInput)
159  circle.addAttribute(circle.aScale)
160  circle.addAttribute(circle.aFrames)
161  circle.addAttribute(circle.aSOutput)
162  circle.addAttribute(circle.aCOutput)
163 
164  # Set the attribute dependencies
165  circle.attributeAffects(circle.aInput, circle.aSOutput)
166  circle.attributeAffects(circle.aInput, circle.aCOutput)
167  circle.attributeAffects(circle.aScale, circle.aSOutput)
168  circle.attributeAffects(circle.aScale, circle.aCOutput)
169  circle.attributeAffects(circle.aFrames, circle.aSOutput)
170  circle.attributeAffects(circle.aFrames, circle.aCOutput)
171 
172 
173 # initialize the script plug-in
174 def initializePlugin(mobject):
175  mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")
176  try:
177  mplugin.registerNode( kPluginNodeTypeName, kPluginNodeId, nodeCreator, nodeInitializer )
178  except:
179  sys.stderr.write( "Failed to register node: %s" % kPluginNodeTypeName )
180  raise
181 
182 
183 # uninitialize the script plug-in
184 def uninitializePlugin(mobject):
185  mplugin = OpenMayaMPx.MFnPlugin(mobject)
186  try:
187  mplugin.deregisterNode( kPluginNodeId )
188  except:
189  sys.stderr.write( "Failed to deregister node: %s" % kPluginNodeTypeName )
190  raise
191