rockingTransform.cpp
#include <maya/MPxTransform.h>
#include <maya/MPxTransformationMatrix.h>
#include <maya/MGlobal.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MIOStream.h>
#include "rockingTransform.h"
#ifndef M_PI
#include <math.h>
#endif
MObject rockingTransformNode::aRockInX;
MTypeId rockingTransformNode::id(kRockingTransformNodeID);
MTypeId rockingTransformMatrix::id(kRockingTransformMatrixID);
rockingTransformMatrix::rockingTransformMatrix()
{
        rockXValue = 0.0;
}
void *rockingTransformMatrix::creator()
{
        return new rockingTransformMatrix();
}
double rockingTransformMatrix::getRockInX() const
{
        return rockXValue;
}
void rockingTransformMatrix::setRockInX( double rock )
{
        rockXValue = rock;
}
MMatrix rockingTransformMatrix::asMatrix() const
{
        
        MMatrix m = ParentClass::asMatrix();
        
        MTransformationMatrix tm( m );
        
        MQuaternion quat = rotation();
        
        DegreeRadianConverter conv;
        double newTheta = conv.degreesToRadians( getRockInX() );
        quat.setToXAxis( newTheta );
        
        tm.addRotationQuaternion( quat.x, quat.y, quat.z, quat.w, MSpace::kTransform );
        
        return tm.asMatrix();
}
MMatrix rockingTransformMatrix::asMatrix(double percent) const
{
        MPxTransformationMatrix m(*this);
        
        MVector trans = m.translation();
        trans *= percent;
        m.translateTo( trans );
        MPoint rotatePivotTrans = m.rotatePivot();
        rotatePivotTrans = rotatePivotTrans * percent;
        m.setRotatePivot( rotatePivotTrans );
        MPoint scalePivotTrans = m.scalePivotTranslation();
        scalePivotTrans = scalePivotTrans * percent;
        m.setScalePivotTranslation( scalePivotTrans );
        
        
        MQuaternion quat = rotation();
        DegreeRadianConverter conv;
        double newTheta = conv.degreesToRadians( getRockInX() );
        quat.setToXAxis( newTheta );
        m.rotateBy( quat );
        MEulerRotation eulRotate = m.eulerRotation();
        m.rotateTo(  eulRotate * percent, MSpace::kTransform);
        
        MVector s(scale(MSpace::kTransform));
        s.x = 1.0 + (s.x - 1.0)*percent;
        s.y = 1.0 + (s.y - 1.0)*percent;
        s.z = 1.0 + (s.z - 1.0)*percent;
        m.scaleTo(s, MSpace::kTransform);
        return m.asMatrix();
}
MMatrix rockingTransformMatrix::asRotateMatrix() const
{
        
        return ParentClass::asRotateMatrix();
}
rockingTransformNode::rockingTransformNode()
: ParentClass()
{
        rockXValue = 0.0;
}
rockingTransformNode::rockingTransformNode(MPxTransformationMatrix *tm)
: ParentClass(tm)
{
        rockXValue = 0.0;
}
void rockingTransformNode::postConstructor()
{
        
        
        ParentClass::postConstructor();
        
        
        
        if (NULL == baseTransformationMatrix) {
                MGlobal::displayWarning("NULL baseTransformationMatrix found!");
                baseTransformationMatrix = new MPxTransformationMatrix();
        }
        MPlug aRockInXPlug(thisMObject(), aRockInX);
}
rockingTransformNode::~rockingTransformNode()
{
}
MPxTransformationMatrix *rockingTransformNode::createTransformationMatrix()
{
        return new rockingTransformMatrix();
}
void *rockingTransformNode::creator()
{
        return new rockingTransformNode();
}
MStatus rockingTransformNode::initialize()
{
        MFnNumericAttribute numFn;
        aRockInX = numFn.create("RockInX", "rockx", MFnNumericData::kDouble, 0.0);
        numFn.setKeyable(true);
        numFn.setAffectsWorldSpace(true);
        addAttribute(aRockInX);
        
        mustCallValidateAndSet(aRockInX);
        return MS::kSuccess;
}
const char* rockingTransformNode::className() 
{
        return "rockingTransformNode";
}
void  rockingTransformNode::resetTransformation (const MMatrix &matrix)
{
        ParentClass::resetTransformation( matrix );
}
void  rockingTransformNode::resetTransformation (MPxTransformationMatrix *resetMatrix )
{
        ParentClass::resetTransformation( resetMatrix );
}
MStatus rockingTransformNode::validateAndSetValue(const MPlug& plug,
                                                                                                const MDataHandle& handle,
                                                                                                const MDGContext& context)
{
        MStatus status = MS::kSuccess;
        
        
        if (plug.isNull())
                return MS::kFailure;
        MDataBlock block = forceCache(*(MDGContext *)&context);
        MDataHandle blockHandle = block.outputValue(plug, &status);
        ReturnOnError(status);
        
        if ( plug == aRockInX )
        {
                
                double rockInX = handle.asDouble();
                blockHandle.set(rockInX);
                rockXValue = rockInX;
                
                
                
                rockingTransformMatrix *ltm = getRockingTransformMatrix();
                if (ltm)
                        ltm->setRockInX(rockXValue);
                else 
                        MGlobal::displayError("Failed to get rock transform matrix");
                        
                blockHandle.setClean();
                
                
                
                dirtyMatrix();          
        }
        
        
        return ParentClass::validateAndSetValue(plug, handle, context);
}
rockingTransformMatrix *rockingTransformNode::getRockingTransformMatrix()
{
        rockingTransformMatrix *ltm = (rockingTransformMatrix *) baseTransformationMatrix;
        return ltm;
}
double DegreeRadianConverter::degreesToRadians( double degrees )
{
         return degrees * ( M_PI/ 180.0 );
}
double DegreeRadianConverter::radiansToDegrees( double radians )
{
        return radians * (180.0/M_PI);
}