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 )