Esempio n. 1
0
    def compute(self, plug, dataBlock):
        if plug == computePoleVector.poleVector:
            '''
            dataHandleInString = dataBlock.inputValue(computePoleVector.inString)
            dataHandleInParam = dataBlock.inputValue(computePoleVector.inParam)

            inStringVal = dataHandleInString.asString()
            inParamVal = dataHandleInParam.asInt()

            outVal = inStringVal.replace('<param>', str(inParamVal).zfill(3))

            dataHandleOutString = dataBlock.outputValue(computePoleVector.outString)
            dataHandleOutString.setString(outVal)
            dataBlock.setClean(plug)
            '''

            dataHandle = OpenMaya.MDataHandle(dataBlock.inputValue(computePoleVector.inLegPosition))
            legPositionValue = dataHandle.asVector()
            dataHandle = OpenMaya.MDataHandle (dataBlock.inputValue (computePoleVector.inKneePosition))
            kneePositionValue = dataHandle.asVector()
            dataHandle = OpenMaya.MDataHandle (dataBlock.inputValue (computePoleVector.inFootPosition))
            footPositionValue = dataHandle.asVector()


            #computations
            #find start of vector
            pt0 = legPositionValue
            pt1 = kneePositionValue
            pt2 = footPositionValue

            res1 = OpenMaya.MVector (pt1.x - pt0.x, pt1.y - pt0.y, pt1.z - pt0.z)
            res1Raw = res1
            res2 = OpenMaya.MVector (pt2.x - pt0.x, pt2.y - pt0.y, pt2.z - pt0.z)
            res2Raw = res2

            thetaCos = normalize (res2) * normalize (res1)
            thetaSin = math.sqrt(1-math.sqrt(thetaCos))

            vectorProject = thetaCos * res1.length ()
            poleStartPos = (normalize (res2) * vectorProject) + pt0

            #find pole vector
            poleVector = OpenMaya.MVector(pt1.x - poleStartPos.x,
                                          pt1.y - poleStartPos.y,
                                          pt1.z - poleStartPos.z)

            #vectorCrossProduct = res1 ^ res2

            offset = 10
            polePos = normalize (poleVector) * offset + pt1
            result = polePos

            dataHandle = OpenMaya.MDataHandle(dataBlock.outputValue (computePoleVector.poleVector))
            dataHandle.set3Double(result.x, result.y, result.z)
            dataBlock.setClean(plug)

        else:
            return OpenMaya.kUnknownParameter
Esempio n. 2
0
 def compute(self, plug, dataBlock):
     
     if plug == oyCenterOfMass.aCOMPos:
         
         # get the mesh vertices for time from start to end
         
         # get the meshes
         arrayDataHandle = dataBlock.inputArrayValue( oyCenterOfMass.aObjectList )
         numOfConnections = arrayDataHandle.elementCount()
         
         inputDataHandle = OpenMaya.MDataHandle()
         inputGeometryDataHandle = OpenMaya.MDataHandle()
         
         mesh = OpenMaya.MObject()
         meshList = OpenMaya.MObjectArray()
         
         for i in range(numOfConnections):
             arrayDataHandle.jumpToElement(i)
             
             inputDataHandle = arrayDataHandle.inputValue()
             inputGeometryDataHandle = inputDataHandle.child( oyCenterOfMass.aObjectList )
             
             mesh = inputGeometryDataHandle.asMesh()
             
             if mesh.hasFn( OpenMaya.MFn.kMesh ):
                 meshList.append( mesh )
         
         
         numOfMesh = meshList.length()
         
         # return if no mesh
         if numOfMesh == 0:
             return OpenMaya.MStatus.kSuccess
         
         # read the mesh vertices in to one big array
         verticesOfOneMesh = OpenMaya.MPointArray()
         allVertices = OpenMaya.MPointArray()
         
         meshFn = OpenMaya.MFnMesh()
         
         for i in range(numOfMesh):
             meshFn.getPoints ( verticesOfOneMesh, OpenMaya.MSpace.kWorld )
             
             for j in range(verticesOfOneMesh.length()):
                 allVertices.append( verticesOfOneMesh[j] )
             
         
         
         
         
         
         
         
         # set the time
         
         return OpenMaya.MStatus.kSuccess
     else:
         return OpenMaya.kUnknownParameter
Esempio n. 3
0
    def write_ouputState(self, outState_handle, numberofOutput_Val,
                         activeIndex_Val, ThsNde):
        cBuilder = outState_handle.builder()
        bldChck = cBuilder.elementCount()
        growVal = numberofOutput_Val - bldChck

        if growVal > 0:
            #print 'we need to grow this array of ', bldChck , ' elements by  ', growVal
            cBuilder.growArray(growVal)

        stateList = []
        stateList = [0 for k in range(numberofOutput_Val)]
        stateList[activeIndex_Val] = 1

        currentDH = OpenMaya.MDataHandle()
        for n in range(0, numberofOutput_Val):
            currentDH = cBuilder.addElement(n)
            currentDH.setBool(stateList[n])

        bldChck = cBuilder.elementCount()
        # prune unwanted index --> equivalent to removeMultiInstance...
        if bldChck > numberofOutput_Val:
            depFn = OpenMaya.MFnDependencyNode(ThsNde)
            curvePointsPlug = depFn.findPlug('outState')
            outName = curvePointsPlug.info()
            for k in range(bldChck - 1, numberofOutput_Val - 1, -1):
                try:
                    cBuilder.removeElement(k)
                except:
                    # --> a bit dirty but it help when node is not connected yet we have access to the correct number of output attribute
                    # when node is connected this fallback is not needed anymore
                    cmds.removeMultiInstance('%s[%s]' % (outName, k), b=True)
        outState_handle.set(cBuilder)
        outState_handle.setAllClean()
Esempio n. 4
0
    def compute(self, plug, dataBlock):
        if plug == arrayTest.output1WgtAttr:
            #calculations here
            #get inputs
            dataHandleInput = dataBlock.inputValue(arrayTest.input1VecAttr)
            inVal = dataHandleInput.asFloat()

            #get ouput array
            arrayDataHandle = OpenMaya.MArrayDataHandle(
                dataBlock.outputArrayValue(arrayTest.output1WgtAttr))
            myBuilder = OpenMaya.MArrayDataBuilder(arrayTest.output1WgtAttr, 0)

            for i in range(arrayDataHandle.elementCount()):
                #arrayDataHandle.next()
                output = inVal / (i + 1)
                #output = inVal + outValue

                myElementHandle = OpenMaya.MDataHandle(myBuilder.addElement(i))
                myElementHandle.setFloat(output)

            arrayDataHandle.set(myBuilder)
            arrayDataHandle.setAllClean()

            dataBlock.setClean(plug)

        else:
            return OpenMaya.kUnknownParameter
Esempio n. 5
0
    def compute(self, plug, dataBlock):

	dataHandle = om.MDataHandle(dataBlock.inputValue(mat_test.sourceAttr))
	sourcePos = dataHandle.asFloat3()
	dataHandle = om.MDataHandle(dataBlock.inputValue(mat_test.targetAttr))
	targetPos = dataHandle.asFloat3()
	#dataHandle = om.MDataHandle(dataBlock.inputValue(mat_test.inMeshAttr))
	#inMesh = dataHandle.asMesh()	


	outPos =[ ( targetPos[0] - sourcePos[0] ) / 2 , ( targetPos[1] - sourcePos[1] ) / 2 ,  ( targetPos[1] - sourcePos[1] ) / 2 ] 

	
	
	dataHandle = om.MDataHandle(dataBlock.outputValue(mat_test.outputAttr))
	dataHandle.asFloat3(outPos)
	dataBlock.setClean(plug)
Esempio n. 6
0
 def compute(self, plug, dataBlock):
     """Compute the arithmetic mean of input 1 and input 2."""
     if (plug == AR_AverageDoublesNode.outputAttr):
         # get the incoming data
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(AR_AverageDoublesNode.input1Attr))
         input1 = dataHandle.asDouble()
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(AR_AverageDoublesNode.input2Attr))
         input2 = dataHandle.asDouble()
         # compute output
         output = (input1 + input2) * 0.5
         # set the outgoing plug
         dataHandle = om.MDataHandle(
             dataBlock.outputValue(AR_AverageDoublesNode.outputAttr))
         dataHandle.setDouble(output)
         dataBlock.setClean(plug)
     else:
         return om.kUnknownParameter
Esempio n. 7
0
    def compute(self, plug, data):
        if plug.isNull():
            return OpenMayaMPx.MPxNode.compute(plug, data)

        type_handle = OpenMaya.MDataHandle(data.inputValue(Connect.type))
        type_value = type_handle.asChar()

        count_handle = OpenMaya.MDataHandle(data.inputValue(Connect.count))
        count_value = count_handle.asLong()

        row_handle = OpenMaya.MDataHandle(data.inputValue(Connect.row))
        row_value = row_handle.asLong()

        column_handle = OpenMaya.MDataHandle(data.inputValue(Connect.column))
        column_value = column_handle.asLong()

        offset_handle = OpenMaya.MDataHandle(data.inputValue(Connect.offset))
        offset_value = offset_handle.asLong()

        random_handle = OpenMaya.MDataHandle(data.inputValue(Connect.random))
        random_value = random_handle.asLong()

        print 'random_value', random_value

        self.crowd_setup(type=type_value,
                         count=count_value,
                         row=row_value,
                         column=column_value,
                         offset=offset_value,
                         random=random_value)
Esempio n. 8
0
 def compute(self, plug, dataBlock):
     """Compute the mean of input 1 and input 2."""
     if (plug == AR_WeightedAverageVectorsNode.outputAttr or
         (plug.isChild()
          and plug.parent() == AR_WeightedAverageVectorsNode.outputAttr)):
         # get the incoming data
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(
                 AR_WeightedAverageVectorsNode.input1VecAttr))
         input1Vector = dataHandle.asVector()
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(
                 AR_WeightedAverageVectorsNode.input1WgtAttr))
         input1Weight = dataHandle.asDouble()
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(
                 AR_WeightedAverageVectorsNode.input2VecAttr))
         input2Vector = dataHandle.asVector()
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(
                 AR_WeightedAverageVectorsNode.input2WgtAttr))
         input2Weight = dataHandle.asDouble()
         # compute output
         totalWeight = input1Weight + input2Weight
         if not abs(
                 totalWeight) <= abs(totalWeight) * sys.float_info.epsilon:
             output = (input1Vector * input1Weight +
                       input2Vector * input2Weight) / totalWeight
         else:
             output = (input1Vector + input2Vector) * 0.5
         # set the outgoing plug
         dataHandle = om.MDataHandle(
             dataBlock.outputValue(
                 AR_WeightedAverageVectorsNode.outputAttr))
         dataHandle.set3Double(output.x, output.y, output.z)
         dataBlock.setClean(plug)
     else:
         return om.kUnknownParameter
Esempio n. 9
0
 def compute(self, plug, dataBlock):
     """Compute the arithmetic mean of all the items in input array."""
     if (plug == AR_AverageDoubleArrayNode.outputAttr):
         # get the incoming data
         dataHandle = om.MDataHandle(
             dataBlock.inputValue(AR_AverageDoubleArrayNode.inputAttr))
         doubleArrayFn = om.MFnDoubleArrayData(dataHandle.data())
         doubleArray = om.MDoubleArray(doubleArrayFn.array())
         # compute output
         output = 0.0
         for i in range(doubleArray.length()):
             output += doubleArray[i]
         try:
             output /= doubleArray.length()
         except:
             pass
         # set the outgoing plug
         dataHandle = om.MDataHandle(
             dataBlock.outputValue(AR_AverageDoubleArrayNode.outputAttr))
         dataHandle.setDouble(output)
         dataBlock.setClean(plug)
     else:
         return om.kUnknownParameter
Esempio n. 10
0
    def compute(self, plug, dataBlock):

        self.sourcePos = dataBlock.inputValue(self.sourceAttr).asFloat3()
        self.targetPos = dataBlock.inputValue(self.targetAttr).asFloat3()

        #dataHandle = om.MDataHandle(dataBlock.inputValue(mat_test.sourceAttr))
        #self.sourcePos = dataHandle.asFloat3()
        #dataHandle = om.MDataHandle(dataBlock.inputValue(mat_test.targetAttr))
        #self.targetPos = dataHandle.asFloat3()

        startPnt = om.MPoint(self.sourcePos[0], self.sourcePos[1],
                             self.sourcePos[2])
        targetPnt = om.MPoint(self.targetPos[0], self.targetPos[1],
                              self.targetPos[2])

        outPos = [0, 0, 0]
        outPos = [(startPnt.x - targetPnt.x) / 2,
                  (startPnt.y - targetPnt.x) / 2,
                  (startPnt.z - targetPnt.x) / 2]

        dataHandle = om.MDataHandle(dataBlock.outputValue(mat_test.outputAttr))
        dataHandle.asFloat3(outPos)
        dataBlock.setClean(plug)
Esempio n. 11
0
 def compute(self, plug, dataBlock):
     """Compute the arithmetic mean of all the items in input array."""
     if (plug == AR_AverageArrayDoublesNode.outputAttr):
         # get the incoming data
         arrayDataHandle = om.MArrayDataHandle(
             dataBlock.inputValue(AR_AverageArrayDoublesNode.inputAttr))
         # compute output
         output = 0.0
         try:
             output = (arrayDataHandle.inputValue()).asDouble()
         except:
             pass
         for i in range(arrayDataHandle.elementCount() - 1):
             arrayDataHandle.next()
             output += (arrayDataHandle.inputValue()).asDouble()
         try:
             output /= arrayDataHandle.elementCount()
         except:
             pass
         """
         # an alternative approach using an MPlug; less efficient because MPlug is slower
         arrayPlug = om.MPlug(self.thisMObject(), AR_AverageArrayDoublesNode.inputAttr)
         output = 0.0
         for i in range(arrayPlug.numElements()):
             elementPlug = om.MPlug(arrayPlug[i]).asDouble() # index operator works with physical indices
             output += elementPlug.asDouble()
         try: output /= arrayPlug.numElements()
         except: pass
         """
         # set the outgoing plug
         dataHandle = om.MDataHandle(
             dataBlock.outputValue(AR_AverageArrayDoublesNode.outputAttr))
         dataHandle.setDouble(output)
         dataBlock.setClean(plug)
     else:
         return om.kUnknownParameter
Esempio n. 12
0
    def compute(self, plug, dataBlock):
        """Compute an exposed object's transformations with respect to a reference object."""
        if (plug == AM_ExposeTransformNode.position or (
                plug.isChild()
                and plug.parent() == AM_ExposeTransformNode.position
        ) or  # WARNING: without this, position always initializes to 0, 0, 0 when connection is made
                plug == AM_ExposeTransformNode.distance or
                plug == AM_ExposeTransformNode.rotation or
            (
                plug.isChild() and plug.parent()
                == AM_ExposeTransformNode.rotation
            ) or  # WARNING: without this, setting rotateOrder attribute manually won't push a compute()
                plug == AM_ExposeTransformNode.dot
                or plug == AM_ExposeTransformNode.angle
                or plug == AM_ExposeTransformNode.dotToTarget
                or plug == AM_ExposeTransformNode.angleToTarget):
            # get the incoming data
            # rotation order for Euler output
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_ExposeTransformNode.rotateOrder))
            eRotateOrder = dataHandle.asShort()
            # should the incoming axes be normalized for computing dot products?
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_ExposeTransformNode.normalize))
            bNormalizeInputAxes = dataHandle.asBool()
            # axis on the object for computing dot product and angle
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_ExposeTransformNode.objectAxis))
            vObjectAxis = OM.MVector(dataHandle.asVector())
            if bNormalizeInputAxes:
                vObjectAxis.normalize()
            # axis on the reference object for computing dot product and angle
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_ExposeTransformNode.referenceAxis))
            vReferenceAxis = OM.MVector(dataHandle.asVector())
            if bNormalizeInputAxes:
                vReferenceAxis.normalize()
            # worldMatrix of the object
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_ExposeTransformNode.objectMatrix))
            mObjectMatrix = OM.MMatrix(dataHandle.asMatrix())
            # worldMatrix of the reference
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_ExposeTransformNode.referenceMatrix))
            mReferenceMatrix = OM.MMatrix(dataHandle.asMatrix())

            # compute the output values
            mOutputMatrix = OM.MTransformationMatrix(
                mObjectMatrix * mReferenceMatrix.inverse())
            vOutPosition = OM.MVector(
                mOutputMatrix.getTranslation(OM.MSpace.kTransform))
            vOutRotation = OM.MEulerRotation(
                mOutputMatrix.eulerRotation().reorder(eRotateOrder))
            vObjectAxis *= mObjectMatrix  # rotate objectAxis into world space
            vReferenceAxis *= mReferenceMatrix  # rotate referenceAxis into world space
            vToTarget = OM.MVector(
                mReferenceMatrix(3, 0) - mObjectMatrix(3, 0),
                mReferenceMatrix(3, 1) - mObjectMatrix(3, 1),
                mReferenceMatrix(3, 2) - mObjectMatrix(3, 2)
            )  # the vector from the object's axis to the reference object's position
            if bNormalizeInputAxes:
                vObjectAxis.normalize()
                vReferenceAxis.normalize()
                vToTarget.normalize()

            # set the outgoing plugs
            outputHandle = dataBlock.outputValue(
                AM_ExposeTransformNode.position)
            outputHandle.set3Double(vOutPosition.x, vOutPosition.y,
                                    vOutPosition.z)
            outputHandle = dataBlock.outputValue(
                AM_ExposeTransformNode.distance)
            outputHandle.setDouble(vOutPosition.length())
            outputHandle = dataBlock.outputValue(
                AM_ExposeTransformNode.rotation)
            outputHandle.set3Double(math.degrees(vOutRotation.x),
                                    math.degrees(vOutRotation.y),
                                    math.degrees(vOutRotation.z))
            outputHandle = dataBlock.outputValue(AM_ExposeTransformNode.dot)
            outputHandle.setDouble(vObjectAxis * vReferenceAxis)
            outputHandle = dataBlock.outputValue(AM_ExposeTransformNode.angle)
            outputHandle.setDouble(
                math.degrees(vObjectAxis.angle(vReferenceAxis)))
            outputHandle = dataBlock.outputValue(
                AM_ExposeTransformNode.dotToTarget)
            outputHandle.setDouble(vObjectAxis * vToTarget)
            outputHandle = dataBlock.outputValue(
                AM_ExposeTransformNode.angleToTarget)
            outputHandle.setDouble(math.degrees(vObjectAxis.angle(vToTarget)))
            dataBlock.setClean(plug)

        else:
            return OM.kUnknownParameter
Esempio n. 13
0
    def compute(self, plug, dataBlock):
        dataBlock.setClean(plug)

        if plug != angleReader.outAngle_nAttr and plug != angleReader.outWeight_nAttr:
            return om.kUnknownParameter

        baseMatrix_DH = om.MDataHandle()
        baseMatrix_DH = dataBlock.inputValue(angleReader.baseMatrix_mAttr)
        base_M = baseMatrix_DH.asMatrix()

        driverMatrix_DH = om.MDataHandle()
        driverMatrix_DH = dataBlock.inputValue(angleReader.driverMatrix_mAttr)
        driver_M = driverMatrix_DH.asMatrix()

        rotateAxisX_DH = om.MDataHandle()
        rotateAxisX_DH = dataBlock.inputValue(angleReader.rotateAxisX_nAttr)
        rotateAxisY_DH = om.MDataHandle()
        rotateAxisY_DH = dataBlock.inputValue(angleReader.rotateAxisY_nAttr)
        rotateAxisZ_DH = om.MDataHandle()
        rotateAxisZ_DH = dataBlock.inputValue(angleReader.rotateAxisZ_nAttr)
        rotateAxis_V = om.MVector(rotateAxisX_DH.asFloat(),
                                  rotateAxisY_DH.asFloat(),
                                  rotateAxisZ_DH.asFloat())

        frontAxisX_DH = om.MDataHandle()
        frontAxisX_DH = dataBlock.inputValue(angleReader.frontAxisX_nAttr)
        frontAxisY_DH = om.MDataHandle()
        frontAxisY_DH = dataBlock.inputValue(angleReader.frontAxisY_nAttr)
        frontAxisZ_DH = om.MDataHandle()
        frontAxisZ_DH = dataBlock.inputValue(angleReader.frontAxisZ_nAttr)
        frontAxis_V = om.MVector(frontAxisX_DH.asFloat(),
                                 frontAxisY_DH.asFloat(),
                                 frontAxisZ_DH.asFloat())

        preStart_DH = om.MDataHandle()
        preStart_DH = dataBlock.inputValue(angleReader.preStart_nAttr)
        preStart = preStart_DH.asFloat()
        start_DH = om.MDataHandle()
        start_DH = dataBlock.inputValue(angleReader.start_nAttr)
        start = start_DH.asFloat()
        end_DH = om.MDataHandle()
        end_DH = dataBlock.inputValue(angleReader.end_nAttr)
        end = end_DH.asFloat()
        postEnd_DH = om.MDataHandle()
        postEnd_DH = dataBlock.inputValue(angleReader.postEnd_nAttr)
        postEnd = postEnd_DH.asFloat()

        negate_DH = om.MDataHandle()
        negate_DH = dataBlock.inputValue(angleReader.negate_nAttr)
        negate = negate_DH.asInt()

        # compute the angle

        # first get the local axis of the matrices
        driverFront_V = frontAxis_V * driver_M
        driverFront_V.normalize()
        baseRotate_V = rotateAxis_V * base_M
        baseRotate_V.normalize()
        baseFront_V = frontAxis_V * base_M
        baseFront_V.normalize()

        # then calculate the third axis for the baseMatrix
        upAxis_V = baseFront_V ^ baseRotate_V

        # then make a projection from driver's frontAxis to the base rotate vector
        projected_V = driverFront_V ^ baseRotate_V
        dotProjBaseFront = projected_V * baseFront_V
        dotProjUp = projected_V * upAxis_V
        angle = math.atan2(dotProjBaseFront, dotProjUp)
        mAngle = om.MAngle(angle, om.MAngle.kRadians)

        outAngle_DH = om.MDataHandle()
        outAngle_DH = dataBlock.outputValue(angleReader.outAngle_nAttr)
        outAngle_DH.setMAngle(mAngle)
        outAngle_DH.setClean()

        # print pluginName + ' : ' + str(angle)
        outWeight_DH = om.MDataHandle()
        outWeight_DH = dataBlock.outputValue(angleReader.outWeight_nAttr)
        weight = computeWeight(math.degrees(angle), preStart, start, end,
                               postEnd, negate)
        outWeight_DH.setFloat(weight)
        outWeight_DH.setClean()
Esempio n. 14
0
    def compute(self, plug, dataBlock):
        """Use a NURBS curve and other input parameters to generate mesh data to be piped into a shape node."""
        if (plug == AM_RibbonsNode.output):
            # get the incoming data
            # the input nurbs curve
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputCurve))
            curve = OM.MObject(dataHandle.asNurbsCurve())
            # early out if there is no curve data
            if curve.isNull():
                return OM.kUnknownParameter
            # width of the ribbon in centimeters
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputWidth))
            width = dataHandle.asDouble()
            # number of divisions along the ribbon
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputDivisions))
            divisions = dataHandle.asInt()
            # the ribbon must have at least one division
            if divisions < 1:
                divisions = 1
                dataHandle.setInt(1)
                dataHandle.setClean()
            # amount of taper at the far end of the ribbon
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputTaper))
            taper = dataHandle.asDouble()
            # amount of twisting of the ribbon at its base
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputTwistBase))
            twistBase = dataHandle.asDouble()
            # amount of twisting of the ribbon at its far end
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputTwistLength))
            twistLength = dataHandle.asDouble()
            # up-vector for the ribbon at its base
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputUpVector))
            upVector = OM.MVector(dataHandle.asVector())
            upVector.normalize()
            if upVector.length() == 0:
                upVector = OM.MVector(0.0, 1.0, 0.0)
            # scale factor applied to the default uv layout
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputUVScale))
            uvScale = dataHandle.asDouble()
            # pin location for the default uv layout
            dataHandle = OM.MDataHandle(
                dataBlock.inputValue(AM_RibbonsNode.inputUVPin))
            uvPin = dataHandle.asShort()

            # create data for the output mesh
            dataCreator = OM.MFnMeshData()
            outputData = dataCreator.create()
            numVertices = 2 + divisions * 2
            numPolygons = divisions
            newMeshVertices = OM.MPointArray()
            newMeshPolyCount = OM.MIntArray()
            newMeshPolyConnects = OM.MIntArray()
            newMeshUVCounts = OM.MIntArray()
            newMeshUVIDs = OM.MIntArray()
            meshFn = OM.MFnMesh()

            # find the points and tangents at each division along the curve
            pointsOnCurve = OM.MPointArray()
            tangentsOnCurve = OM.MVectorArray()
            curveFn = OM.MFnNurbsCurve(curve)
            maxParam = curveFn.findParamFromLength(curveFn.length())
            paramStep = maxParam / divisions
            startPoint = OM.MPoint()
            currentPoint = OM.MPoint()
            curveFn.getPointAtParam(0.0, startPoint)
            for i in range(divisions + 1):
                curveFn.getPointAtParam(i * paramStep, currentPoint)
                pointsOnCurve.append(OM.MPoint(currentPoint - startPoint))
                tangentsOnCurve.append(curveFn.tangent(i * paramStep).normal())

            # determine the amount of twisting to apply at the base and per division
            twistBaseRotation = OM.MQuaternion(math.radians(twistBase),
                                               tangentsOnCurve[0])
            twistStepAngle = math.radians(twistLength / divisions)
            # if the first tangent is roughly the same as the up-vector, then simply override the up-vector to be the z-axis
            upVector = upVector.rotateBy(twistBaseRotation)
            if upVector * tangentsOnCurve[0] > 0.999999999999999:
                upVector = OM.MVector(0.0, 0.0, 1.0)
            # orthonormalize the up-vector and first tangent
            rightVector = OM.MVector(upVector ^ tangentsOnCurve[0]).normal()
            upVector = tangentsOnCurve[0] ^ rightVector

            # create the points along the curve
            for i in range(pointsOnCurve.length()):
                if i is not 0:
                    upVector = upVector.rotateBy(
                        OM.MQuaternion(tangentsOnCurve[i - 1],
                                       tangentsOnCurve[i]))
                    upVector = upVector.rotateBy(
                        OM.MQuaternion(twistStepAngle, tangentsOnCurve[i]))
                    newMeshPolyCount.append(4)
                    newMeshUVCounts.append(4)
                rightVector = upVector ^ tangentsOnCurve[i]
                newMeshVertices.append(
                    OM.MPoint(pointsOnCurve[i] + rightVector * 0.5 * width *
                              (1.0 + (taper - 1.0) / pointsOnCurve.length() *
                               (i + 1))))
                newMeshVertices.append(
                    OM.MPoint(pointsOnCurve[i] + rightVector * -0.5 * width *
                              (1.0 + (taper - 1.0) / pointsOnCurve.length() *
                               (i + 1))))

            # connect the points in the new mesh and assign uv values to the faces
            for i in range(newMeshPolyCount.length()):
                newMeshPolyConnects.append(i * 2 + 0)
                newMeshPolyConnects.append(i * 2 + 1)
                newMeshPolyConnects.append(i * 2 + 3)
                newMeshPolyConnects.append(i * 2 + 2)
                newMeshUVIDs.append(i * 2 + 0)
                newMeshUVIDs.append(i * 2 + 1)
                newMeshUVIDs.append(i * 2 + 3)
                newMeshUVIDs.append(i * 2 + 2)

            # establish other parameters for the new mesh data
            numVertices = newMeshVertices.length()
            numPolygons = divisions

            # create the new mesh from all of the data
            mesh = meshFn.create(numVertices, numPolygons, newMeshVertices,
                                 newMeshPolyCount, newMeshPolyConnects,
                                 outputData)

            # set and assign uv values
            for i in range(pointsOnCurve.length()):
                meshFn.setUV(
                    i * 2 + 0, 1.0,
                    1.0 - uvScale * (float(i) / (pointsOnCurve.length() - 1)) -
                    uvPin * (1.0 - uvScale))
                meshFn.setUV(
                    i * 2 + 1, 0.0,
                    1.0 - uvScale * (float(i) / (pointsOnCurve.length() - 1)) -
                    uvPin * (1.0 - uvScale))
            meshFn.assignUVs(newMeshUVCounts, newMeshUVIDs)

            # set the outgoing plug
            outputHandle = dataBlock.outputValue(AM_RibbonsNode.output)
            outputHandle.setMObject(outputData)
            dataBlock.setClean(plug)

        else:
            return OM.kUnknownParameter