#include <maya/MIOStream.h>
#include <maya/MPxNode.h>   
#include <maya/MPxLocatorNode.h> 
#include <maya/MString.h> 
#include <maya/MTypeId.h> 
#include <maya/MPlug.h>
#include <maya/MVector.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MColor.h>
#include <maya/M3dView.h>
#include <maya/MFnPlugin.h>
#include <maya/MDistance.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFn.h>
#include <maya/MPxNode.h>
#include <maya/MPxManipContainer.h> 
#include <maya/MFnDistanceManip.h> 
#include <maya/MPxContext.h>
#include <maya/MPxSelectionContext.h>
#include <maya/MFnNumericData.h>
#include <maya/MManipData.h>
#include <maya/MDrawRegistry.h>
#include <maya/MPxDrawOverride.h>
#include <maya/MUserData.h>
#include <maya/MDrawContext.h>
#include <maya/MHWGeometryUtilities.h>
#include <maya/MPointArray.h>
static float sole[][3] = { {  0.00f, 0.0f, -0.70f},
                           {  0.04f, 0.0f, -0.69f },
                           {  0.09f, 0.0f, -0.65f },
                           {  0.13f, 0.0f, -0.61f }, 
                           {  0.16f, 0.0f, -0.54f },
                           {  0.17f, 0.0f, -0.46f },
                           {  0.17f, 0.0f, -0.35f },
                           {  0.16f, 0.0f, -0.25f },
                           {  0.15f, 0.0f, -0.14f },
                           {  0.13f, 0.0f,  0.00f },
                           {  0.00f, 0.0f,  0.00f },
                           { -0.13f, 0.0f,  0.00f },
                           { -0.15f, 0.0f, -0.14f },
                           { -0.16f, 0.0f, -0.25f },
                           { -0.17f, 0.0f, -0.35f },
                           { -0.17f, 0.0f, -0.46f }, 
                           { -0.16f, 0.0f, -0.54f },
                           { -0.13f, 0.0f, -0.61f },
                           { -0.09f, 0.0f, -0.65f },
                           { -0.04f, 0.0f, -0.69f }, 
                           { -0.00f, 0.0f, -0.70f } }; 
static float heel[][3] = { {  0.00f, 0.0f,  0.06f },
                           {  0.13f, 0.0f,  0.06f },
                           {  0.14f, 0.0f,  0.15f },
                           {  0.14f, 0.0f,  0.21f }, 
                           {  0.13f, 0.0f,  0.25f },
                           {  0.11f, 0.0f,  0.28f },
                           {  0.09f, 0.0f,  0.29f },
                           {  0.04f, 0.0f,  0.30f },
                           {  0.00f, 0.0f,  0.30f },
                           { -0.04f, 0.0f,  0.30f },
                           { -0.09f, 0.0f,  0.29f },
                           { -0.11f, 0.0f,  0.28f }, 
                           { -0.13f, 0.0f,  0.25f },
                           { -0.14f, 0.0f,  0.21f },
                           { -0.14f, 0.0f,  0.15f },
                           { -0.13f, 0.0f,  0.06f },  
                           { -0.00f, 0.0f,  0.06f } }; 
static int heelCount = 17;
static int soleCount = 21;
 
{
public:
    footPrintLocatorManip();
    virtual ~footPrintLocatorManip();
    
    static void * creator();
    
    MManipData startPointCallback(
unsigned index) 
const;
 
    
public:
};
MManipData footPrintLocatorManip::startPointCallback(
unsigned index)
  
const
{
}
MVector footPrintLocatorManip::nodeTranslation()
 const 
{
}
MTypeId footPrintLocatorManip::id( 0x8001b );
 
footPrintLocatorManip::footPrintLocatorManip() 
{ 
    
}
footPrintLocatorManip::~footPrintLocatorManip() 
{
}
void* footPrintLocatorManip::creator()
{
     return new footPrintLocatorManip();
}
MStatus footPrintLocatorManip::initialize()
 
{ 
    return stat;
}
MStatus footPrintLocatorManip::createChildren()
 
{
    MString manipName(
"distanceManip");
 
    MPoint startPoint(0.0, 0.0, 0.0);
 
    fDistanceManip = addDistanceManip(manipName,
                                      distanceName);
    distanceManipFn.setStartPoint(startPoint);
    distanceManipFn.setDirection(direction);
    
    return stat;
}
MStatus footPrintLocatorManip::connectToDependNode(
const MObject &node)
 
{
    
    
    dagNodeFn.getPath(fNodePath);
    
    
    MPlug sizePlug = nodeFn.findPlug(
"size", &stat);
 
        distanceManipFn.connectToDistancePlug(sizePlug);
        unsigned startPointIndex = distanceManipFn.startPointIndex();
        addPlugToManipConversionCallback(startPointIndex, 
                                         (plugToManipConversionCallback) 
                                         &footPrintLocatorManip::startPointCallback);
        
        
        addPlugToInViewEditor( sizePlug );
        finishAddingManips();
    }
    return stat;
}
void footPrintLocatorManip::draw(
M3dView & view, 
 
{ 
    MPoint textPos = nodeTranslation();
 
    char str[100];
    sprintf(str, "Stretch Me!"); 
}
void    footPrintLocatorManip::preDrawUI( 
const M3dView &view )
 
{
    
    fTextPosition = nodeTranslation();
}
void    footPrintLocatorManip::drawUI(
{
}
{
public:
    footPrintLocator();
    virtual ~footPrintLocator(); 
    static  void *          creator();
public: 
    static  MString     drawDbClassification;
 
};
MTypeId footPrintLocator::id( 0x8001c );
 
MString footPrintLocator::drawDbClassification(
"drawdb/geometry/footPrintLocator");
 
MString footPrintLocator::drawRegistrantId(
"FootPrintManipPlugin");
 
footPrintLocator::footPrintLocator() 
{}
footPrintLocator::~footPrintLocator() 
{}
{ 
}
{ 
    
    
    MPlug plug(thisNode, size);
 
    plug.getValue(sizeVal);
    {  
        
        
        glPushAttrib(GL_CURRENT_BIT);
        } else {
        }  
        glBegin(GL_TRIANGLE_FAN);
            int i;
            int last = soleCount - 1;
            for (i = 0; i < last; ++i) {
                glVertex3f(sole[i][0] * multiplier,
                           sole[i][1] * multiplier,
                           sole[i][2] * multiplier);
            } 
        glEnd();
        glBegin(GL_TRIANGLE_FAN);
            last = heelCount - 1;
            for (i = 0; i < last; ++i) {
                glVertex3f(heel[i][0] * multiplier,
                           heel[i][1] * multiplier,
                           heel[i][2] * multiplier);
            }
        glEnd();
        glPopAttrib();
    }
    
    
    glBegin(GL_LINES);
        int i;
        int last = soleCount - 1;
        for (i = 0; i < last; ++i) { 
            glVertex3f(sole[i][0] * multiplier, 
                       sole[i][1] * multiplier, 
                       sole[i][2] * multiplier);
            glVertex3f(sole[i+1][0] * multiplier, 
                       sole[i+1][1] * multiplier, 
                       sole[i+1][2] * multiplier);
        } 
        last = heelCount - 1;
        for (i = 0; i < last; ++i) { 
            glVertex3f(heel[i][0] * multiplier, 
                       heel[i][1] * multiplier, 
                       heel[i][2] * multiplier);
            glVertex3f(heel[i+1][0] * multiplier, 
                       heel[i+1][1] * multiplier, 
                       heel[i+1][2] * multiplier);
        }
    glEnd();
}
bool footPrintLocator::isBounded() const
{ 
    return true;
}
{   
    
    
    MPlug plug(thisNode, size);
 
    plug.getValue(sizeVal);
 
    MPoint corner1(-0.17, 0.0, -0.7);
 
    MPoint corner2(0.17, 0.0, 0.3);
 
    corner1 = corner1 * multiplier;
    corner2 = corner2 * multiplier;
}
void* footPrintLocator::creator()
{
    return new footPrintLocator();
}
MStatus footPrintLocator::initialize()
 
{ 
    stat = addAttribute(size);
    if (!stat) {
        return stat;
    }
    
}
class FootPrintLocatorData : 
public MUserData 
{
public:
    virtual ~FootPrintLocatorData() {}
};
{
public:
    {
        return new FootPrintLocatorDrawOverride(obj);
    }
    virtual ~FootPrintLocatorDrawOverride();
protected:
private:
    FootPrintLocatorDrawOverride(
const MObject& obj);
    float getMultiplier(
const MDagPath& objPath) 
const;
 
};
FootPrintLocatorDrawOverride::FootPrintLocatorDrawOverride(
const MObject& obj)
{
}
FootPrintLocatorDrawOverride::~FootPrintLocatorDrawOverride()
{
}
{
    
}
float FootPrintLocatorDrawOverride::getMultiplier(
const MDagPath& objPath)
 const 
{
    
    if (status)
    {
        MPlug plug(footprintLocatorNode, footPrintLocator::size);
 
        if (!plug.isNull())
        {
            if (plug.getValue(sizeVal))
            {
            }
        }
    }
    return 1.0f;
}
bool FootPrintLocatorDrawOverride::isBounded(
const MDagPath& ,
 
{
    return true;
}
{
    MPoint corner1( -0.17, 0.0, -0.7 );
 
    MPoint corner2( 0.17, 0.0, 0.3 );
 
    float multiplier = getMultiplier(objPath);
    corner1 = corner1 * multiplier;
    corner2 = corner2 * multiplier;
    FootPrintLocatorDrawOverride *nonConstThis = (FootPrintLocatorDrawOverride *)this;
    nonConstThis->mCurrentBoundingBox.clear();
    nonConstThis->mCurrentBoundingBox.expand( corner1 );
    nonConstThis->mCurrentBoundingBox.expand( corner2 );
    return mCurrentBoundingBox;
}
bool FootPrintLocatorDrawOverride::disableInternalBoundingBoxDraw() const
{
    return false;
}
MUserData* FootPrintLocatorDrawOverride::prepareForDraw(
 
{
    
    FootPrintLocatorData* data = dynamic_cast<FootPrintLocatorData*>(oldData);
    if (!data)
    {
        data = new FootPrintLocatorData();
    }
    float fMultiplier = getMultiplier(objPath);
    data->fSoleLineList.clear();
    for (int i = 0; i < soleCount; i++)
    {
        data->fSoleLineList.append(sole[i][0] * fMultiplier, sole[i][1] * fMultiplier, sole[i][2] * fMultiplier);
    }
    data->fHeelLineList.clear();
    for (int i = 0; i < heelCount; i++)
    {
        data->fHeelLineList.append(heel[i][0] * fMultiplier, heel[i][1] * fMultiplier, heel[i][2] * fMultiplier);
    }
    data->fSoleTriangleList.clear();    
    for (int i = 1; i <= soleCount - 2; i++)
    {
        data->fSoleTriangleList.append(sole[0][0] * fMultiplier, sole[0][1] * fMultiplier, sole[0][2] * fMultiplier);
        data->fSoleTriangleList.append(sole[i][0] * fMultiplier, sole[i][1] * fMultiplier, sole[i][2] * fMultiplier);
        data->fSoleTriangleList.append(sole[i+1][0] * fMultiplier, sole[i+1][1] * fMultiplier, sole[i+1][2] * fMultiplier);
    }
    data->fHeelTriangleList.clear();    
    for (int i = 1; i <= heelCount - 2; i++)
    {
        data->fHeelTriangleList.append(heel[0][0] * fMultiplier, heel[0][1] * fMultiplier, heel[0][2] * fMultiplier);
        data->fHeelTriangleList.append(heel[i][0] * fMultiplier, heel[i][1] * fMultiplier, heel[i][2] * fMultiplier);
        data->fHeelTriangleList.append(heel[i+1][0] * fMultiplier, heel[i+1][1] * fMultiplier, heel[i+1][2] * fMultiplier);
    }
    
    return data;
}
void FootPrintLocatorDrawOverride::addUIDrawables(
{
    FootPrintLocatorData* pLocatorData = (FootPrintLocatorData*)data;
    
    drawManager.
setColor( pLocatorData->fColor );
    }
    
    MColor textColor( 0.1f, 0.8f, 0.8f, 1.0f ); 
 
}
{ 
    MFnPlugin plugin(obj, PLUGIN_COMPANY, 
"3.0", 
"Any");
 
    status = plugin.registerNode("footPrintLocator", 
                                 footPrintLocator::id, 
                                 &footPrintLocator::creator, 
                                 &footPrintLocator::initialize,
                                 &footPrintLocator::drawDbClassification
                                 );
    if (!status) {
        status.
perror(
"registerNode");
        return status;
    }
        footPrintLocator::drawDbClassification,
        footPrintLocator::drawRegistrantId,
        FootPrintLocatorDrawOverride::Creator);
    if (!status) {
        status.
perror(
"registerDrawOverrideCreator");
        return status;
    }
    
    
    status = plugin.registerNode("footPrintLocatorManip", 
                                 footPrintLocatorManip::id, 
                                 &footPrintLocatorManip::creator, 
                                 &footPrintLocatorManip::initialize,
    if (!status) {
        status.
perror(
"registerNode");
        return status;
    }
    return status;
}
{
    status = plugin.deregisterNode(footPrintLocator::id);
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
        footPrintLocator::drawDbClassification,
        footPrintLocator::drawRegistrantId);
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    status = plugin.deregisterNode(footPrintLocatorManip::id);
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    return status;
}