//
//	Calls applyRotationLocks && applyRotationLimits
//	This method verifies that the passed value can be set on the 
//	rotate plugs. In the base class, limits as well as locking are
//	checked by this method.
//
//	The compute, validateAndSetValue, and rotateTo functions
//	all use this method.
//
MStatus rockingTransformCheckNode::checkAndSetRotation(MDataBlock &block,
									const MPlug& plug,
									const MEulerRotation& newRotation, 
									MSpace::Space space )
{
	const MDGContext context = block.context();
	updateMatrixAttrs(context);

	MStatus status = MS::kSuccess;
	MEulerRotation outRotation = newRotation;
	if (context.isNormal()) {
		//	For easy reading.
		//
		MPxTransformationMatrix *xformMat = baseTransformationMatrix;

		//	Get the current translation in transform space for 
		//	clamping and locking.
		//
		MEulerRotation savedRotation = 
			xformMat->eulerRotation(MSpace::kTransform, &status);
		ReturnOnError(status);

		//	Translate to transform space, since the limit test needs the
		//	values in transform space. The locking test needs the values
		//	in the same space as the savedR value - which is transform 
		//	space as well.
		//
		status = baseTransformationMatrix->rotateTo(newRotation, space);
		ReturnOnError(status);

		outRotation = xformMat->eulerRotation(MSpace::kTransform, &status);
		ReturnOnError(status);

		//	Now that everything is in the same space, apply limits 
		//	and change the value to adhere to plug locking.
		//
		outRotation = applyRotationLimits(outRotation, block, &status);
		ReturnOnError(status);

		outRotation = applyRotationLocks(outRotation, savedRotation, &status);
		ReturnOnError(status);

		//	The value that remain is in transform space.
		//
		status = xformMat->rotateTo(outRotation, MSpace::kTransform);
		ReturnOnError(status);

		//	Get the value that was just set. It needs to be in transform
		//	space since it is used to set the datablock values at the
		//	end of this method. Getting the vaolue right before setting
		//	ensures that the transformation matrix and data block will
		//	be synchronized.
		//
		outRotation = xformMat->eulerRotation(MSpace::kTransform, &status);
		ReturnOnError(status);
	} else {
		//	Get the rotation for clamping and locking. This will get the
		//	rotate value in transform space.
		//
		double3 &s3 = block.inputValue(rotate).asDouble3();
		MEulerRotation savedRotation(s3[0], s3[1], s3[2]);

		//	Create a local transformation matrix for non-normal context
		//	calculations.
		//
		MPxTransformationMatrix *local = createTransformationMatrix();
		if (NULL == local) {
			MGlobal::displayError("rockingTransformCheck::checkAndSetRotation internal error");
			return status;
		}

		//	Fill the newly created transformation matrix.
		//
		status = computeLocalTransformation(local, block);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		//	Translate the values to transform space. This will allow the 
		//	limit and locking tests to work properly.
		//
		status = local->rotateTo(newRotation, space);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		outRotation = local->eulerRotation(MSpace::kTransform, &status);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		//	Apply limits
		//
		outRotation = applyRotationLimits(outRotation, block, &status);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		outRotation = applyRotationLocks(outRotation, savedRotation, &status);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		status = local->rotateTo(outRotation, MSpace::kTransform);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		//	Get the rotate value in transform space for placement in the
		//	datablock.
		//
		outRotation = local->eulerRotation(MSpace::kTransform, &status);
		if ( MS::kSuccess != status)
		{
			delete local;
			return status;
		}

		delete local;
	}

	MDataHandle handle = block.outputValue(plug, &status);
	if ( MS::kSuccess != status)
	{
		return status;
	}

	if (plug == rotate) {
		handle.set(outRotation.x, outRotation.y, outRotation.z);
	} else if (plug == rotateX) {
		handle.set(outRotation.x);
	} else if (plug == rotateY) {
		handle.set(outRotation.y);
	} else {
		handle.set(outRotation.z);
	}

	return status;
}
示例#2
0
MStatus dgTransform::compute( const MPlug& plug, MDataBlock& data )
{
	MStatus status;

	MDataHandle hTranslate = data.inputValue( aTranslate, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hRotate    = data.inputValue( aRotate, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hScale     = data.inputValue( aScale, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hShear     = data.inputValue( aShear, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hJointOrient     = data.inputValue( aJointOrient, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );

	MDataHandle hInputTranslate = data.inputValue( aInputTranslate, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hInputRotate    = data.inputValue( aInputRotate, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hInputScale     = data.inputValue( aInputScale, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hInputShear     = data.inputValue( aInputShear, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );


	MPxTransformationMatrix inputMpxTrMtx;
	MEulerRotation inputEulerRot( hInputRotate.asVector() );

	inputMpxTrMtx.translateTo( hInputTranslate.asVector() );
	inputMpxTrMtx.rotateTo( inputEulerRot );
	inputMpxTrMtx.scaleTo( hInputScale.asVector() );
	inputMpxTrMtx.shearTo( hInputShear.asVector() );


	MMatrix parentMatrix = inputMpxTrMtx.asMatrix();


	MPxTransformationMatrix mpxTrMtx;
	MEulerRotation eulerRot( hRotate.asVector() );
	MEulerRotation joEulerRot( hJointOrient.asVector() );

	mpxTrMtx.translateTo( hTranslate.asVector() );
	mpxTrMtx.rotateTo( eulerRot );
	mpxTrMtx.rotateBy( joEulerRot );
	mpxTrMtx.scaleTo( hScale.asVector() );
	mpxTrMtx.shearTo( hShear.asVector() );

	if( plug == aMatrix )
	{
		//cout <<"matrix"<<endl;
		MDataHandle hMatrix = data.outputValue( aMatrix, &status );
		CHECK_MSTATUS_AND_RETURN_IT( status );
		hMatrix.setMMatrix( mpxTrMtx.asMatrix() );
	}

	if( plug == aInverseMatrix )
	{
		//cout <<"inverseMatrix"<<endl;
		MDataHandle hInverseMatrix = data.outputValue( aInverseMatrix, &status );
		CHECK_MSTATUS_AND_RETURN_IT( status );
		hInverseMatrix.setMMatrix( mpxTrMtx.asMatrix().inverse() );
	}

	if( plug == aWorldMatrix || plug == aWorldInverseMatrix )
	{
		MMatrix worldMatrix = mpxTrMtx.asMatrix()*parentMatrix;
		if( plug == aWorldMatrix )
		{
			//cout <<"worldMatrix"<<endl;
			MDataHandle hWorldMatrix = data.outputValue( aWorldMatrix, &status );
			CHECK_MSTATUS_AND_RETURN_IT( status );
			hWorldMatrix.setMMatrix( worldMatrix );
		}

		if( plug == aWorldInverseMatrix )
		{
			//cout <<"worldInverseMatrix"<<endl;
			MDataHandle hWorldInverseMatrix = data.outputValue( aWorldInverseMatrix, &status );
			CHECK_MSTATUS_AND_RETURN_IT( status );
			hWorldInverseMatrix.setMMatrix( worldMatrix.inverse() );
		}
	}

	if( plug == aParentMatrix )
	{
		//cout <<"parentMatrix"<<endl;
		MDataHandle hParentMatrix = data.outputValue( aParentMatrix, &status );
		CHECK_MSTATUS_AND_RETURN_IT( status );
		hParentMatrix.setMMatrix( parentMatrix );
	}

	if( plug == aParentInverseMatrix )
	{
		//cout <<"parentInverseMatrix"<<endl;
		MDataHandle hParentInverseMatrix = data.outputValue( aParentInverseMatrix, &status );
		CHECK_MSTATUS_AND_RETURN_IT( status );
		hParentInverseMatrix.setMMatrix( parentMatrix.inverse() );
	}

	data.setClean( plug );

	return status;
}