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