Esempio n. 1
0
    def redoIt(self):
        mSel = OpenMaya.MSelectionList()
        mDagPath = OpenMaya.MDagPath()
        mFnMesh = OpenMaya.MFnMesh()
        OpenMaya.MGlobal.getActiveSelectionList(mSel)
        if mSel.length() >= 1:
            try:
                mSel.getDagPath(0, mDagPath)
                mFnMesh.setObject(mDagPath)
            except:
                print 'select a poly mesh'
        else:
            print 'select some poly Object'

        print 'I have passed line 46'
        print mDagPath.fullPathName()
        mPointArray = OpenMaya.MPointArray()
        mFnMesh.getPoints(mPointArray, OpenMaya.MSpace.kWorld)
        print 'I have passed 49'
        mFnParticle = OpenMayaFX.MFnParticleSystem()
        self.mObj_particle = mFnParticle.create()
        mFnParticle = OpenMayaFX.MFnParticleSystem(self.mObj_particle)

        counter = 0
        for i in xrange(mPointArray.length()):
            if i % self.sparse == 0:
                mFnParticle.emit(mPointArray[i])
                counter += 1
        print "Total Points : " + str(counter)
        mFnParticle.saveInitialState()
Esempio n. 2
0
    def redoIt(self):
        MSel = om.MSelectionList()
        MDag = om.MDagPath()
        MfnMesh = om.MFnMesh()
        om.MGlobal.getActiveSelectionList(MSel)

        if MSel.length() >= 1:
            try:
                MSel.getDagPath(0, MDag)
                MfnMesh.setObject(MDag)
            except:
                om.MGlobal.displayError("Select a poly mesh")
                return
        else:
            om.MGlobal.displayError("Select mesh object in scene")
            return
        #
        MPointArray = om.MPointArray()
        MfnMesh.getPoints(MPointArray, om.MSpace.kWorld)
        #
        MFnParticle = ofx.MFnParticleSystem()
        self.MObjParticle = MFnParticle.create()
        MFnParticle = ofx.MFnParticleSystem(self.MObjParticle)
        #
        #
        counter = 0

        for idx in range(MPointArray.length()):
            if idx % self.sparse == 0:
                MFnParticle.emit(MPointArray[idx])
                counter += 1

        om.MGlobal.displayInfo("Total points: {}".format(counter))
        MFnParticle.saveInitialState()
Esempio n. 3
0
    def redoIt(self):
        counter = 0
        mSel = OpenMaya.MSelectionList()
        mDagPath = OpenMaya.MDagPath()
        mFnMesh = OpenMaya.MFnMesh()
        OpenMaya.MGlobal.getActiveSelectionList(mSel)
        if mSel.length() > 0:
            try:
                mSel.getDagPath(0, mDagPath)
                mFnMesh.setObject(mDagPath)
            except:
                print "select a poly mesh"
                return
        else:
            print 'select a poly mesh'
            return

        mPointArray = OpenMaya.MPointArray()
        mFnMesh.getPoints(mPointArray, OpenMaya.MSpace.kWorld)
        print mFnMesh.name()
        print mPointArray.length()
        # create a particle system
        mFnParticle = OpenMayaFX.MFnParticleSystem()
        self.mObj_particle = mFnParticle.create()
        # fix some bug issue
        mFnParticle = OpenMayaFX.MFnParticleSystem(self.mObj_particle)
        for i in xrange(mPointArray.length()):
            if i % self.sparse == 0:
                mFnParticle.emit(mPointArray[i])
                counter += 1
        print 'Total Points:' + str(counter)
        mFnParticle.saveInitialState()
        return
Esempio n. 4
0
    def compareData(self, particleSystemShapes, inputData):

        if not isinstance(particleSystemShapes, (list, tuple)):
            particleSystemShapes = [particleSystemShapes]

        particleFnList = []

        sel = OpenMaya.MSelectionList()
        # Get API objet
        for particleSystem in particleSystemShapes:
            sel.add(particleSystem)

        for i, particleSystem in enumerate(particleSystemShapes):
            obj = OpenMaya.MObject()
            sel.getDependNode(i, obj)
            particleFnList.append(OpenMayaFX.MFnParticleSystem(obj))

        frameList = sorted(inputData.keys())
        # Compare alembic data with particleData in playback order
        for frame in inputData.keys():
            self.compareAtFrame(inputData, particleFnList, frame)

        # do it again in a random way, alembic should be consistent when playing randomly or backward
        random.shuffle(frameList)
        for frame in frameList:
            self.compareAtFrame(inputData,
                                particleFnList,
                                frame,
                                info="rand - ")
 def runTest(self):
     fluid = cmds.createNode('fluidShape')
     selList = om.MSelectionList()
     selList.add(fluid)
     dag = om.MDagPath()
     selList.getDagPath(0, dag)
     fx.MFnFluid(dag)
Esempio n. 6
0
 def __init__(self, fileHandle, dagPath):
     """
     Set up the objects we're dealing with
     """
     
     self.fileHandle = fileHandle
     self.dagPath = dagPath
     
     self.fFluid = OpenMayaFX.MFnFluid( dagPath )
Esempio n. 7
0
    def _TestPrototypes(self, instancerName):
        """
        Tests that all of the instancer prototypes made it to USD.
        """
        self.assertTrue(self.stage)
        instancer = OMFX.MFnInstancer(self._GetDagPath(instancerName))

        # Move to the last frame so that we can ensure all of the prototypes
        # are in use.
        cmds.currentTime(self.END_TIMECODE, edit=True)
        paths = OM.MDagPathArray()
        matrices = OM.MMatrixArray()
        particlePathStartIndices = OM.MIntArray()
        pathIndices = OM.MIntArray()
        instancer.allInstances(paths, matrices, particlePathStartIndices,
                               pathIndices)

        # Check that the Maya instanced objects are what we think they are.
        pathStrings = [paths[i].fullPathName() for i in range(paths.length())]
        self.assertEqual(
            pathStrings,
            [
                # 0 (logical 0) - Cube
                "|dummyGroup|pCube1|pCubeShape1",
                "|dummyGroup|pCube1|pSphere1|pSphereShape1",
                # 1 (logical 2) - Sphere
                "|InstancerTest|%s|prototypeUnderInstancer|prototypeUnderInstancerShape"
                % instancerName,
                # 2 (logical 3) - Reference
                "|referencePrototype|NS_referencePrototype:Geom|NS_referencePrototype:Cone|NS_referencePrototype:ConeShape"
            ])

        # Check that the USD prims have correct type name, references, kinds,
        # kinds, instancerTranslate xformOps.
        instancerPrim = self.stage.GetPrimAtPath("/InstancerTest/%s" %
                                                 instancerName)
        self.assertEqual(
            Usd.ModelAPI(instancerPrim).GetKind(), Kind.Tokens.subcomponent)

        prototypesPrim = instancerPrim.GetChild("Prototypes")
        self.assertEqual(len(prototypesPrim.GetChildren()), 3)
        self.assertEqual(
            Usd.ModelAPI(prototypesPrim).GetKind(), Kind.Tokens.subcomponent)

        # Note that pCube1_0 is a special case where instancerTranslate
        # isn't the opposite of translate, so both have to be left in.
        prototype0 = prototypesPrim.GetChild("pCube1_0")
        self._AssertPrototype(prototype0, "Xform", 2, True)

        prototype1 = prototypesPrim.GetChild("prototypeUnderInstancer_1")
        self._AssertPrototype(prototype1, "Mesh", 0, False)

        prototype2 = prototypesPrim.GetChild("referencePrototype_2")
        self._AssertPrototype(prototype2, "Xform", 1, False)
        self.assertEqual(
            Usd.ModelAPI(prototype2).GetAssetName(), "ConeAssetName")
Esempio n. 8
0
    def redoIt(self):
        # Read Selection/Actively selected objects
        mSel = openmaya.MSelectionList()
        mDagPath = openmaya.MDagPath()
        mFnMesh = openmaya.MFnMesh()
        openmaya.MGlobal.getActiveSelectionList(mSel)
        if mSel.length() >= 1:
            try:
                mSel.getDagPath(0, mDagPath)
                # attach the mesh to the MFnMesh
                mFnMesh.setObject(mDagPath)
            except:
                print "Select a poly mesh"
                return openmaya.kUnknownParameter

        else:
            print "Select a poly mesh"
            return openmaya.kUnknownParameter

        # Read vertex positions of selected Mesh
        mPointArray = openmaya.MPointArray()
        mFnMesh.getPoints(mPointArray, openmaya.MSpace.kWorld)

        # Create a particle system
        mFnParticle = openmayafx.MFnParticleSystem()
        self.mObj_particle = mFnParticle.create()

        # Fix maya bug
        mFnParticle = openmayafx.MFnParticleSystem(self.mObj_particle)

        # Attach the particles on the vertex positions
        counter = 0
        for i in xrange(mPointArray.length()):
            if i % self.sparse == 0:
                mFnParticle.emit(mPointArray[i])
                counter += 1
        print "Total points :" + str(counter)

        # After emitting the particle, we have to save the initial state of the particle as well,
        # otherwise if you apply any dynamics on it, your particles would never come back to their actual positions.
        mFnParticle.saveInitialState()
Esempio n. 9
0
    def doIt(self, args):
        ''' Command's first-time execution. '''

        # Clear the current selection list to avoid any wrong grouping.
        OpenMaya.MGlobal.clearSelectionList()

        # Create the turbulence field
        self.dagModifier.commandToExecute('turbulence -name "' + self.turbulenceFieldName + '"')
        self.dagModifier.commandToExecute('scale ' + str(0.5 * self.size_x) + ' '
                                          + str(0.5 * self.size_y) + ' '
                                          + str(0.5 * self.size_z) + ' '
                                          + self.turbulenceFieldName)
        self.dagModifier.commandToExecute(
            'setAttr "' + self.turbulenceFieldName + '.volumeShape" 1')  # 1 for cube, 2 for sphere.
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.magnitude" 100')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.attenuation" 0.1')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.frequency" 4')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.interpolationType" 1')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.noiseLevel" 8')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.noiseRatio" 1')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.trapInside" 1')
        self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.trapRadius" 1')

        # Create the particle system
        self.dagModifier.commandToExecute('particle -name "' + self.particleSystemName + '"')
        self.dagModifier.commandToExecute('setAttr "' + self.particleSystemName + 'Shape.conserve" 0.75')
        self.dagModifier.commandToExecute(
            'setAttr "' + self.particleSystemName + 'Shape.particleRenderType" 6')  # 3 for points, 6 for streaks

        # Connect the particle system to the turbulence field.
        self.dagModifier.commandToExecute(
            'connectDynamic -f ' + self.turbulenceFieldName + ' ' + self.particleSystemName + 'Shape')

        # Execute the commands enqueued in the MDagModifier.
        self.dagModifier.doIt()

        # Call a helper function to obtain the MDagPath of the shape.
        particleShapeDagPath = self.getDagPathToObject(self.particleSystemName + 'Shape')

        # Create a function set around the particleShapeDagPath.
        particleSystemFn = OpenMayaFX.MFnParticleSystem(particleShapeDagPath)

        # Randomly generate the positions of the particles within the volume.
        for i in range(0, self.numParticles):
            self.particlePositions.append(random.uniform(0.5 * -self.size_x, 0.5 * self.size_x),
                                          random.uniform(0.5 * -self.size_y, 0.5 * self.size_y),
                                          random.uniform(0.5 * -self.size_z, 0.5 * self.size_z))

        # Emit particles using the particle positions.
        particleSystemFn.emit(self.particlePositions)

        # Save the starting positions of the particles, so we can scrub the timeline.
        particleSystemFn.saveInitialState()
Esempio n. 10
0
    def testTransforms(self):
        """
        Check that the point transforms are correct.
        """
        mayaInstancer = OMFX.MFnInstancer(self._GetDagPath("instancer1"))
        usdInstancer = UsdGeom.PointInstancer(
            self.stage.GetPrimAtPath("/InstancerTest/instancer1"))

        time = self.START_TIMECODE
        while time <= self.END_TIMECODE:
            cmds.currentTime(time, edit=True)

            # Need to do this because MFnInstancer will give instance matrices
            # as offsets from prototypes' original world space positions.
            worldPositions = [
                self._GetWorldSpacePosition("|dummyGroup|pCube1"),
                self._GetWorldSpacePosition(
                    "|InstancerTest|instancer1|prototypeUnderInstancer"),
                self._GetWorldSpacePosition("|referencePrototype")
            ]

            paths = OM.MDagPathArray()
            matrices = OM.MMatrixArray()
            particlePathStartIndices = OM.MIntArray()
            pathIndices = OM.MIntArray()
            mayaInstancer.allInstances(paths, matrices,
                                       particlePathStartIndices, pathIndices)

            usdInstanceTransforms = \
                    usdInstancer.ComputeInstanceTransformsAtTime(time, time)
            usdProtoIndices = usdInstancer.GetProtoIndicesAttr().Get(time)

            self.assertEqual(matrices.length(), len(usdInstanceTransforms))

            # Compute the instancer-space position of instances in Maya
            # (including the protos' transforms). By default, this is what
            # UsdGeomPointInstancer::ComputeInstanceTransformsAtTime already
            # gives us.
            mayaWorldPositions = [
                worldPositions[protoIndex] for protoIndex in usdProtoIndices
            ]
            mayaGfMatrices = [
                mayaWorldPositions[i] * self._MayaToGfMatrix(matrices[i])
                for i in xrange(matrices.length())
            ]
            usdGfMatrices = [
                usdInstanceTransforms[i]
                for i in xrange(len(usdInstanceTransforms))
            ]
            for i in xrange(len(usdGfMatrices)):
                self._AssertXformMatrices(mayaGfMatrices[i], usdGfMatrices[i])

            time += 1.0
Esempio n. 11
0
    def redoIt(self):
        mSel = OpenMaya.MSelectionList()
        mDagPath = OpenMaya.MDagPath()
        mFnMesh = OpenMaya.MFnMesh()
        OpenMaya.MGlobal.getActiveSelectionList(
            mSel)  # return a MselectionList of current selection
        if mSel.length() >= 1:
            try:
                mSel.getDagPath(0, mDagPath)
                mFnMesh.setObject(mDagPath)
            except:
                print 'Select a polymesh'
                return OpenMaya.kUnknownParameter

        else:
            print 'Select a polymesh'
            return OpenMaya.kUnknownParameter

        # store vertex points in a MPointArray
        mPointArray = OpenMaya.MPointArray()
        mFnMesh.getPoints(mPointArray, OpenMaya.MSpace.kWorld)

        # Create a particle system
        mFnParticle = OpenMayaFX.MFnParticleSystem()
        self.mObj_particle = mFnParticle.create()

        # to fix maya bug
        mFnParticle = OpenMayaFX.MFnParticleSystem(self.mObj_particle)

        counter = 0
        for i in xrange(mPointArray.length()):
            # don't understand this
            if (i % self.sparse) == 0:
                mFnParticle.emit(mPointArray[i])
                counter += 1
        print 'Total points: %s' % str(counter)
        mFnParticle.saveInitialState()
        print 'This is self.sparse %s' % self.sparse
Esempio n. 12
0
 def particlePoints(self, selection, scale):
     dagPath = om.MDagPath()
     iter = om.MItSelectionList(selection, om.MFn.kParticle)
     partPoints = []
     vec = om.MVectorArray()
     while not iter.isDone():
         iter.getDagPath(dagPath)
         part = omx.MFnParticleSystem(dagPath)
         part.position(vec)
         for i in range(vec.length()):
             partPoints.append([
                 vec[i].x * scale, vec[i].y * scale, vec[i].z * scale * -1
             ])
         iter.next()
     return partPoints
Esempio n. 13
0
    def testInstancePaths(self):
        """
        Checks that the proto index assigned for each point is correct.
        """
        mayaInstancer = OMFX.MFnInstancer(self._GetDagPath("instancer1"))
        usdInstancer = UsdGeom.PointInstancer(
            self.stage.GetPrimAtPath("/InstancerTest/instancer1"))

        time = self.START_TIMECODE
        while time <= self.END_TIMECODE:
            cmds.currentTime(time, edit=True)

            paths = OM.MDagPathArray()
            matrices = OM.MMatrixArray()
            particlePathStartIndices = OM.MIntArray()
            pathIndices = OM.MIntArray()
            mayaInstancer.allInstances(paths, matrices,
                                       particlePathStartIndices, pathIndices)
            usdProtoIndices = usdInstancer.GetProtoIndicesAttr().Get(time)

            # Mapping of proto index to index(es) in the paths array.
            # Note that in the Maya instancer a single point may map to multiple
            # DAG paths, which correspond to all the shapes in the instanced
            # hierarchy.
            usdIndicesToMayaIndices = {
                0: [0, 1],  # the first prototype has two shapes in hierarchy
                1: [2],  # this prototype only has one shape
                2: [3],  # the reference prototype only has one shape
            }

            for i in xrange(len(usdProtoIndices)):
                usdProtoIndex = usdProtoIndices[i]
                expectedMayaIndices = usdIndicesToMayaIndices[usdProtoIndex]

                mayaIndicesStart = particlePathStartIndices[i]
                mayaIndicesEnd = particlePathStartIndices[i + 1]

                self.assertEqual(mayaIndicesEnd - mayaIndicesStart,
                                 len(expectedMayaIndices))
                actualPathIndices = [
                    pathIndices[i]
                    for i in xrange(mayaIndicesStart, mayaIndicesEnd)
                ]
                self.assertEqual(actualPathIndices, expectedMayaIndices)

            time += 1.0
Esempio n. 14
0
 def particlePoints2(self, selection, scale):
     dagPath = om.MDagPath()
     iter = om.MItSelectionList(selection, om.MFn.kParticle)
     partPoints = []
     vec = om.MVectorArray()
     if self.op['globalpos']:
         space = 'worldPosition'
     else:
         space = 'position'
     while not iter.isDone():
         iter.getDagPath(dagPath)
         part = omx.MFnParticleSystem(dagPath)
         part.getPerParticleAttribute(space, vec)
         for i in range(vec.length()):
             partPoints.append([
                 vec[i].x * scale, vec[i].y * scale, vec[i].z * scale * -1
             ])
         iter.next()
     return partPoints
Esempio n. 15
0
    def compute(self, plug, data):
        if plug == testNucleusNode.nextState:
            if plug.isArray():
                # don't support evaluation of the whole array plug, only its elements
                return OpenMaya.kUnknownParameter
            logicalIndex = plug.logicalIndex()
            # get the value of the currentTime
            currTime = data.inputValue(testNucleusNode.currentTime).asTime()
            # pull on start state or current state depending on the current time.
            if currTime.value() <= 0.0:
                multiDataHandle = data.inputArrayValue(
                    testNucleusNode.startState)
                multiDataHandle.jumpToElement(logicalIndex)
                inputData = multiDataHandle.inputValue().data()
            else:
                multiDataHandle = data.inputArrayValue(
                    testNucleusNode.currentState)
                multiDataHandle.jumpToElement(logicalIndex)
                inputData = multiDataHandle.inputValue().data()

            inputNData = OpenMayaFX.MFnNObjectData(inputData)
            nObj = inputNData.getClothObjectPtr()

            points = OpenMaya.MFloatPointArray()
            nObj.getPositions(points)
            for ii in range(points.length()):
                points[ii].y = math.sin(points[ii].x + currTime.value() * 4.0 *
                                        (3.1415 / 180.0))
            nObj.setPositions(points)

            data.setClean(plug)
        elif plug == testNucleusNode.currentState:
            data.setClean(plug)
        elif plug == testNucleusNode.startState:
            data.setClean(plug)
        else:
            return OpenMaya.kUnknownParameter
Esempio n. 16
0
def getPartticlePos(parDag, parCom):
    parPos = mom.MVectorArray()
    parDag.extendToShape()
    parSysFn = momf.MFnParticleSystem(parDag)
    parSysFn.position(parPos)

    isParticle = parDag.hasFn(mom.MFn.kParticle)
    isNParticle = parDag.hasFn(mom.MFn.kNParticle)
    if (isParticle == 0) and (isNParticle == 0):
        return parPos

    if (parCom.isNull() == 0) and (parCom.apiType()
                                   == mom.MFn.kDynParticleSetComponent):
        compFn = mom.MFnSingleIndexedComponent(parCom)
        idArray = mom.MIntArray()
        compFn.getElements(idArray)
        newPos = mom.MVectorArray()
        if idArray.length() != 0:
            for i in range(0, idArray.length()):
                newPos.append(parPos[idArray[i]])
            return newPos
        else:
            return parPos
    return parPos
    def doIt(self, args):
        #command's first-time execution
        #parse the flags and the arguments!!
        try:
            self.parseArgs(args)
        except Exception:
            #an exception should be thrown here if the argument/flag syntax is wrong.
            print('Invalid flag syntax for parse command!')
            return  #END EXECUTION!! dont carry on..

        #clear the current selection list to avoid any wrong grouping.
        OpenMaya.MGlobal.clearSelectionList()

        #create the "turbulence field". got help online for these!
        self.dagModifier.commandToExecute('turbulence -name "' +
                                          self.tur_field_name + '"')
        self.dagModifier.commandToExecute('scale ' + str(0.5 * self.size_x) +
                                          ' ' + str(0.5 * self.size_y) + ' ' +
                                          str(0.5 * self.size_z) + ' ' +
                                          self.tur_field_name)
        self.dagModifier.commandToExecute(
            'setAttr "' + self.tur_field_name + '.volumeShape" ' +
            str(self.volShapeNum)
        )  # 1 for cube, 2 for sphere ... check maya doc for more (goes uptil 5)
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.magnitude" 100')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.attenuation" 0.1')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.frequency" 4')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.interpolationType" 1')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.noiseLevel" 8')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.noiseRatio" 1')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.trapInside" 1')
        self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name +
                                          '.trapRadius" 1')

        # create the particle system of "bees" or particles
        self.dagModifier.commandToExecute('particle -name "' +
                                          self.particle_system_name + '"')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.particle_system_name +
                                          'Shape.conserve" 1.00')
        self.dagModifier.commandToExecute(
            'setAttr "' + self.particle_system_name +
            'Shape.particleRenderType" 6')  # 3 for points, 6 for streaks

        #connect the particle system to the turbulence field.
        #COPIED!!
        self.dagModifier.commandToExecute('connectDynamic -f ' +
                                          self.tur_field_name + ' ' +
                                          self.particle_system_name + 'Shape')
        self.dagModifier.doIt()
        particleShapeDagPath = self.getDagPathToObject(
            self.particle_system_name + 'Shape')
        particleSystemFn = OpenMayaFX.MFnParticleSystem(particleShapeDagPath)

        #randomly generate the positions of the particles within the volume.
        for i in range(0, self.numParticles):
            self.particlePositions.append(
                random.uniform(0.5 * -self.size_x, 0.5 * self.size_x),
                random.uniform(0.5 * -self.size_y, 0.5 * self.size_y),
                random.uniform(0.5 * -self.size_z, 0.5 * self.size_z))

        #emit means to display the particles at those positions
        particleSystemFn.emit(self.particlePositions)
        particleSystemFn.saveInitialState()
Esempio n. 18
0
def getData(particleSystemShapes,
            frameRange=(1, 24),
            abc=False,
            customAttribute=[]):
    '''
    Create a dict containing data

    exemple:

    dict = { frame : { attibute : [data] }

     3: "nParticle_test_1Shape" : {'id': [0.0],
                                  'position':  [(-0.0025255996733903885, 4.990767002105713, -0.0024415384978055954)],
                                  'radius':    [0.20000000298023224],
                                  'rgbPP':       [(0.44199632268870914, 0.2631281241639378, 0.6541382528648185)],
                                  'rotationPP':  [(0.0, -0.0, 0.0)],
                                  'velocity':    [(-0.6160576343536377, 0.1030367910861969, -0.5955522060394287)]},
    '''

    if not isinstance(particleSystemShapes, (list, tuple)):
        particleSystemShapes = [particleSystemShapes]

    # Get API objet
    particleFnList = []
    sel = OpenMaya.MSelectionList()
    for particleSystem in particleSystemShapes:
        sel.add(particleSystem)

    for i, particleSystem in enumerate(particleSystemShapes):
        obj = OpenMaya.MObject()
        stdoutWrite("%d: %s" % (i, particleSystem))
        sel.getDependNode(i, obj)
        particleFnList.append(OpenMayaFX.MFnParticleSystem(obj))

    testData = {}

    # seed on first frame (doing the same before alembic export to correctly match randomly generated attributes)
    cmds.currentTime(1)
    maya.mel.eval("seed(1)")

    frameList = range(frameRange[0], frameRange[1])

    perParticleAttr = ("particleId", "position", "acceleration", "velocity",
                       "radius", "force", "rgbPP", "mass", "age", "lifespanPP")
    for item in customAttribute:
        perParticleAttr.append(item)

    # Now eval the frameList
    for frame in frameList:

        stdoutWrite("fame: %d" % frame)

        # Jump to frame
        OpenMaya.MGlobal.viewFrame(frame)
        testData[frame] = {}

        for particleFn in particleFnList:

            stdoutWrite("\t: %s" % particleFn.name())
            # Force evaluate dynamics
            particleFn.evaluateDynamics(OpenMaya.MTime(frame), False)

            testData[frame][particleFn.name()] = {}

            # Get all perParticle attributes for current Shape
            for attr in perParticleAttr:
                if cmds.objExists("%s.%s" % (particleFn.name(), attr)):
                    testData[frame][
                        particleFn.name()][attr] = getParticleAttribute(
                            particleFn, attr, abc=abc)

    return testData
Esempio n. 19
0
class Volume(ExportModule):
    """
    Fluid volume export module
    """
    
    fFluid = OpenMayaFX.MFnFluid()
    
    def __init__(self, fileHandle, dagPath):
        """
        Set up the objects we're dealing with
        """
        
        self.fileHandle = fileHandle
        self.dagPath = dagPath
        
        self.fFluid = OpenMayaFX.MFnFluid( dagPath )
        
    def getOutput(self):
        """
        Read Fluid data and export as volumegrid
        """
    
        xPtr = OpenMaya.MScriptUtil().asDoublePtr()
        yPtr = OpenMaya.MScriptUtil().asDoublePtr()
        zPtr = OpenMaya.MScriptUtil().asDoublePtr()
        self.fFluid.getDimensions( xPtr, yPtr, zPtr )
        dimX = OpenMaya.MScriptUtil( xPtr ).asDouble() / 2
        dimY = OpenMaya.MScriptUtil( yPtr ).asDouble() / 2
        dimZ = OpenMaya.MScriptUtil( zPtr ).asDouble() / 2
        
        #xrPtr = OpenMaya.MScriptUtil().asIntPtr()
        #yrPtr = OpenMaya.MScriptUtil().asIntPtr()
        #zrPtr = OpenMaya.MScriptUtil().asIntPtr()
        #self.fFluid.getResolution( xrPtr, yrPtr, zrPtr )
        #xres = OpenMaya.MScriptUtil( xrPtr ).asInt()
        #yres = OpenMaya.MScriptUtil( yrPtr ).asInt()
        #zres = OpenMaya.MScriptUtil( zrPtr ).asInt()
        
        # getResolution is NOT IMPLEMENTED !!! ??!
        
        # therefore, assume equal res in every direction
        xres = yres = zres = round(self.fFluid.gridSize()**0.333333333333)
        
        self.addToOutput( 'AttributeBegin' )
        self.addToOutput( self.translationMatrix(self.dagPath) )
        
        self.addToOutput( '\tVolume "volumegrid"' )
        self.addToOutput( '\t\t"color sigma_a" [0.9 0.9 0.9]' )
        self.addToOutput( '\t\t"point p0" [%f %f %f]' % (-dimX, -dimY, -dimZ) )
        self.addToOutput( '\t\t"point p1" [%f %f %f]' % ( dimX,  dimY,  dimZ) )
        
        self.addToOutput( '\t\t"integer nx" [%i]' % xres )
        self.addToOutput( '\t\t"integer ny" [%i]' % yres )
        self.addToOutput( '\t\t"integer nz" [%i]' % zres )
        
        self.addToOutput( '\t\t"float density" [' )

        outStr = str()
        for i in range(0, self.fFluid.gridSize()):
            outStr += '%f ' % OpenMaya.MScriptUtil.getFloatArrayItem( self.fFluid.density(), i)
        
        self.addToOutput( '\t\t\t%s' % outStr )
        self.addToOutput( '\t\t]' )
    
        self.addToOutput( 'AttributeEnd' )
        self.addToOutput( '' )
Esempio n. 20
0
def set_initial_state(npNode=None, npFnPart=None):
    """
    Given a particle dependency node calculate the start goalU and and goalV values
    :param npNode: Particle dependency node to get goal data from
    :param npFnPart: particle function set we can get the points from and set data
    """
    print '#----------------------------#'
    print 'Setting initial state'

    # before we start set the time back to the first frame
    tMin = int(cmds.playbackOptions(q=True, minTime=True))
    cmds.currentTime(tMin, e=True)

    # a dict of all the base attributes we want to make sure exist!
    attrs = {
        'goalU': {
            'longName': 'goalU',
            'shortName': 'goalU',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'goalV': {
            'longName': 'goalV',
            'shortName': 'goalV',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'verticalSpeedPP': {
            'longName': 'verticalSpeedPP',
            'shortName': 'vSpePP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'rotationRatePP': {
            'longName': 'rotationRatePP',
            'shortName': 'rotRtPP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'jitterIntervalPP': {
            'longName': 'jitterIntervalPP',
            'shortName': 'jtrIntPP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'jitterStepPP': {
            'longName': 'jitterStepPP',
            'shortName': 'jtrStpPP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'jitterRangePP': {
            'longName': 'jitterRangePP',
            'shortName': 'jtrRngPP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'jitterValuePP': {
            'longName': 'jitterValuePP',
            'shortName': 'jtrValPP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'isDonePP': {
            'longName': 'isDonePP',
            'shortName': 'isDonePP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        },
        'lifespanPP': {
            'longName': 'lifespanPP',
            'shortName': 'lifespanPP',
            'initialState': True,
            'type': om.MFnNumericData.kDoubleArray,  # @UndefinedVariable
            'data': om.MDoubleArray()
        }
    }

    # if nothing passed in we assume we are updating intial state
    # so need to setup npNode and npFnPart from selection
    if not npNode:
        sel = cmds.ls(sl=True, l=True)

        if len(sel) == 0:
            print 'Please select a nParticle system to update initial state on!'
            return

        # from the list make sure the first object is a nparticle system, get a handle on this
        # then remove from the list
        if not cmds.objectType(sel[0]) == 'nParticle':

            shape = cmds.listRelatives(sel[0])[0]

            if not cmds.objectType(shape) == 'nParticle':
                print 'Please select a nParticle system followed by objects to goal to!'
                return

            else:
                npShape = shape

        else:
            npShape = sel.pop(0)

        # now we have our particle system we need to get the
        # dependency node and particle system function set
        selList = om.MSelectionList()
        selList.add(npShape)

        npDag = om.MDagPath()
        npMObj = om.MObject()

        selList.getDependNode(0, npMObj)
        selList.getDagPath(0, npDag)

        npNode = om.MFnDependencyNode(npMObj)
        npFnPart = omfx.MFnParticleSystem(npDag)

    # make sure that we have a valid function set
    if npFnPart == None:
        print '###Error: Please make sure you pass in both a dependency node and function set or neither!'
        return

    # get the goalGeometry plug. this can tell us what our
    # particle is goaled to
    goalGeo_plug = npNode.findPlug('goalGeometry')

    # get the first item that is connected as a goal (this will be our initial goal)
    goal_plug = goalGeo_plug.elementByPhysicalIndex(0)
    attrName = goal_plug.name()

    # get the goal index number (this may not be 0)
    goalIndex = attrName.split('[')[-1].split(']')[0]

    # create the goal weight attribute
    attrs['goalWeight{}PP'.format(goalIndex)] = {
        'longName': 'goalWeight%sPP' % goalIndex,
        'shortName': 'goalWeight%sPP' % goalIndex,
        'initialState': True,
        'type': om.MFnNumericData.kDoubleArray,
        'data': om.MDoubleArray()
    }

    # make sure that all the attributes we need exist
    _create_attributes(npNode, attrs)

    # get all the objects connected to our goal array plug (should only be 1!)
    mPlugArray = om.MPlugArray()
    goal_plug.connectedTo(mPlugArray, True, False)

    if mPlugArray.length() > 1:
        print '###Error :More than one object is connected to this goal plug. Weird!'
        return

    goalMeshFn = om.MFnMesh()

    # get the node that is connected the plug and get a mesh function set
    goal_obj = mPlugArray[0].node()
    goal_dagpath = om.MDagPath().getAPathTo(goal_obj)
    goalMeshFn.setObject(goal_dagpath)

    # get user defined variables
    verticalOffset = 0
    goalWeight_min = 0.2
    goalWeight_max = 0.4
    verticleSpeed_min = 0.005
    verticleSpeed_max = 0.0075
    rotationSpeed = 0.1
    jitterInterval = 10
    jitterRange = 0.01

    # setup a bunch of arrays we are about to calculate
    # then get a list of all the points in our particle system and iterate through them
    partPosArray = om.MVectorArray()

    npFnPart.position(partPosArray)

    # for each particle we want to calculate information on the intial state
    # for all of our pp attributes we want to set
    for i in range(partPosArray.length()):

        # get our particle point as a vector
        partPoint = partPosArray[i]

        # get the goal uvs closest to our point
        uvArray = [0, 0]
        scriptUtil = om.MScriptUtil()
        scriptUtil.createFromList(uvArray, 2)
        uvPoint = scriptUtil.asFloat2Ptr()

        goalMeshFn.getUVAtPoint(om.MPoint(partPoint), uvPoint,
                                om.MSpace.kWorld)

        uPoint = om.MScriptUtil.getFloat2ArrayItem(uvPoint, 0, 0)
        #vPoint = om.MScriptUtil.getFloat2ArrayItem(uvPoint, 0, 1)

        # append to our goalU and goalV array
        attrs['goalU']['data'].append(uPoint % 1)
        attrs['goalV']['data'].append(random.uniform(0, verticalOffset))

        goalWeight = random.uniform(goalWeight_min, goalWeight_max)

        # give this particle a random goal weight
        attrs['goalWeight%sPP' % goalIndex]['data'].append(goalWeight)
        #goal_weights.append(1)

        # set a bunch of attributes used to control motion of particles
        attrs['verticalSpeedPP']['data'].append(
            random.uniform(verticleSpeed_min, verticleSpeed_max))

        adjustedRot = rotationSpeed * (1.1 - goalWeight)

        attrs['rotationRatePP']['data'].append(random.uniform(0, adjustedRot))
        attrs['jitterIntervalPP']['data'].append(
            random.randint(1, jitterInterval))
        attrs['jitterStepPP']['data'].append(0)
        attrs['jitterRangePP']['data'].append(jitterRange)
        attrs['jitterValuePP']['data'].append(
            random.uniform((-1 * jitterRange), jitterRange))

        attrs['isDonePP']['data'].append(0)

        attrs['lifespanPP']['data'].append(100000000000000000)

    # for each item in our attrs dictionary we want to set the attribute data
    for i in attrs:
        print 'Setting: %s' % i
        if npFnPart.hasAttribute(i):
            npFnPart.setPerParticleAttribute(i, attrs[i]['data'])

    # save our intial state (NB: if the particle sim has moved on from particle start it
    # will overwrite their positions. Write a check in at the start of function)
    npFnPart.saveInitialState()
Esempio n. 21
0
def bake(instancerName, start, end, progress=None):
    """
    Process an instancer node over the specified frame range, reading the 
    positions and objects. With this data objects are duplicated and 
    positioned to mimic the instancer. With the particle data individual 
    objects can be matched over the different frames and animated. When
    a particle "dies", the visibility is turned off.

    :param str instancerName: Name if the instancer to bake
    :param int start: Start frame
    :param int end: End frame
    :param QProgressBar progress: Update ui ( Optional )
    :return: Group that contains all of the baked information
    :rtype: str
    :raises RuntimeError: When the instancer doesn't exist
    :raises RuntimeError: When there are no particles attached
    """
    # store all particle information in data variable
    data = {}

    # get instance
    if not cmds.objExists(instancerName):
        raise RuntimeError("Instancer doesn't exist!")
        return

    # set visible
    cmds.setAttr("{0}.visibility".format(instancerName), 1)

    instancerObj = asMObject(instancerName)
    instancerDag = asMDagPath(instancerObj)
    instancer = OpenMayaFX.MFnInstancer(instancerDag)

    # get particles
    particleName = cmds.listConnections(
        "{0}.inputPoints".format(instancerName))
    if not particleName:
        raise RuntimeError("No particles connected!")
        return

    particleName = particleName[0]
    particleObj = asMObject(particleName)
    particleDag = asMDagPath(particleObj)
    particle = OpenMayaFX.MFnParticleSystem(particleDag)

    # variables
    ages = OpenMaya.MDoubleArray()
    paths = OpenMaya.MDagPathArray()
    matrices = OpenMaya.MMatrixArray()
    particleIndices = OpenMaya.MIntArray()
    pathIndices = OpenMaya.MIntArray()

    # create container group
    container = cmds.group(world=True,
                           empty=True,
                           n="{0}_bake_1".format(instancerName))

    # loop time
    for i in range(start, end + 1):
        # set time
        cmds.currentTime(i)

        # query instancer information
        instancer.allInstances(paths, matrices, particleIndices, pathIndices)

        # query particle information
        particle.age(ages)

        # loop particle instances
        num = matrices.length()
        for j in range(num):
            # get particles index
            p = particleIndices[j]

            # get parent
            parent = paths[pathIndices[j]].fullPathName()

            # get age
            age = ages[j]

            if data.get(p):
                # get path and age
                path = data[p].get("path")

                oldAge = data[p].get("age")
                oldParent = data[p].get("parent")

                # check if age is less than previous
                if age < oldAge:
                    # hide mesh and delete particle id data
                    keyVisibility(path, i, 0)
                    del (data[p])

                # check if parent is the same as previous
                elif parent != oldParent:
                    # hide mesh and delete particle id data
                    keyVisibility(path, i, 0)
                    del (data[p])

            # duplicate path if index not in data
            if not data.get(p):
                # get parent name
                parentShort = parent.split("|")[-1].split(":")[-1]

                # duplicate mesh
                name = "{0}_{1}_1".format(instancerName, parentShort)
                path = cmds.duplicate(parent, n=name)[0]
                path = cmds.parent(path, container)[0]

                # handle visibility
                keyVisibility(path, i, 1)

                # get dag
                dag = asMDagPath(asMObject(path))

                # get matrix
                transform = asMFnTransform(dag)
                matrix = transform.transformation().asMatrix()

                # store variables
                data[p] = {}
                data[p]["path"] = path
                data[p]["dag"] = dag
                data[p]["matrix"] = matrix
                data[p]["parent"] = parent

            # get variables
            path = data[p].get("path")
            dag = data[p].get("dag")
            matrix = data[p].get("matrix")

            # store age
            data[p]["age"] = age

            # set matrix
            m = matrix * matrices[j]
            m = OpenMaya.MTransformationMatrix(m)

            transform = asMFnTransform(dag)
            transform.set(m)

            # set keyframes
            keyTransform(path, i)

        # update progress
        if progress:
            progress.setValue(i + 1 - start)

    return container
def sampleColorAtParticle(textureNode, particleShapeNode):

    # get the particle object as an MObject

    selectionList = om.MSelectionList()
    selectionList.add(particleShapeNode)
    particleObject = om.MObject()
    selectionList.getDependNode(0, particleObject)

    # create a MFnParticle to get to the data

    particleDataFn = omFX.MFnParticleSystem(particleObject)

    # get the positionPP data

    posPPArray = om.MVectorArray()

    particleDataFn.getPerParticleAttribute("position", posPPArray)

    # these are the arguments required to sample a 3d texture:
    shadingNodeName = textureNode

    numSamples = posPPArray.length()
    pointArray = om.MFloatPointArray()
    pointArray.setLength(numSamples)

    refPoints = om.MFloatPointArray()
    refPoints.setLength(numSamples)

    for i in range(posPPArray.length()):
        particlePosVector = om.MVector()
        particlePosVector = posPPArray[i]
        location = om.MFloatPoint(
            particlePosVector[0], particlePosVector[1], particlePosVector[2])

        pointArray.set(location, i)
        refPoints.set(location, i)

    # but we don't need these
    useShadowMap = False
    reuseMaps = False
    cameraMatrix = om.MFloatMatrix()
    uCoords = None
    vCoords = None
    normals = None
    tangentUs = None
    tangentVs = None
    filterSizes = None

    # and the return arguments are empty....
    resultColors = om.MFloatVectorArray()
    resultTransparencies = om.MFloatVectorArray()

    # this is the command wot samples

    omr.MRenderUtil.sampleShadingNetwork(shadingNodeName, numSamples, useShadowMap, reuseMaps, cameraMatrix, pointArray,
                                         uCoords, vCoords, normals, refPoints, tangentUs, tangentVs, filterSizes, resultColors, resultTransparencies)

    # use the sampled colours to set rgbPP
    resultPPColors = om.MVectorArray()
    resultPPColors.clear()

    for i in range(resultColors.length()):
        floatVector = om.MFloatVector(resultColors[i])
        vector = om.MVector(floatVector)
        resultPPColors.append(vector)

    particleDataFn.setPerParticleAttribute("rgbPP", resultPPColors)
Esempio n. 23
0
    def doIt(self, args):
        # Procesar argumentos
        try:
            self.parseArgs(args)
        except Exception as e:
            print('[' + commandName + '] Sintaxis de flag invalida')
            return

        # Deseleciona todo
        OpenMaya.MGlobal.clearSelectionList()

        # Crea el campo de turbulencia
        self.dagModifier.commandToExecute('turbulence -name "' +
                                          self.turbulenceFieldName + '"')
        self.dagModifier.commandToExecute('scale ' + str(0.5 * self.size_x) +
                                          ' ' + str(0.5 * self.size_y) + ' ' +
                                          str(0.5 * self.size_z) + ' ' +
                                          self.turbulenceFieldName)
        self.dagModifier.commandToExecute(
            'setAttr "' + self.turbulenceFieldName +
            '.volumeShape" 1')  # 1 para cubo, 2 para esfera
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.magnitude" 100')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.attenuation" 0.1')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.frequency" 4')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.interpolationType" 1')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.noiseLevel" 8')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.noiseRatio" 1')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.trapInside" 1')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.turbulenceFieldName +
                                          '.trapRadius" 1')

        # Crea el sistema de particulas
        self.dagModifier.commandToExecute('particle -name "' +
                                          self.particleSystemName + '"')
        self.dagModifier.commandToExecute('setAttr "' +
                                          self.particleSystemName +
                                          'Shape.conserve" 0.75')
        self.dagModifier.commandToExecute(
            'setAttr "' + self.particleSystemName +
            'Shape.particleRenderType" 6')  # 3 para puntos, 6 para streaks

        # Conecta el sistema de particulas con el campo de fuerza
        self.dagModifier.commandToExecute('connectDynamic -f ' +
                                          self.turbulenceFieldName + ' ' +
                                          self.particleSystemName + 'Shape')

        # Ejecuta los comandos encolados
        self.dagModifier.doIt()

        # Ayuda a obtener el Dag path del particleShape
        particleShapeDagPath = self.getDagPathToObject(
            self.particleSystemName + 'Shape')

        # Crea una funcion para establecer al particleShapeDagPath
        particleSystemFn = OpenMayaFX.MFnParticleSystem(particleShapeDagPath)

        # Genera aleatoriamente las posiciones de las particulas
        for i in range(0, self.numParticles):
            self.particlesPositions.append(
                random.uniform(0.5 * -self.size_x, 0.5 * self.size_x),
                random.uniform(0.5 * -self.size_y, 0.5 * self.size_y),
                random.uniform(0.5 * -self.size_z, 0.5 * self.size_z))

        # Emite particulas usando las posiciones generadas
        particleSystemFn.emit(self.particlesPositions)

        particleSystemFn.saveInitialState()
Esempio n. 24
0
def set_goals():

    sel = cmds.ls(sl=True, l=True)

    # make sure we have at least two items
    if len(sel) < 2:
        print 'Please select a nParticle system followed by the objects to set as goals'
        return

    elif len(sel) > 2:
        print 'For inital goal we want one particle system and one object to goal!'
        print 'Try again :)'
        return

    print sel

    # from the list make sure the first object is a nparticle system, get a handle on this
    # then remove from the list
    if not cmds.objectType(sel[0]) == 'nParticle':

        shape = cmds.listRelatives(sel[0])[0]

        if not cmds.objectType(shape) == 'nParticle':
            print 'Please select a nParticle system followed by objects to goal to!'
            return

        else:
            npSystem = sel.pop(0)
            npShape = shape

    else:
        npShape = sel.pop(0)
        npSystem = cmds.listRelatives(npShape, parent=True, f=True)

    obj = sel[0]

    selList = om.MSelectionList()
    selList.add(npShape)

    npDag = om.MDagPath()
    npMObj = om.MObject()

    selList.getDependNode(0, npMObj)
    selList.getDagPath(0, npDag)

    npNode = om.MFnDependencyNode(npMObj)
    npFnPart = omfx.MFnParticleSystem(npDag)

    if _get_goal(npDag):
        print 'Particle system already has goal. For now we are only supporting one goal!'
        return

    cmds.goal(npSystem, g=obj, w=1)

    set_initial_state(npNode, npFnPart)

    print '#------------------------------#'

    creation_dynExpression = ('.goalV = 0;\n'
                              '.goalU = 0;\n'
                              '.goalWeight0PP = .2;\n'
                              '.verticalSpeedPP = rand(0.01, 0.1);\n'
                              '.rotationRatePP = rand(0.03, 0.05);\n'
                              '.jitterIntervalPP = 0;\n'
                              '.jitterStepPP = 0;\n'
                              '.jitterRangePP = 0;\n'
                              '.lifespanPP = 5;')
    runtime_dynExpression = ('.goalV += .verticalSpeedPP;\n'
                             '.goalU += .rotationRatePP;\n\n'
                             'if (.jitterIntervalPP > .jitterStepPP)\n'
                             '{\n'
                             '\t.jitterStepPP ++;\n'
                             '}\n'
                             'else\n'
                             '{\n'
                             '\t.goalU += .jitterValuePP;\n'
                             '\t$hiRange = rand(0, .jitterRangePP);\n'
                             '\t$loRange = $hiRange * -1;\n'
                             '\t.jitterValuePP = rand($loRange, $hiRange);\n'
                             '\t.jitterStepPP = 0;\n'
                             '}\n\n'
                             'if (.goalU > 1)\n'
                             '{\n'
                             '\t.goalU -= 1;\n'
                             '}\n'
                             'else if(.goalU < 0)\n'
                             '{\n'
                             '\t.goalU += 1;\n'
                             '}')

    cmds.dynExpression(npShape, creation=True, string=creation_dynExpression)
    cmds.dynExpression(npShape, rbd=True, string=runtime_dynExpression)

    # now we want to make our goal object a passive rigid body so that
    # the particles don't go through it
    cmds.select(obj)

    print 'Selection is: %s' % cmds.ls(sl=True)

    # make our goal object a passive rigid body so the particles
    # can collide with it
    cmd = 'makeCollideNCloth'
    rigidShape = mel.eval(cmd)

    # rigid shape is not created if it already exists!
    if rigidShape:
        # parent the rigid body to keep things tidy
        nRigid = cmds.listRelatives(rigidShape[0], parent=True, f=True)
        #cmds.parent(nRigid, dynamics_grp)

    # select our particle system to tidy things up
    cmds.select(npSystem)