41 This example show a custom solver at work. Two nCloth objects are created,
42 one is disconnected from the default nucleus solver, and hooked to
43 this custom solver node, which will just compute a sine wave motion on
46 A custom solver needs to have a minimum of 3 attributes:
48 -startState To be connected from the cloth object to the solver
49 -currentState To be connected from the cloth object to the solver
50 -nextState To be connected from the solver object to the cloth
52 and usually a 4th attribute that is the current time.
54 The idea is that when a solve is needed, the cloth object will pull on the
55 nextState attribute. At this point the solver should pull on either the
56 currentState attribute or the startState, depending on the current time.
57 Once it has the state information, the solver can extract that information,
58 solve one step, and stuff that information back into the MnCloth to
61 Below is some example code to test this plugin:
63 #**************************************************************************
64 # Note: Before running this code, make sure the plugin spTestNucleusNode is loaded!
65 #**************************************************************************
66 import maya.cmds as cmds
67 import maya.mel as mel
68 def setupCustomSolverScene():
69 cmds.file( f=True, new=True )
71 pPlane1 = cmds.polyPlane( w=5, h=5, sx=10, sy=10, ax=(0,1,0), cuv=2, ch=1 )
72 cmds.move( -10, 0, 0, r=True )
73 mel.eval( 'createNCloth 0' )
75 pPlane2 = cmds.polyPlane( w=5, h=5, sx=10, sy=10, ax=(0,1,0), cuv=2, ch=1 )
76 mel.eval( 'createNCloth 0' )
78 # Hookup plane2 (the cloth object created for plane2 is named nClothShape2) to our custom solver instead.
80 # First, disconnect it from the default nucleus solver:
81 cmds.disconnectAttr( 'nClothShape2.currentState', 'nucleus1.inputActive[1]' )
82 cmds.disconnectAttr( 'nClothShape2.startState', 'nucleus1.inputActiveStart[1]' )
83 cmds.disconnectAttr( 'nucleus1.outputObjects[1]', 'nClothShape2.nextState' )
85 # create our custom solver:
86 cmds.createNode( 'spTestNucleusNode' )
88 # Hookup plane2 to our custom solver:
89 cmds.connectAttr( 'spTestNucleusNode1.nextState[0]', 'nClothShape2.nextState' )
90 cmds.connectAttr( 'nClothShape2.currentState', 'spTestNucleusNode1.currentState[0]' )
91 cmds.connectAttr( 'nClothShape2.startState', 'spTestNucleusNode1.startState[0]' )
92 cmds.connectAttr( 'time1.outTime', 'spTestNucleusNode1.currentTime' )
97 import maya.OpenMaya
as OpenMaya
98 import maya.OpenMayaMPx
as OpenMayaMPx
99 import maya.OpenMayaFX
as OpenMayaFX
101 class testNucleusNode(OpenMayaMPx.MPxNode):
102 kPluginNodeName =
"spTestNucleusNode"
110 OpenMayaMPx.MPxNode.__init__(self)
112 def compute(self, plug, data):
113 if plug == testNucleusNode.nextState:
116 return OpenMaya.kUnknownParameter
117 logicalIndex = plug.logicalIndex()
119 currTime = data.inputValue(testNucleusNode.currentTime).asTime()
121 if currTime.value() <= 0.0:
122 multiDataHandle = data.inputArrayValue(testNucleusNode.startState)
123 multiDataHandle.jumpToElement( logicalIndex )
124 inputData = multiDataHandle.inputValue().data()
126 multiDataHandle = data.inputArrayValue(testNucleusNode.currentState)
127 multiDataHandle.jumpToElement( logicalIndex )
128 inputData = multiDataHandle.inputValue().data()
130 inputNData = OpenMayaFX.MFnNObjectData(inputData)
131 nObj = inputNData.getClothObjectPtr()
134 nObj.getPositions(points)
135 for ii
in range( points.length() ):
136 points[ii].y = math.sin( points[ii].x + currTime.value()*4.0*(3.1415/180.0) )
137 nObj.setPositions(points)
140 elif plug == testNucleusNode.currentState:
142 elif plug == testNucleusNode.startState:
145 return OpenMaya.kUnknownParameter
149 return OpenMayaMPx.asMPxPtr( testNucleusNode() )
155 testNucleusNode.startState = tAttr.create(
"startState",
"sst", OpenMaya.MFnData.kNObject)
156 tAttr.setWritable(
True)
157 tAttr.setStorable(
True)
158 tAttr.setHidden(
True)
161 testNucleusNode.currentState = tAttr.create(
"currentState",
"cst", OpenMaya.MFnData.kNObject)
162 tAttr.setWritable(
True)
163 tAttr.setStorable(
True)
164 tAttr.setHidden(
True)
167 testNucleusNode.nextState = tAttr.create(
"nextState",
"nst", OpenMaya.MFnData.kNObject)
168 tAttr.setWritable(
True)
169 tAttr.setStorable(
True)
170 tAttr.setHidden(
True)
174 testNucleusNode.currentTime = uniAttr.create(
"currentTime",
"ctm" , OpenMaya.MFnUnitAttribute.kTime, 0.0 )
176 testNucleusNode.addAttribute(testNucleusNode.startState)
177 testNucleusNode.addAttribute(testNucleusNode.currentState)
178 testNucleusNode.addAttribute(testNucleusNode.nextState)
179 testNucleusNode.addAttribute(testNucleusNode.currentTime)
181 testNucleusNode.attributeAffects(testNucleusNode.startState, testNucleusNode.nextState)
182 testNucleusNode.attributeAffects(testNucleusNode.currentState, testNucleusNode.nextState)
183 testNucleusNode.attributeAffects(testNucleusNode.currentTime, testNucleusNode.nextState)
186 def initializePlugin(mobject):
187 mplugin = OpenMayaMPx.MFnPlugin(mobject)
189 mplugin.registerNode( testNucleusNode.kPluginNodeName, testNucleusNode.kPluginNodeId, testNucleusNode.creator, testNucleusNode.initializer )
191 sys.stderr.write(
"Failed to register node: %s" % testNucleusNode.kPluginNodeName )
195 def uninitializePlugin(mobject):
196 mplugin = OpenMayaMPx.MFnPlugin(mobject)
198 mplugin.deregisterNode( testNucleusNode.kPluginNodeId )
200 sys.stderr.write(
"Failed to deregister node: %s" % testNucleusNode.kPluginNodeName )