#include <maya/MIOStream.h>
#include <stdio.h>
#include <stdlib.h>
#include <maya/MFn.h>
#include <maya/MPxNode.h>
#include <maya/MPxManipContainer.h> 
#include <maya/MFnDistanceManip.h> 
#include <maya/MFnFreePointTriadManip.h> 
#include <maya/MFnDiscManip.h> 
#include <maya/MPxContext.h>
#include <maya/MPxSelectionContext.h>
#include <maya/MModelMessage.h>
#include <maya/MPxToolCommand.h>
#include <maya/MFnPlugin.h>
#include <maya/MArgList.h>
#include <maya/MGlobal.h>
#include <maya/MItSelectionList.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MDagPath.h>
#include <maya/MFnTransform.h>
#include <maya/MItCurveCV.h>
#include <maya/MItSurfaceCV.h>
#include <maya/MItMeshVertex.h>
#include <maya/MPxSelectionContext.h>
#include <maya/MPxContextCommand.h>
#include <maya/M3dView.h>
#include <maya/MFnCamera.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MDistance.h>
#include <maya/MManipData.h>
#include <maya/MEulerRotation.h>
#include <maya/MQuaternion.h>
#define     customAttribute1String  "customManip1"
#define     customAttribute2String  "customManip2"
#define     customAttribute3String  "customManip3"
#define     scaleAttributeString    "customScaleAttr"
#define CHECKRESULT(stat,msg)     \
    if (MS::kSuccess != stat) {   \
        cerr << msg << endl;      \
    }
#ifdef LATER
    #define ADDMANIPFUNC        addDiscManip
    #define CUSTOMMANIPTYPE     MFnDiscManip
    #define MANIPDIRECTIONFUNC      setNormal
    #define MANIPPLUGCONN       connectToAnglePlug
#else
    #define ADDMANIPFUNC        addDistanceManip
    #define CUSTOMMANIPTYPE     MFnDistanceManip
    #define MANIPDIRECTIONFUNC      setDirection
    #define MANIPPLUGCONN       connectToDistancePlug
#endif
{
public:
    customAttrManip();
    virtual ~customAttrManip();
    
    static void * creator();
    void updateManipLocations();
public:
};
MTypeId customAttrManip::id( 0x80020 );
 
customAttrManip::customAttrManip() 
{ 
    
    
}
customAttrManip::~customAttrManip() 
{
}
void *customAttrManip::creator()
{
     return new customAttrManip();
}
MStatus customAttrManip::initialize()
 
{ 
    return stat;
}
{
    
    
    
}
{
}
MStatus  customAttrManip::doRelease()
 
{
    
    updateManipLocations();
    
}
MStatus customAttrManip::createChildren()
 
{
    MString pointManipName1(
"customtManip1");
 
    MString pointName1(
"customPoint1");
 
    fManip1 = ADDMANIPFUNC(pointManipName1, pointName1);
    MString pointManipName2(
"customtManip2");
 
    MString pointName2(
"customPoint2");
 
    fManip2 = ADDMANIPFUNC(pointManipName2, pointName2);
    MString pointManipName3(
"customtManip3");
 
    MString pointName3(
"customPoint3");
 
    fManip3 = ADDMANIPFUNC(pointManipName3, pointName3);
    return stat;
}
{
    
    
    
    
    
    return q;
}
MVector customAttrManip::nodeTranslation()
 const 
{
    
    
    
    
    
}
void customAttrManip::updateManipLocations()
{
    CUSTOMMANIPTYPE freePointManipFn1(fManip1);
    CUSTOMMANIPTYPE freePointManipFn2(fManip2);
    CUSTOMMANIPTYPE freePointManipFn3(fManip3);
    freePointManipFn1.MANIPDIRECTIONFUNC(vecX);
    freePointManipFn1.rotateBy(q);
    freePointManipFn2.MANIPDIRECTIONFUNC(vecY);
    freePointManipFn2.rotateBy(q);
    freePointManipFn3.MANIPDIRECTIONFUNC(vecZ);
    freePointManipFn3.rotateBy(q);
}
{
    
    
    dagNodeFn.getPath(fNodePath);
    
    
    CUSTOMMANIPTYPE freePointManipFn1(fManip1);
    CUSTOMMANIPTYPE freePointManipFn2(fManip2);
    CUSTOMMANIPTYPE freePointManipFn3(fManip3);
    MPlug cPlug1 = nodeFn.findPlug(customAttribute1String, &stat);
 
    {
        cerr << "Can't find dynamic attr -- " << customAttribute1String << endl;
    }
    else
    {
        freePointManipFn1.MANIPPLUGCONN(cPlug1);
    }
    MPlug cPlug2 = nodeFn.findPlug(customAttribute2String, &stat);
 
    {
        cerr << "Can't find dynamic attr -- " << customAttribute1String << endl;
    }
    else
    {
        freePointManipFn2.MANIPPLUGCONN(cPlug2);
    }
    MPlug cPlug3 = nodeFn.findPlug(customAttribute3String, &stat);
 
    {
        cerr << "Can't find dynamic attr -- " << customAttribute1String << endl;
    }
    else
    {
        freePointManipFn3.MANIPPLUGCONN(cPlug3);
    }
    finishAddingManips();
    MPlug cPlug4 = nodeFn.findPlug(scaleAttributeString, &stat);
 
    {
        cerr << "Can't find dynamic attr -- " << scaleAttributeString << endl;
    }
    else
    {
        double factor;
        freePointManipFn1.setScalingFactor( factor );
        freePointManipFn2.setScalingFactor( factor );
        freePointManipFn3.setScalingFactor( factor );
    }
    updateManipLocations();
    return stat;
}
void customAttrManip::draw(
M3dView & view, 
 
{ 
}
#define MOVEHELPSTR     "Drag rings to change values on custom attributes"
#define MOVETITLESTR    "customAttrManip"
{
public:
    customAttrCtx();
    customAttrManip * caManip;
};
void updateManipulators(void * data);
MCallbackId id1;
customAttrCtx::customAttrCtx()
{
    setTitleString(str);
}
void customAttrCtx::toolOnSetup(
MEvent &)
 
{
    setHelpString(str);
    updateManipulators(this);
                                     updateManipulators, 
                                     this, &status);
    if (!status) {
        cerr << "Model addCallback failed\n";
    }
}
void customAttrCtx::toolOffCleanup()
{
    if (!status) {
        cerr << "Model remove callback failed\n";
    }
}
void updateManipulators(void * data)
{
    
    
    customAttrCtx * ctxPtr = (customAttrCtx *) data;
    ctxPtr->deleteManipulators(); 
    
    
        for (; !iter.isDone(); iter.next()) {
            
            
            MString manipName (
"customAttrManip");
 
            ctxPtr->caManip = (customAttrManip *) customAttrManip::newManipulator(manipName, manipObject);
            if (NULL != ctxPtr->caManip) {
                ctxPtr->addManipulator(manipObject);
                iter.getDependNode(dependNode);
                
                dependNodeFn.findPlug(customAttribute1String, &stat);
                    cerr << "dependNodeFn.findPlug failed\n";
                    ctxPtr->deleteManipulators(); 
                    return;
                }
                dependNodeFn.findPlug(customAttribute2String, &stat);
                    cerr << "dependNodeFn.findPlug failed\n";
                    ctxPtr->deleteManipulators(); 
                    return;
                }
                dependNodeFn.findPlug(customAttribute3String, &stat);
                    cerr << "dependNodeFn.findPlug failed\n";
                    ctxPtr->deleteManipulators(); 
                    return;
                }
                else {
                    
                }
                ctxPtr->caManip->connectToDependNode(dependNode);
            } 
        }
    }
}
{
    return setHelpString(str);
}
#define CREATE_CTX_NAME "customAttrManipContext"
{
public:
    customAttrCtxCommand() {};
public:
    static void* creator();
};
{
    customAttrCtx *newC = new customAttrCtx();
    return newC;
}
void *customAttrCtxCommand::creator()
{
    return new customAttrCtxCommand;
}
{
    MFnPlugin plugin(obj, PLUGIN_COMPANY, 
"3.0", 
"Any");
 
    status = plugin.registerContextCommand(CREATE_CTX_NAME,
                                           &customAttrCtxCommand::creator);
    if (!status) 
    {
        status.
perror(
"registerContextCommand");
        return status;
    }
    status = plugin.registerNode("customAttrManip", customAttrManip::id, 
                                 &customAttrManip::creator, &customAttrManip::initialize,
    if (!status) 
    {
        status.
perror(
"registerNode");
        return status;
    }
    return status;
}
{
    status = plugin.deregisterContextCommand(CREATE_CTX_NAME);
    if (!status) {
        status.
perror(
"deregisterContextCommand");
        return status;
    }
    status = plugin.deregisterNode(customAttrManip::id);
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    return status;
}