moveManip.cpp
#include <maya/MIOStream.h>
#include <stdio.h>
#include <stdlib.h>
#include <maya/MFn.h>
#include <maya/MPxNode.h>
#include <maya/MPxManipContainer.h>
#include <maya/MPxSelectionContext.h>
#include <maya/MPxContextCommand.h>
#include <maya/MModelMessage.h>
#include <maya/MFnPlugin.h>
#include <maya/MGlobal.h>
#include <maya/MItSelectionList.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MDagPath.h>
#include <maya/MManipData.h>
#include <maya/MFnFreePointTriadManip.h>
#include <maya/MFnDistanceManip.h>
class moveManip : public MPxManipContainer
{
public:
        moveManip();
        virtual ~moveManip();
        
        static void * creator();
        static MStatus initialize();
        virtual MStatus createChildren();
        virtual MStatus connectToDependNode(const MObject &node);
        virtual void draw(M3dView &view, 
                                          const MDagPath &path, 
                                          M3dView::DisplayStyle style,
                                          M3dView::DisplayStatus status);
        MDagPath fDistanceManip;
        MDagPath fFreePointManip;
public:
        static MTypeId id;
};
MTypeId moveManip::id( 0x8001d );
moveManip::moveManip() 
{ 
        
        
}
moveManip::~moveManip() 
{
}
void *moveManip::creator()
{
         return new moveManip();
}
MStatus moveManip::initialize()
{ 
        MStatus stat;
        stat = MPxManipContainer::initialize();
        return stat;
}
MStatus moveManip::createChildren()
{
        MStatus stat = MStatus::kSuccess;
        fDistanceManip = addDistanceManip("distanceManip",
                                                                          "distance");
        
        
        MFnDistanceManip distanceManipFn(fDistanceManip);
        MPoint startPoint(0.0, 0.0, 0.0);
        MVector direction(0.0, 1.0, 0.0);
        distanceManipFn.setStartPoint(startPoint);
        distanceManipFn.setDirection(direction);
        fFreePointManip = addFreePointTriadManip("pointManip",
                                                                                         "freePoint");
        return stat;
}
MStatus moveManip::connectToDependNode(const MObject &node)
{
        MStatus stat;
        
        
        
        
        
        MFnDependencyNode nodeFn(node);
        MPlug syPlug = nodeFn.findPlug("scaleY", &stat);
        MPlug tPlug = nodeFn.findPlug("translate", &stat);
        MFnDistanceManip distanceManipFn(fDistanceManip);
        distanceManipFn.connectToDistancePlug(syPlug);
        MFnFreePointTriadManip freePointManipFn(fFreePointManip);
        freePointManipFn.connectToPointPlug(tPlug);
        
        
        
        
        
        MVector offset(0.0, 0.0, 0.0);
        freePointManipFn.setTranslation(offset, MSpace::kTransform);
        finishAddingManips();
        MPxManipContainer::connectToDependNode(node);           
        return stat;
}
void moveManip::draw(M3dView & view, 
                                         const MDagPath & path, 
                                         M3dView::DisplayStyle style,
                                         M3dView::DisplayStatus status)
{
        
        
        
        
        MPxManipContainer::draw(view, path, style, status);
        view.beginGL(); 
        MPoint textPos(0, 0, 0);
        char str[100];
        sprintf(str, "Stretch Me!"); 
        MString distanceText(str);
        view.drawText(distanceText, textPos, M3dView::kLeft);
        view.endGL();
}
class MoveManipContext : public MPxSelectionContext
{
public:
        MoveManipContext();
        virtual void    toolOnSetup(MEvent &event);
        virtual void    toolOffCleanup();
        
        static void updateManipulators(void * data);
private:
        MCallbackId id1;
};
MoveManipContext::MoveManipContext()
{
        MString str("Plugin move Manipulator");
        setTitleString(str);
}
void MoveManipContext::toolOnSetup(MEvent &)
{
        MString str("Move the object using the manipulator");
        setHelpString(str);
        updateManipulators(this);
        MStatus status;
        id1 = MModelMessage::addCallback(MModelMessage::kActiveListModified,
                                                                         updateManipulators, 
                                                                         this, &status);
        if (!status) {
                MGlobal::displayError("Model addCallback failed");
        }
}
void MoveManipContext::toolOffCleanup()
{
        MStatus status;
        status = MModelMessage::removeCallback(id1);
        if (!status) {
                MGlobal::displayError("Model remove callback failed");
        }
        MPxContext::toolOffCleanup();
}
void MoveManipContext::updateManipulators(void * data)
{
        MStatus stat = MStatus::kSuccess;
        
        MoveManipContext * ctxPtr = (MoveManipContext *) data;
        ctxPtr->deleteManipulators(); 
        MSelectionList list;
        stat = MGlobal::getActiveSelectionList(list);
        MItSelectionList iter(list, MFn::kInvalid, &stat);
        if (MS::kSuccess == stat) {
                for (; !iter.isDone(); iter.next()) {
                        
                        
                        
                        MObject dependNode;
                        iter.getDependNode(dependNode);
                        if (dependNode.isNull() || !dependNode.hasFn(MFn::kDependencyNode))
                        {
                                MGlobal::displayWarning("Object in selection list is not "
                                        "a depend node.");
                                continue;
                        }
                        MFnDependencyNode dependNodeFn(dependNode);
                        MPlug rPlug = dependNodeFn.findPlug("translate", &stat);
                        MPlug sPlug = dependNodeFn.findPlug("scaleY", &stat);
                        if (rPlug.isNull() || sPlug.isNull()) {
                                MGlobal::displayWarning("Object cannot be manipulated: " +
                                        dependNodeFn.name());
                                continue;
                        }
                        
                        
                        MString manipName ("moveManip");
                        MObject manipObject;
                        moveManip* manipulator =
                                (moveManip *) moveManip::newManipulator(manipName, manipObject);
                        if (NULL != manipulator) {
                                
                                
                                ctxPtr->addManipulator(manipObject);
                                
                                
                                if (!manipulator->connectToDependNode(dependNode))
                                {
                                        MGlobal::displayWarning("Error connecting manipulator to"
                                                " object: " + dependNodeFn.name());
                                }
                        } 
                }
        }
}
class moveManipContext : public MPxContextCommand
{
public:
        moveManipContext() {};
        virtual MPxContext * makeObj();
public:
        static void* creator();
};
MPxContext *moveManipContext::makeObj()
{
        return new MoveManipContext();
}
void *moveManipContext::creator()
{
        return new moveManipContext;
}
MStatus initializePlugin(MObject obj)
{
        MStatus status;
        MFnPlugin plugin(obj, PLUGIN_COMPANY, "3.0", "Any");
        status = plugin.registerContextCommand("moveManipContext",
                                                                                   &moveManipContext::creator);
        if (!status) {
                MGlobal::displayError("Error registering moveManipContext command");
                return status;
        }
        status = plugin.registerNode("moveManip", moveManip::id, 
                                                                 &moveManip::creator, &moveManip::initialize,
                                                                 MPxNode::kManipContainer);
        if (!status) {
                MGlobal::displayError("Error registering moveManip node");
                return status;
        }
        return status;
}
MStatus uninitializePlugin(MObject obj)
{
        MStatus status;
        MFnPlugin plugin(obj);
        status = plugin.deregisterContextCommand("moveManipContext");
        if (!status) {
                MGlobal::displayError("Error deregistering moveManipContext command");
                return status;
        }
        status = plugin.deregisterNode(moveManip::id);
        if (!status) {
                MGlobal::displayError("Error deregistering moveManip node");
                return status;
        }
        return status;
}