1 from __future__
import division
43 This example show a custom solver at work. Two nCloth objects are created,
44 one is disconnected from the default nucleus solver, and hooked to
45 this custom solver node, which will just compute a sine wave motion on
48 A custom solver needs to have a minimum of 3 attributes:
50 -startState To be connected from the cloth object to the solver
51 -currentState To be connected from the cloth object to the solver
52 -nextState To be connected from the solver object to the cloth
54 and usually a 4th attribute that is the current time.
56 The idea is that when a solve is needed, the cloth object will pull on the
57 nextState attribute. At this point the solver should pull on either the
58 currentState attribute or the startState, depending on the current time.
59 Once it has the state information, the solver can extract that information,
60 solve one step, and stuff that information back into the MnCloth to
63 Below is some example code to test this plugin:
65 #**************************************************************************
66 # Note: Before running this code, make sure the plugin spTestNucleusNode is loaded!
67 #**************************************************************************
68 import maya.cmds as cmds
69 import maya.mel as mel
70 def setupCustomSolverScene():
71 cmds.file( f=True, new=True )
73 pPlane1 = cmds.polyPlane( w=5, h=5, sx=10, sy=10, ax=(0,1,0), cuv=2, ch=1 )
74 cmds.move( -10, 0, 0, r=True )
75 mel.eval( 'createNCloth 0' )
77 pPlane2 = cmds.polyPlane( w=5, h=5, sx=10, sy=10, ax=(0,1,0), cuv=2, ch=1 )
78 mel.eval( 'createNCloth 0' )
80 # Hookup plane2 (the cloth object created for plane2 is named nClothShape2) to our custom solver instead.
82 # First, disconnect it from the default nucleus solver:
83 cmds.disconnectAttr( 'nClothShape2.currentState', 'nucleus1.inputActive[1]' )
84 cmds.disconnectAttr( 'nClothShape2.startState', 'nucleus1.inputActiveStart[1]' )
85 cmds.disconnectAttr( 'nucleus1.outputObjects[1]', 'nClothShape2.nextState' )
87 # create our custom solver:
88 cmds.createNode( 'spTestNucleusNode' )
90 # Hookup plane2 to our custom solver:
91 cmds.connectAttr( 'spTestNucleusNode1.nextState[0]', 'nClothShape2.nextState' )
92 cmds.connectAttr( 'nClothShape2.currentState', 'spTestNucleusNode1.currentState[0]' )
93 cmds.connectAttr( 'nClothShape2.startState', 'spTestNucleusNode1.startState[0]' )
94 cmds.connectAttr( 'time1.outTime', 'spTestNucleusNode1.currentTime' )
98 from builtins
import range
100 import maya.OpenMaya
as OpenMaya
101 import maya.OpenMayaMPx
as OpenMayaMPx
102 import maya.OpenMayaFX
as OpenMayaFX
104 class testNucleusNode(OpenMayaMPx.MPxNode):
105 kPluginNodeName =
"spTestNucleusNode"
113 OpenMayaMPx.MPxNode.__init__(self)
115 def compute(self, plug, data):
116 if plug == testNucleusNode.nextState:
119 return OpenMaya.kUnknownParameter
120 logicalIndex = plug.logicalIndex()
122 currTime = data.inputValue(testNucleusNode.currentTime).asTime()
124 if currTime.value() <= 0.0:
125 multiDataHandle = data.inputArrayValue(testNucleusNode.startState)
126 multiDataHandle.jumpToElement( logicalIndex )
127 inputData = multiDataHandle.inputValue().data()
129 multiDataHandle = data.inputArrayValue(testNucleusNode.currentState)
130 multiDataHandle.jumpToElement( logicalIndex )
131 inputData = multiDataHandle.inputValue().data()
133 inputNData = OpenMayaFX.MFnNObjectData(inputData)
134 nObj = inputNData.getClothObjectPtr()
137 nObj.getPositions(points)
138 for ii
in range( points.length() ):
139 points[ii].y = math.sin( points[ii].x + currTime.value()*4.0*(3.1415/180.0) )
140 nObj.setPositions(points)
143 elif plug == testNucleusNode.currentState:
145 elif plug == testNucleusNode.startState:
148 return OpenMaya.kUnknownParameter
152 return OpenMayaMPx.asMPxPtr( testNucleusNode() )
158 testNucleusNode.startState = tAttr.create(
"startState",
"sst", OpenMaya.MFnData.kNObject)
159 tAttr.setWritable(
True)
160 tAttr.setStorable(
True)
161 tAttr.setHidden(
True)
164 testNucleusNode.currentState = tAttr.create(
"currentState",
"cst", OpenMaya.MFnData.kNObject)
165 tAttr.setWritable(
True)
166 tAttr.setStorable(
True)
167 tAttr.setHidden(
True)
170 testNucleusNode.nextState = tAttr.create(
"nextState",
"nst", OpenMaya.MFnData.kNObject)
171 tAttr.setWritable(
True)
172 tAttr.setStorable(
True)
173 tAttr.setHidden(
True)
177 testNucleusNode.currentTime = uniAttr.create(
"currentTime",
"ctm" , OpenMaya.MFnUnitAttribute.kTime, 0.0 )
179 testNucleusNode.addAttribute(testNucleusNode.startState)
180 testNucleusNode.addAttribute(testNucleusNode.currentState)
181 testNucleusNode.addAttribute(testNucleusNode.nextState)
182 testNucleusNode.addAttribute(testNucleusNode.currentTime)
184 testNucleusNode.attributeAffects(testNucleusNode.startState, testNucleusNode.nextState)
185 testNucleusNode.attributeAffects(testNucleusNode.currentState, testNucleusNode.nextState)
186 testNucleusNode.attributeAffects(testNucleusNode.currentTime, testNucleusNode.nextState)
189 def initializePlugin(mobject):
190 mplugin = OpenMayaMPx.MFnPlugin(mobject)
192 mplugin.registerNode( testNucleusNode.kPluginNodeName, testNucleusNode.kPluginNodeId, testNucleusNode.creator, testNucleusNode.initializer )
194 sys.stderr.write(
"Failed to register node: %s" % testNucleusNode.kPluginNodeName )
198 def uninitializePlugin(mobject):
199 mplugin = OpenMayaMPx.MFnPlugin(mobject)
201 mplugin.deregisterNode( testNucleusNode.kPluginNodeId )
203 sys.stderr.write(
"Failed to deregister node: %s" % testNucleusNode.kPluginNodeName )