#include "lineManipContainer.h"
#include <maya/MHardwareRenderer.h>
#include <maya/MIOStream.h>
#include <maya/MMatrix.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <maya/MFnTransform.h>
#include <maya/MGlobal.h>
#include <maya/MFnCamera.h>
#include <maya/MTemplateManipulator.h>
MTypeId lineManipContainer::id( 0x8104A );
 
class lineGeometry
{
public:
    static MPoint topPoint( 
bool rightLine = 
true ) {
 
        if ( rightLine )
            return MPoint( 1.0f, 1.0f, 0.0f );
 
        return MPoint( -1.0f, 1.0f, 0.0f );
 
    }
    static MPoint bottomPoint( 
bool rightLine = 
true ) {
 
        if ( rightLine )
            return MPoint( 1.0f, -1.0f, 0.0f );
 
        return MPoint( -1.0f, -1.0f, 0.0f );
 
    }
        return MPoint( 2.0f, -1.0f, 0.0f );
 
    }
};
lineManip::lineManip()
{
    
    
    MPoint pointOnPlane(lineGeometry::topPoint());
 
    
                    (
MVector(lineGeometry::otherPoint()) - 
MVector(lineGeometry::bottomPoint()));
    
    plane.setPlane( pointOnPlane, normalToPlane );
    
    affectScale = affectTranslate = false;
}
lineManip::~lineManip()
{
    
}
void lineManip::preDrawUI( 
const M3dView &view )
 
{
    
    fDrawManip = true;
    
    const char *nameBuffer = viewCamera.name().asChar();
    if ( 0 == nameBuffer )
        fDrawManip = false;
    if ( ( 0 == strstr(nameBuffer,"persp") ) && ( 0 == strstr(nameBuffer,"front") ) )
        fDrawManip = false;
    if ( !fDrawManip )
        return;
    
    
    
    float top[4], bottom[4];
    getManipLinePos(top, bottom);
}
{
    if(!fDrawManip)
        return;
    setHandleColor(drawManager, lineName, mainColor());
    drawManager.
line(fLineStart, fLineEnd);
}
{
    if ( 0 == gGLFT )
    
    const char *nameBuffer = viewCamera.name().asChar();
    if ( 0 == nameBuffer )
        return;
    if ( ( 0 == strstr(nameBuffer,"persp") ) && ( 0 == strstr(nameBuffer,"front") ) )
        return;
    
    
    
    float top[4],bottom[4];
    getManipLinePos(top, bottom);
    
    
    MGLuint glPickableItem;
    glFirstHandle( glPickableItem );
    
    lineName = glPickableItem;
    
    
    colorAndName( view, glPickableItem, true, mainColor() );
    gGLFT->
glBegin( MGL_LINES );
        gGLFT->
glVertex3fv( top );
        gGLFT->glVertex3fv( bottom );
    
}
{
    
    
    updateDragInformation();
}
{
    updateDragInformation();
}
{
    
    
    {
            iter.getDependNode( node );
        {
            if ( affectScale )
            {
                double newScale[3];
                newScale[0] = mousePointGlName.x + 1;
                newScale[1] = mousePointGlName.y + 1;
                newScale[2] = mousePointGlName.z + 1;
                xform.setScale( newScale );
            }
            if ( affectTranslate )
            {
                double newTranslate[3];
                newTranslate[0] = mousePointGlName.x;
                newTranslate[1] = mousePointGlName.y;
                newTranslate[2] = mousePointGlName.z;
            }
        }
    }
}
 
MStatus lineManip::updateDragInformation()
 
{
    
    if ( 
MS::kFailure == mouseRay( localMousePoint, localMouseDirection) )
 
    
    
    MPoint mouseIntersectionWithManipPlane;
 
    if ( ! plane.intersect( localMousePoint, localMouseDirection,   mouseIntersectionWithManipPlane ) )
    mousePointGlName = mouseIntersectionWithManipPlane;
    MGLuint active = 0;
    if ( glActiveName( active ) )
    {
        float start[4] = {0,0,0,0},end[4] = {0,0,0,0};
        if ( active == lineName )
        {
            
            bool rightLine = true;
            if ( affectTranslate )
                    rightLine = false;
            lineGeometry::topPoint(rightLine).
get(start);
            lineGeometry::bottomPoint(rightLine).get(end);
        }
        if ( active != 0 )
        {
            lineMath line;
            
            MPoint a( start[0], start[1], start[2] );
 
            MPoint b( end[0], end[1], end[2] );
 
            
            line.setLine( start, vab );
            
            
            if ( line.closestPoint( mousePointGlName, cpt ) )
            {
                mousePointGlName.
x -= cpt.
x;
                mousePointGlName.y -= cpt.
y;
                mousePointGlName.z -= cpt.
z;
            }
        }
    }
}
void lineManip::getManipLinePos(float* top, float* bottom)
{
    bool rightLine = true;
    if ( affectTranslate )
        rightLine = false;
    lineGeometry::topPoint(rightLine).get(top);
    lineGeometry::bottomPoint(rightLine).get(bottom);
    
    
    
    MGLuint active = 0;
    if(glActiveName(active))
    {
        if(active && active == lineName)
        {
            top[0] += (float) mousePointGlName.x; 
            top[1] += (float) mousePointGlName.y; 
            top[2] += (float) mousePointGlName.z;
            bottom[0] += (float) mousePointGlName.x; 
            bottom[1] += (float) mousePointGlName.y; 
            bottom[2] += (float) mousePointGlName.z;
        }
    }
}
lineManipContainer::lineManipContainer() 
{ 
    
}
lineManipContainer::~lineManipContainer() 
{
    
}
MStatus lineManipContainer::createChildren()
 
{
    MString manipTypeName(
"singleLineManip");
 
    MString manipName(
"rightLineManip");
 
    status = addMPxManipulatorNode( manipTypeName, manipName, proxyManip );
    if ( !status )
    {
    }
    lineManip *rightManipPtr = (lineManip *) proxyManip;
    if ( rightManipPtr )
    {
        rightManipPtr->affectScale = true;
    }
    proxyManip = 0;
    manipTypeName = "singleLineManip";
    manipName = "leftLineManip";
    status = addMPxManipulatorNode( manipTypeName, manipName, proxyManip );
    if ( !status )
    {
    }
    lineManip *leftManipPtr = (lineManip *) proxyManip;
    if ( leftManipPtr )
    {
        leftManipPtr->affectTranslate = true;
    }
    return status;
}
{
    
}
{
    MPoint textPos = nodeTranslation();
 
    drawManager.
text(textPos, 
MString( 
"Two custom line manipulators"));
}
void lineManipContainer::draw(
M3dView & view, 
 
{ 
    
    MPoint textPos = nodeTranslation();
 
    MString str( 
"Two custom line manipulators"); 
 
    MString distanceText(str.asChar());
 
    
}
MVector lineManipContainer::nodeTranslation()
 const 
{
}
class lineManipContainerContext;
char contextName[] = "lineManipContainerContext";
char manipulatorContainerNodeName[] = "lineManipContainer";
class lineManipContainerContext : 
        MFn::kTransform, lineManipContainer, manipulatorContainerNodeName >
{
public:
    lineManipContainerContext() {}
    virtual ~lineManipContainerContext() {}
    {
        namesOfAttributes.
append(
"scaleX");
        namesOfAttributes.
append(
"translateX");
    }
};
class lineManipContainerContextCommand;
char contextCommandName[] = "lineManipContainerContext";
class lineManipContainerContextCommand : 
{
public:
    lineManipContainerContextCommand() {}
    virtual ~lineManipContainerContextCommand() {}
};
static lineManipContainerContextCommand _lineManipContainerContextCommand;
void* lineManip::creator()
{
    return new lineManip();
}
{
}
void* lineManipContainer::creator()
{
     return new lineManipContainer();
}
MStatus lineManipContainer::initialize()
 
{ 
    return status;
}
{ 
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"2009", 
"Any");
 
    status = plugin.registerNode( "singleLineManip", lineManip::id, lineManip::creator,
    if (!status) 
    {
        status.
perror(
"registerNode");
        return status;
    }
    status = plugin.registerNode( manipulatorContainerNodeName, lineManipContainer::id, lineManipContainer::creator,
    if (!status) 
    {
        status.
perror(
"registerNode");
        return status;
    }
    status = _lineManipContainerContextCommand.registerContextCommand( obj );
    if (!status) 
    {
        status.
perror(
"registerContextCommand");
        return status;
    }
    return status;
}
{
    status = plugin.deregisterNode( lineManip::id );
    if (!status) 
    {
        status.
perror(
"deregisterNode");
        return status;
    }
    status = plugin.deregisterNode(lineManipContainer::id);;
    if (!status) 
    {
        status.
perror(
"deregisterNode");
        return status;
    }
    status = _lineManipContainerContextCommand.deregisterContextCommand( obj );
    if (!status) 
    {
        status.
perror(
"deregisterContextCommand");
        return status;
    }
    return status;
}