#include <maya/MIOStream.h>
#include <stdio.h>
#include <stdlib.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/MFeedbackLine.h>
#define CHECKRESULT(stat,msg)     \
    if ( MS::kSuccess != stat ) { \
        cerr << msg << endl;      \
    }
#define kVectorEpsilon 1.0e-3
#define     MOVENAME    "moveNumericToolCmd"
#define     DOIT        0
#define     UNDOIT      1
#define     REDOIT      2
{
public:
    moveCmd();
    virtual ~moveCmd(); 
    
public:
    static void*    creator();
    void            setVector( double x, double y, double z );
private:
};
moveCmd::moveCmd( )
{
    setCommandString( MOVENAME );
}
moveCmd::~moveCmd()
{}
void* moveCmd::creator()
{
    return new moveCmd;
}
bool moveCmd::isUndoable() const
{
    return true;
}
void moveCmd::setVector( double x, double y, double z)
{
    delta.x = x;
    delta.y = y;
    delta.z = z;
}
{
    
    
    else
        vec = transFn.translation( spc, &stat );
    }
    return stat;
}
{
    command.
addArg( commandString() );
    
    
    
}
{
    unsigned i = 0;
    {
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;
        case 0:
        default:
            break;
    }
    delta = vector;
    return action( DOIT );
}
{
    return action( UNDOIT );
}
{
    return action( REDOIT );
}
MStatus moveCmd::action( 
int flag )
 
{
    switch( flag )
    {
        case UNDOIT:    
            break;
        case REDOIT:    
            break;
        case DOIT:      
            break;
        default:
            break;
    }
    
    
    
    
    else
        stat = transFn.translateBy( vector, spc );
        CHECKRESULT(stat,"Error doing translate on transform");
    }
}
#define     MOVEHELPSTR        "drag to move selected object"
#define     MOVETITLESTR       "moveNumericTool"
#define     TOP         0
#define     FRONT       1
#define     SIDE        2
#define     PERSP       3
{
public:
    moveNumericContext();
                                               bool isAbsolute );
private:
    int currWin;
    short startPos_x, endPos_x, start_x, last_x;
    short startPos_y, endPos_y, start_y, last_y;
    moveCmd * cmd;
};
moveNumericContext::moveNumericContext()
{
    setTitleString( str );
    
    
}
void moveNumericContext::toolOnSetup( 
MEvent & )
 
{
    setHelpString( str );
}
{
    
    
    
    if ( !isSelecting() ) {
        event.getPosition( startPos_x, startPos_y );
        stat = view.getCamera( camera );
            cerr << "Error: M3dView::getCamera" << endl;
            return stat;
        }
        MVector upDir = fnCamera.upDirection( spc );
 
        MVector rightDir = fnCamera.rightDirection( spc );
 
        
        
        if ( fnCamera.isOrtho() ) {
                currWin = TOP;
                currWin = FRONT;
            } else  {
                currWin = SIDE;
            }
        }
        else {
            currWin = PERSP;
        }
        
        
        cmd = (moveCmd*)newToolCommand();
        cmd->setVector( 0.0, 0.0, 0.0 );
    }
    feedbackNumericalInput();
    return stat;
}
{
    
    
    
    if ( !isSelecting() ) {
        event.getPosition( endPos_x, endPos_y );
        view.viewToWorld( startPos_x, startPos_y, startW, vec );
        view.viewToWorld( endPos_x, endPos_y, endW, vec );
        downButton = event.mouseButton();
        
        
        
        cmd->undoIt();
        switch( currWin )
        {
            case TOP:
                switch ( downButton )
                {
                        cmd->setVector( endW.
x - startW.
x, 0.0, 0.0 );
                        break;
                    default:
                        cmd->setVector( endW.
x - startW.
x, 0.0,
                        break;
                }
                break;  
            case FRONT:
                switch ( downButton )
                {
                        cmd->setVector( endW.
x - startW.
x, 0.0, 0.0 );
                        break;
                    default:
                        cmd->setVector( endW.
x - startW.
x,
                                        endW.
y - startW.
y, 0.0 );
                        break;
                }
                break;  
            case SIDE:
                switch ( downButton )
                {
                        cmd->setVector( 0.0, 0.0, endW.
z - startW.
z );
                        break;
                    default:
                        cmd->setVector( 0.0, endW.
y - startW.
y,
                        break;
                }
                break;  
            case PERSP:
                break;
        }
        stat = cmd->redoIt();
        view.refresh( true );
    }
    feedbackNumericalInput();
    return stat;
}
{
    if ( !isSelecting() ) {
        event.getPosition( endPos_x, endPos_y );
        
        
        
        
        if (abs(startPos_x - endPos_x) < 2 && abs(startPos_y - endPos_y) < 2) {
            delete cmd;
            view.refresh( true );
        }
        else {
            stat = cmd->finalize();
            view.refresh( true );
        }
    }
    feedbackNumericalInput();
    return stat;
}
{
    return setHelpString( str );
}
bool moveNumericContext::processNumericalInput ( 
const MDoubleArray &values,
 
                                                 bool isAbsolute )
{
    unsigned valueLength = values.
length();
 
    cmd = (moveCmd *) newToolCommand();
     moveCmd::getVector(vec);
    if (isAbsolute) {
        if (ignoreEntry(flags, 0) || (valueLength < 1)) absoluteDelta.
x = 0;
 
        else absoluteDelta.
x = values[0] - vec.
x;
 
        if (ignoreEntry(flags, 1) || (valueLength < 2)) absoluteDelta.
y = 0;
 
        else absoluteDelta.
y = values[1] - vec.
y;
 
        if (ignoreEntry(flags, 2) || (valueLength < 3)) absoluteDelta.
z = 0;
 
        else absoluteDelta.
z = values[2] - vec.
z;
 
        cmd->setVector(absoluteDelta.
x, absoluteDelta.
y, absoluteDelta.
z);
    }
    else {
        if (ignoreEntry(flags, 0) || (valueLength < 1)) relativeDelta.
x = 0;
 
        else relativeDelta.
x = values[0];
 
        if (ignoreEntry(flags, 1) || (valueLength < 2)) relativeDelta.
y = 0;
 
        else relativeDelta.
y = values[1];
 
        if (ignoreEntry(flags, 2) || (valueLength < 3)) relativeDelta.
z = 0;
 
        else relativeDelta.
z = values[2];
 
        cmd->setVector(relativeDelta.
x, relativeDelta.
y, relativeDelta.
z);
    }
    cmd->redoIt();
    cmd->finalize();
    feedbackNumericalInput();
    return true;
}
bool moveNumericContext::feedbackNumericalInput() const
{
     moveCmd::getVector(vec);
    return true;
}
const
{
}
#define     CREATE_CTX_NAME "moveNumericToolContext"
{
public:
    moveNumericContextCommand() {};
public:
    static void* creator();
};
{
    return new moveNumericContext();
}
void * moveNumericContextCommand::creator()
{
    return new moveNumericContextCommand;
}
{
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"3.0", 
"Any" );
 
    status = plugin.registerContextCommand(CREATE_CTX_NAME,
                                           &moveNumericContextCommand::creator,
                                           MOVENAME, &moveCmd::creator);
    if (!status) {
        status.
perror(
"registerContextCommand");
        return status;
    }
    return status;
}
{
    status = plugin.deregisterContextCommand( CREATE_CTX_NAME, MOVENAME );
    if (!status) {
        status.
perror(
"deregisterContextCommand");
        return status;
    }
    return status;
}