MPlug ColorSplineParameterHandler<S>::doCreate( IECore::ConstParameterPtr parameter, const MString &plugName, MObject &node ) const
{
	assert( parameter );

	typename IECore::TypedParameter< S >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter< S > >( parameter );
	if( !p )
	{
		return MPlug();
	}

	MRampAttribute fnRAttr;
	MObject attribute = fnRAttr.createColorRamp( plugName, plugName );

	MPlug result = finishCreating( parameter, attribute, node );
	doUpdate( parameter, result );
	
	return result;
}
Exemplo n.º 2
0
MStatus volumeLight::doIt( const MArgList& args )
{
	MStatus stat;

	double arc = 180.0f;
	double coneEndRadius = 0.0f;
	MFnVolumeLight::MLightDirection volumeLightDirection = MFnVolumeLight::kOutward;
	MFnVolumeLight::MLightShape lightShape = MFnVolumeLight::kConeVolume;
	bool emitAmbient = true;

	unsigned	i;

	// Parse the arguments.
	for ( i = 0; i < args.length(); i++ )
	{
		if ( MString( "-a" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			double tmp = args.asDouble( ++i, &stat );
			if ( MS::kSuccess == stat )
				arc = tmp;
		}
		else if ( MString( "-c" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			double tmp = args.asDouble( ++i, &stat );
			if ( MS::kSuccess == stat )
				coneEndRadius = tmp;
		}
		else if ( MString( "-e" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			bool tmp = args.asBool( ++i, &stat );
			if ( MS::kSuccess == stat )
				emitAmbient = tmp;
		}

	}

	MFnVolumeLight light;

	light.create( true, &stat);

	cout<<"What's up?";

	if ( MS::kSuccess != stat )
	{
		cout<<"Error creating light."<<endl;
		return stat;
	}
	
	stat = light.setArc ((float)arc);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error setting \"arc\" attribute."<<endl;
		return stat;
	}

	stat = light.setVolumeLightDirection (volumeLightDirection);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error setting \"volumeLightDirection\" attribute."<<endl;
		return stat;
	}

	stat = light.setConeEndRadius ((float)coneEndRadius);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error setting \"coneEndRadius\" attribute."<<endl;
		return stat;
	}

	stat = light.setEmitAmbient (emitAmbient);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error setting \"emitAmbient\" attribute."<<endl;
		return stat;
	}

	stat = light.setLightShape (lightShape);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error setting \"lightShape\" attribute."<<endl;
		return stat;
	}

	double arcGet = light.arc (&stat);
	if ( MS::kSuccess != stat || arcGet != arc)
	{
		cout<<"Error getting \"arc\" attribute."<<endl;
		return stat;
	}

	MFnVolumeLight::MLightDirection volumeLightDirectionGet = light.volumeLightDirection (&stat);
	if ( MS::kSuccess != stat || volumeLightDirectionGet != volumeLightDirection)
	{
		cout<<"Error getting \"volumeLightDirection\" attribute."<<endl;
		return stat;
	}

	double coneEndRadiusGet = light.coneEndRadius (&stat);
	if ( MS::kSuccess != stat || coneEndRadiusGet != coneEndRadius)
	{
		cout<<"Error getting \"coneEndRadius\" attribute."<<endl;
		return stat;
	}

	bool emitAmbientGet = light.emitAmbient (&stat);
	if ( MS::kSuccess != stat || emitAmbientGet != emitAmbient)
	{
		cout<<"Error getting \"emitAmbient\" attribute."<<endl;
		return stat;
	}

	MFnVolumeLight::MLightShape lightShapeGet = light.lightShape (&stat);
	if ( MS::kSuccess != stat || lightShapeGet != lightShape)
	{
		cout<<"Error getting \"lightShape\" attribute."<<endl;
		return stat;
	}

	// Get reference to the penumbra ramp.
	MRampAttribute ramp = light.penumbraRamp (&stat);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error getting \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	MFloatArray a, b;
	MIntArray c,d;

	// Get the entries in the ramp
	ramp.getEntries (d, a, b, c, &stat);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error getting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	// There should be 2 entries by default.
	if (d.length() != 2)
	{
		cout<<"Invalid number of entries in \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	MFloatArray a1, b1;
	MIntArray c1;

	// Prepare an array of entries to add.
	// In this case we are just adding 1 more entry
	// at position 0.5 with a curve value of 0.25 and a linear interpolation.
	a1.append (0.5f);
	b1.append (0.25f);
	c1.append (MRampAttribute::kLinear);

	// Add it to the curve ramp
	ramp.addEntries (a1, b1, c1, &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error adding entries to \"penumbraRamp\" attribute."<<endl;
		return stat;
	}


	// Get the entries to make sure that the above add actually worked.
	MFloatArray a2, b2;
	MIntArray c2,d2;
	ramp.getEntries (d2, a2, b2, c2, &stat);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error getting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}
	if ( a.length() + a1.length() != a2.length())
	{
		cout<<"Invalid number of entries in \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	// Now try to interpolate the value at a point
	float newVal = -1;
	ramp.getValueAtPosition(.3f, newVal, &stat);

	if ( MS::kSuccess != stat )
	{
		cout<<"Error interpolating value from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}
	if ( !EQUAL(newVal, .15f))
	{
		cout<<"Invalid interpolation in  \"penumbraRamp\" expected .15 got "<<newVal
			<<" ."<<endl;
	}

	// Try to delete an entry in an incorrect manner. 
	// This delete will work because there is an entry at 0, 
	// However we should never do it this way, because the entries
	// array can become sparse, so trying to delete an entry without 
	// checking whether an entry exists at that index can cause a failure.
	MIntArray entriesToDelete;
	entriesToDelete.append (0);
	ramp.deleteEntries (entriesToDelete, &stat);
	if ( MS::kSuccess != stat )
	{
		cout<<"Error deleting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	// Check to see whether the above delete worked.
	// As mentioned earlier it did work, but we shouldn't do it this way.
	// To illustrate why we shouldn't do it this way, we'll try to delete
	// entry at index 0 ( this no longer exists)
	ramp.getEntries (d2, a2, b2, c2, &stat);

	if ( a2.length() != 2)
	{
		cout<<"Invalid number of entries in \"penumbraRamp\" attribute."<<endl;
		return stat;
	}
	// Trying to delete entry at 0.
	entriesToDelete.clear();
	entriesToDelete.append (0);
	ramp.deleteEntries (entriesToDelete, &stat);

	// It will fail because no entry exists.
	if ( MS::kSuccess == stat)
	{
		cout<<"Error deleting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}
	if ( a2.length() != 2)
	{
		cout<<"Invalid number of entries in \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	// The proper way to delete is to retrieve the index by calling "getEntries"
	ramp.getEntries (d2, a2, b2, c2, &stat);
	entriesToDelete.clear();
	entriesToDelete.append (d2[0]);

	// Delete the first logical entry in the entry array.
	ramp.deleteEntries (entriesToDelete, &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error deleting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	// There should be only 1 entry left.
	ramp.getEntries (d2, a2, b2, c2, &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error getting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}
	entriesToDelete.clear();
	entriesToDelete.append (d2[0]);

	// Can't delete the last entry, should return failure.
	ramp.deleteEntries (entriesToDelete, &stat);
	if ( MS::kSuccess == stat)
	{
		cout<<"Error deleting entries from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}

	ramp.setPositionAtIndex (0.0f, d2[0], &stat);
	if ( MS::kSuccess != stat)
	{
		printf("Error setting position at index: %d, of \"penumbraRamp\" attribute.\n", d2[0]);
		return stat;
	}

	ramp.setValueAtIndex (1.0f, d2[0], &stat);
	if ( MS::kSuccess != stat)
	{
		printf("Error setting value at index: %d, of \"penumbraRamp\" attribute.\n", d2[0]);
		return stat;
	}

	ramp.setInterpolationAtIndex (MRampAttribute::kNone, d2[0], &stat);
	if ( MS::kSuccess != stat)
	{
		printf("Error setting interpolation at index: %d, of \"penumbraRamp\" attribute.\n", d2[0]);
		return stat;
	}

  	MRampAttribute ramp2 = light.colorRamp (&stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error getting  \"colorRamp\" attribute."<<endl;
		return stat;
	}	
	MFloatArray a3;
	MColorArray b3;
	MIntArray c3,d3;

  	// Get the entries in the ramp
	ramp2.getEntries (d3, a3, b3, c3, &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error getting entries from \"colorRamp\" attribute."<<endl;
		return stat;
	}
	// There should be 2 entries by default.
	if ( d3.length() != 2)
	{
		cout<<"Invalid number of entries in \"colorRamp\" attribute."<<endl;
		return stat;
	}

	MFloatArray a4;
	MColorArray b4;
	MIntArray c4;

	// Prepare an array of entries to add.
	// In this case we are just adding 1 more entry
	// at position 0.5 withe curve value of 0.5 and a linear interpolation.
	a4.append (0.5f);
	b4.append (MColor (0.0f, 0.0f, 0.75f));
	c4.append (MRampAttribute::kLinear);

	// Add it to the curve ramp
	ramp2.addEntries (a4, b4, c4, &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error adding entries to \"colorRamp\" attribute."<<endl;
		return stat;
	}
	// Get the entries to make sure that the above add actually worked.
	MFloatArray a5;
	MColorArray b5;
	MIntArray c5,d5;
	ramp2.getEntries (d5, a5, b5, c5, &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error getting entries from \"colorRamp\" attribute."<<endl;
		return stat;
	}
	if (  a3.length() + a4.length() != a5.length())
	{
		cout<<"Invalid number of entries in \"colorRamp\" attribute."<<endl;
		return stat;
	}

	// Now try to interpolate the color at a point
	MColor newCol(0.0, 0.0, 0.0);
	ramp2.getColorAtPosition(.3f, newCol, &stat);

	if ( MS::kSuccess != stat )
	{
		cout<<"Error interpolating color from \"penumbraRamp\" attribute."<<endl;
		return stat;
	}
	if ( !EQUAL(newCol[2], .45))
	{
		cout<<"Invalid color interpolation in  \"colorRamp\" expected .45 got "<<newCol[2]<<endl;
	}

	MColor clr (0.5, 0.5, 0.0);
	ramp2.setColorAtIndex (clr, d5[0], &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error setting color at index: "<<d5[0]
			<<", of \"colorRamp\" attribute."<<endl;
		return stat;
	}

	ramp2.setInterpolationAtIndex (MRampAttribute::kSpline, d5[1], &stat);
	if ( MS::kSuccess != stat)
	{
		cout<<"Error setting interpolation at index: "<<d5[1]
			<<", of \"colorRamp\" attribute."<<endl;
		return stat;
	}

	return stat;
}
// create attributes
MStatus probeDeformerARAPNode::initialize(){
    MFnTypedAttribute tAttr;
    MFnNumericAttribute nAttr;
    MFnEnumAttribute eAttr;
    MFnMatrixAttribute mAttr;
   	MRampAttribute rAttr;

    // this attr will be dirtied when ARAP recomputation is needed
    aARAP = nAttr.create( "arap", "arap", MFnNumericData::kBoolean, true );
    nAttr.setStorable(false);
    nAttr.setKeyable(false);
    nAttr.setHidden(true);
    addAttribute( aARAP );

    // this attr will be dirtied when weight recomputation is needed
    aComputeWeight = nAttr.create( "computeWeight", "computeWeight", MFnNumericData::kBoolean, true );
    nAttr.setStorable(false);
    nAttr.setKeyable(false);
    nAttr.setHidden(true);
    addAttribute( aComputeWeight );

    aMatrix = mAttr.create("probeMatrix", "pm");
    mAttr.setStorable(false);
    mAttr.setHidden(true);
    mAttr.setArray(true);
    mAttr.setUsesArrayDataBuilder(true);
    mAttr.setDisconnectBehavior(MFnMatrixAttribute::kDelete);
    addAttribute(aMatrix);
    attributeAffects( aMatrix, outputGeom );

    aInitMatrix = mAttr.create("initProbeMatrix", "ipm");
    mAttr.setHidden(true);
    mAttr.setArray(true);
    mAttr.setStorable(true);
    mAttr.setUsesArrayDataBuilder(true);
    addAttribute(aInitMatrix);
    attributeAffects( aInitMatrix, outputGeom );

    aBlendMode = eAttr.create( "blendMode", "bm", BM_SRL );
    eAttr.addField( "expSO+expSym", BM_SRL );
    eAttr.addField( "expSE+expSym", BM_SSE );
    eAttr.addField( "logmatrix3", BM_LOG3 );
    eAttr.addField( "logmatrix4", BM_LOG4 );
    eAttr.addField( "quat+linear", BM_SQL );
    eAttr.addField( "linear", BM_AFF );
    eAttr.addField( "off", BM_OFF );
    eAttr.setStorable(true);
    eAttr.setKeyable(false);
    addAttribute( aBlendMode );
    attributeAffects( aBlendMode, outputGeom );

	aRotationConsistency = nAttr.create( "rotationConsistency", "rc", MFnNumericData::kBoolean, false );
    nAttr.setKeyable(false);
    nAttr.setStorable(true);
    addAttribute( aRotationConsistency );
    attributeAffects( aRotationConsistency, outputGeom );

	aFrechetSum = nAttr.create( "frechetSum", "fs", MFnNumericData::kBoolean, false );
    nAttr.setKeyable(false);
    nAttr.setStorable(true);
    addAttribute( aFrechetSum );
    attributeAffects( aFrechetSum, outputGeom );
    
    aNormaliseWeight = eAttr.create( "normaliseWeight", "nw", NM_LINEAR );
    eAttr.addField( "NONE", NM_NONE );
    eAttr.addField( "Linear",  NM_LINEAR );
    eAttr.addField( "Softmax", NM_SOFTMAX );
    eAttr.setStorable(true);
    addAttribute( aNormaliseWeight );
    attributeAffects( aNormaliseWeight, outputGeom );
    attributeAffects( aNormaliseWeight, aComputeWeight );

    aWeightMode = eAttr.create( "weightMode", "wtm", WM_HARMONIC_COTAN );
    eAttr.addField( "inverse", WM_INV_DISTANCE );
    eAttr.addField( "cut-off", WM_CUTOFF_DISTANCE );
    eAttr.addField( "draw", WM_DRAW );
//    eAttr.addField( "harmonic-arap", WM_HARMONIC_ARAP);
    eAttr.addField( "harmonic-cotan", WM_HARMONIC_COTAN);
    eAttr.setStorable(true);
    eAttr.setKeyable(false);
    addAttribute( aWeightMode );
    attributeAffects( aWeightMode, outputGeom );
    attributeAffects( aWeightMode, aComputeWeight );
    
    aConstraintMode = eAttr.create( "constraintMode", "ctm", CONSTRAINT_CLOSEST );
    eAttr.addField( "neighbour",  CONSTRAINT_NEIGHBOUR);
    eAttr.addField( "closestFace", CONSTRAINT_CLOSEST );
    eAttr.setStorable(true);
    eAttr.setKeyable(false);
    addAttribute( aConstraintMode );
    attributeAffects( aConstraintMode, outputGeom );
    attributeAffects( aConstraintMode, aARAP);

    aTetMode = eAttr.create( "tetMode", "tm", TM_FACE );
    eAttr.addField( "face", TM_FACE );
    eAttr.addField( "edge", TM_EDGE );
    eAttr.addField( "vertex", TM_VERTEX );
    eAttr.addField( "vface", TM_VFACE );
    eAttr.setStorable(true);
    eAttr.setKeyable(false);
    addAttribute( aTetMode );
    attributeAffects( aTetMode, outputGeom );
    attributeAffects( aTetMode, aARAP );
    attributeAffects( aTetMode, aComputeWeight );

	aWorldMode = nAttr.create( "worldMode", "wrldmd", MFnNumericData::kBoolean, true );
    nAttr.setStorable(true);
    nAttr.setKeyable(false);
    addAttribute( aWorldMode );
    attributeAffects( aWorldMode, outputGeom );
    attributeAffects( aWorldMode, aARAP );
    
	aEffectRadius = nAttr.create("effectRadius", "er", MFnNumericData::kDouble, 8.0);
    nAttr.setMin( EPSILON );
    nAttr.setStorable(true);
	addAttribute( aEffectRadius );
	attributeAffects( aEffectRadius, outputGeom );
	attributeAffects( aEffectRadius, aComputeWeight );
    
	aTransWeight = nAttr.create("translationWeight", "tw", MFnNumericData::kDouble, 1e-20);
    nAttr.setStorable(true);
	addAttribute( aTransWeight );
	attributeAffects( aTransWeight, outputGeom );
	attributeAffects( aTransWeight, aARAP );

    aAreaWeighted = nAttr.create( "areaWeighted", "aw", MFnNumericData::kBoolean, false );
    nAttr.setStorable(true);
    addAttribute( aAreaWeighted );
    attributeAffects( aAreaWeighted, outputGeom );
    attributeAffects( aAreaWeighted, aARAP );

    aNeighbourWeighting = nAttr.create( "neighbourWeighting", "nghbrw", MFnNumericData::kBoolean, false );
    nAttr.setStorable(true);
    addAttribute( aNeighbourWeighting );
    attributeAffects( aNeighbourWeighting, outputGeom );
    attributeAffects( aNeighbourWeighting, aComputeWeight );
    attributeAffects( aNeighbourWeighting, aARAP );

	aConstraintWeight = nAttr.create("constraintWeight", "cw", MFnNumericData::kDouble, 1.0);
    nAttr.setStorable(true);
	addAttribute( aConstraintWeight );
	attributeAffects( aConstraintWeight, outputGeom );
	attributeAffects( aConstraintWeight, aARAP );
    
	aNormExponent = nAttr.create("normExponent", "ne", MFnNumericData::kDouble, 1.0);
    nAttr.setStorable(true);
	addAttribute( aNormExponent );
	attributeAffects( aNormExponent, outputGeom );
	attributeAffects( aNormExponent, aARAP );
	attributeAffects( aNormExponent, aComputeWeight );
    
	aIteration = nAttr.create("iteration", "it", MFnNumericData::kShort, 1);
    nAttr.setStorable(true);
    addAttribute(aIteration);
    attributeAffects(aIteration, outputGeom);
    
	aConstraintRadius = nAttr.create("constraintRadius", "cr", MFnNumericData::kDouble, 1.0);
    nAttr.setStorable(true);
	addAttribute( aConstraintRadius );
	attributeAffects( aConstraintRadius, outputGeom );
	attributeAffects( aConstraintRadius, aARAP );

    aVisualisationMode = eAttr.create( "visualisationMode", "vm", VM_OFF );
    eAttr.addField( "off", VM_OFF );
    eAttr.addField( "energy", VM_ENERGY );
    eAttr.addField( "effect", VM_EFFECT );
    eAttr.addField( "constraint", VM_CONSTRAINT );
    eAttr.addField( "stiffness", VM_STIFFNESS );
    eAttr.setStorable(true);
    addAttribute( aVisualisationMode );
    attributeAffects( aVisualisationMode, outputGeom );
    
	aVisualisationMultiplier = nAttr.create("visualisationMultiplier", "vmp", MFnNumericData::kDouble, 1.0);
    nAttr.setStorable(true);
	addAttribute( aVisualisationMultiplier );
	attributeAffects( aVisualisationMultiplier, outputGeom );
    
    aStiffness = eAttr.create( "stiffnessMode", "stfm", SM_NONE );
    eAttr.addField( "off", SM_NONE );
    eAttr.addField( "painted weight", SM_PAINT );
    eAttr.addField( "learn", SM_LEARN );
    eAttr.setStorable(true);
    addAttribute( aStiffness );
    attributeAffects( aStiffness, outputGeom );
    attributeAffects( aStiffness, aARAP );
    
	aSupervisedMesh = tAttr.create("supervisedMesh", "svmesh", MFnData::kMesh);
    tAttr.setStorable(true);
    tAttr.setArray(true);
    tAttr.setUsesArrayDataBuilder(true);
    addAttribute(aSupervisedMesh);
	attributeAffects( aSupervisedMesh, outputGeom );
	attributeAffects( aSupervisedMesh, aARAP );
    
    aProbeWeight = nAttr.create("probeWeight", "prw", MFnNumericData::kDouble, 1.0);
    nAttr.setArray(true);
    nAttr.setStorable(true);
    nAttr.setUsesArrayDataBuilder(true);
    addAttribute(aProbeWeight);
	attributeAffects( aProbeWeight, outputGeom );
	attributeAffects( aProbeWeight, aComputeWeight );

    aProbeConstraintRadius = nAttr.create("probeConstraintRadius", "prcr", MFnNumericData::kDouble, 1.0);
    nAttr.setArray(true);
    nAttr.setStorable(true);
    nAttr.setUsesArrayDataBuilder(true);
    addAttribute(aProbeConstraintRadius);
	attributeAffects( aProbeConstraintRadius, outputGeom );
	attributeAffects( aProbeConstraintRadius, aARAP );

	//ramp
    aWeightCurveR = rAttr.createCurveRamp( "weightCurveRotation", "wcr" );
    addAttribute( aWeightCurveR );
	attributeAffects( aWeightCurveR, outputGeom );
	attributeAffects( aWeightCurveR, aComputeWeight );
    aWeightCurveS = rAttr.createCurveRamp( "weightCurveShear", "wcs" );
    addAttribute( aWeightCurveS );
	attributeAffects( aWeightCurveS, outputGeom );
	attributeAffects( aWeightCurveS, aComputeWeight );
    aWeightCurveL = rAttr.createCurveRamp( "weightCurveTranslation", "wcl" );
    addAttribute( aWeightCurveL );
	attributeAffects( aWeightCurveL, outputGeom );
	attributeAffects( aWeightCurveL, aComputeWeight );
    
    // Make the deformer weights paintable
    MGlobal::executeCommand( "makePaintable -attrType multiFloat -sm deformer probeDeformerARAP weights;" );

    return MS::kSuccess;
}
Exemplo n.º 4
0
MStatus ropeGenerator::initialize()
{
	MStatus stat;
	MFnTypedAttribute tAttr;
	MFnNumericAttribute nAttr;
	MRampAttribute rAttr;

	inCurve = tAttr.create( "inCurve", "inCurve", MFnData::kNurbsCurve );
	tAttr.setHidden( true);

	divisions = nAttr.create( "divisions", "divisions", MFnNumericData::kInt, 15 );
	nAttr.setMin( 2 );
	nAttr.setSoftMax( 100 );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	createRope = nAttr.create( "createRope", "createRope", MFnNumericData::kBoolean, false );
	nAttr.setWritable( true );
	nAttr.setStorable( true );
	nAttr.setKeyable( true );

	ropesCount = nAttr.create( "ropesCount", "ropesCount", MFnNumericData::kInt, 5 );
	nAttr.setMin( 3 );
	nAttr.setSoftMax( 10 );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	pointsPerRope = nAttr.create( "pointsPerRope", "pointsPerRope", MFnNumericData::kInt, 6 );
	nAttr.setMin( 3 );
	nAttr.setSoftMax( 15 );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	ropesStrength = nAttr.create( "ropesStrength", "ropesStrength", MFnNumericData::kFloat, 1.0f );
	nAttr.setMin( 0.0 );
	nAttr.setMax( 1.0 );
	nAttr.setWritable( true );
	nAttr.setStorable( true );
	nAttr.setKeyable( true );

	pointsCount = nAttr.create( "pointsCount", "pointsCount", MFnNumericData::kInt, 5 );
	nAttr.setMin(3);
	nAttr.setSoftMax( 20 );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	radius = nAttr.create( "radius", "radius", MFnNumericData::kFloat, 1.0f );
	nAttr.setMin( 0.0 );
	nAttr.setSoftMax( 30.0 );
	nAttr.setKeyable( true );
	nAttr.setWritable( true );
	nAttr.setStorable( true );

	taperRamp = rAttr.createCurveRamp( "tapper", "tapper" );

	twist = nAttr.create( "twist", "twist", MFnNumericData::kFloat, 0.0f );
	nAttr.setSoftMin( -3600.0 );
	nAttr.setSoftMax( 3600.0 );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	twistRamp = rAttr.createCurveRamp( "twistRamp", "twistRamp" );

	uvWidth = nAttr.create( "uvWidth", "uvWidth", MFnNumericData::kFloat, 1.0f );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	uvHeight = nAttr.create( "uvHeight", "uvHeight", MFnNumericData::kFloat, 1.0f );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	uvCapSize = nAttr.create( "uvCapSize", "uvCapSize", MFnNumericData::kFloat, 1.0f );
	nAttr.setWritable( true );
	nAttr.setKeyable( true );
	nAttr.setStorable( true );

	outMesh = tAttr.create( "outMesh", "outMesh", MFnData::kMesh );
	tAttr.setWritable( false );
	tAttr.setStorable( false );

	stat = addAttribute( inCurve );
	if (!stat) { stat.perror("addAttribute inCurve"); return stat;}
	stat = addAttribute( divisions );
	if (!stat) { stat.perror("addAttribute divisions"); return stat;}
	stat = addAttribute( createRope );
	if (!stat) { stat.perror("addAttribute createRope"); return stat;}
	stat = addAttribute( ropesCount );
	if (!stat) { stat.perror("addAttribute ropesCount"); return stat;}
	stat = addAttribute( pointsPerRope );
	if (!stat) { stat.perror("addAttribute pointsPerRope"); return stat;}
	stat = addAttribute( ropesStrength );
	if (!stat) { stat.perror("addAttribute ropesStrength"); return stat;}
	stat = addAttribute( pointsCount );
	if (!stat) { stat.perror("addAttribute pointsCount"); return stat;}
	stat = addAttribute( radius );
	if (!stat) { stat.perror("addAttribute radius"); return stat;}
	stat = addAttribute( taperRamp );
	if (!stat) { stat.perror("addAttribute taperRamp"); return stat;}
	stat = addAttribute( twist );
	if (!stat) { stat.perror("addAttribute twist"); return stat;}
	stat = addAttribute( twistRamp );
	if (!stat) { stat.perror("addAttribute twistRamp"); return stat;}
	stat = addAttribute( uvWidth );
	if (!stat) { stat.perror("addAttribute uvWidth"); return stat;}
	stat = addAttribute( uvHeight );
	if (!stat) { stat.perror("addAttribute uvHeight"); return stat;}
	stat = addAttribute( uvCapSize );
	if (!stat) { stat.perror("addAttribute uvCapSize"); return stat;}
	stat = addAttribute( outMesh );
	if (!stat) { stat.perror("addAttribute outMesh"); return stat;}


	stat = attributeAffects( inCurve, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( divisions, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( createRope, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( ropesCount, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( pointsPerRope, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( ropesStrength, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( pointsCount, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( radius, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( taperRamp, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( twist, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( twistRamp, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( uvWidth, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( uvHeight, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( uvCapSize, outMesh );
	if (!stat) { stat.perror("attributeAffects"); return stat;}

	return MS::kSuccess;
}