#define _MApiVersion
#include <maya/MCursor.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnMesh.h>
#include <maya/MGlobal.h>
#include <maya/MIOStream.h>
#include <maya/MItMeshPolygon.h>
#include <maya/MItMeshVertex.h>
#include <maya/MMatrix.h>
#include <maya/MPlug.h>
#include <maya/MPointArray.h>
#include <maya/MVector.h>
#include "meshRemapTool.h"
#include "meshMapUtils.h"
const double epsilon = 0.00001;
meshRemapTool::meshRemapTool()
{
    setTitleString ( "Mesh Remap Tool" );
    reset();
}
meshRemapTool::~meshRemapTool() {}
void* meshRemapTool::creator()
{
    return new meshRemapTool;
}
void meshRemapTool::toolOnSetup ( 
MEvent & )
 
{
    reset();
}
void meshRemapTool::reset()
{
    fNumSelectedPoints = 0;
    fSelectedPathSrc.clear();
    fSelectedComponentSrc.clear();
    fSelectVtxSrc.clear();
    fSelectedFaceSrc = -1;
    fSelectedPathDst.clear();
    fSelectedComponentDst.clear();
    fSelectVtxDst.clear();
    fSelectedFaceDst = -1;
    fCurrentHelpString = "Select 1st point on source mesh.";
    helpStateHasChanged();
}
{
    char buf[1024];
    
    
    
    
    
    selectionIt.getStrings( selections );
    
    
    if( selections.
length() == 0 )
 
    {
        
        
        
        if( fNumSelectedPoints == 0 || fNumSelectedPoints == 3 )
        {
            if (!selectionDag.isDone() && selectionDag.getDagPath(path) == 
MS::kSuccess)
 
            {
                
                {
                    selectionDag.next();
                    if (selectionDag.isDone())
                    {
                        
                        
                        if (fNumSelectedPoints == 3)
                        {
                            return checkForHistory(path);
                        }
                    }
                }
            }
        }
        
        
        if( fNumSelectedPoints == 0 )
        {
            if (!selectionDag.isDone() && selectionDag.getDagPath(path) == 
MS::kSuccess)
 
            {
                
                {
                    selectionDag.next();
                    if (!selectionDag.isDone() &&
                    {
                        
                        {
                            selectionDag.next();
                            
                            if (selectionDag.isDone())
                            {
                                
                                
                                return checkForHistory(path);
                            }
                        }
                    }
                }
            }
        }
    }
    if( selections.
length() != 1 )
 
    {
    }
    if (selectionIt.isDone ())
    {
    }
    {
    }
    {
    }
    
    
    if ((fNumSelectedPoints == 3) && (checkForHistory(path) != 
MS::kSuccess))
 
    {
    }
    {
    }
    if (fIt.count() != 1 )
    {
        sprintf(buf, "Invalid selection '%s'. Vertices must be picked one at a time.", selections[0].asChar() );
    }
    else
    {
        sprintf(buf, "Accepting vertex '%s'", selections[0].asChar() );
    }
    
    
    
    
    if( fNumSelectedPoints < 3 )
    {
        fSelectedPathSrc.append( path );
        fSelectedComponentSrc.append( component );
    }
    else 
    {
        fSelectedPathDst.append( path );
        fSelectedComponentDst.append( component );
    }
    
    
    
    
    if( fNumSelectedPoints == 2 )
    {
        if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathSrc, fSelectedComponentSrc, &fSelectedFaceSrc, &fSelectVtxSrc ) ) != 
MStatus::kSuccess )
 
        {
            reset();
            return stat;
        }
    }
    
    
    
    if( fNumSelectedPoints == 5 )
    {
        if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathDst, fSelectedComponentDst, &fSelectedFaceDst, &fSelectVtxDst ) ) != 
MStatus::kSuccess )
 
        {
            reset();
            return stat;
        }
        executeCmd();
    }
    else
    {
        
        
        
        fNumSelectedPoints++;   
    }
    helpStateHasChanged();
    return stat;
}
{
    MPlug   historyPlug = meshFn.findPlug(
"inMesh", 
true);
 
    {
    }
}
MStatus meshRemapTool::resolveMapping()
 
{
    
    if( fSelectionList.length() != 2)
    {
        reset();
        helpStateHasChanged();
    }
    {
    }
    
    fSelectedPathSrc.append(dagPath);
    fSelectedPathSrc.append(dagPath);
    fSelectedPathSrc.append(dagPath);
    {
    }
    
    fSelectedPathDst.append(dagPath);
    fSelectedPathDst.append(dagPath);
    fSelectedPathDst.append(dagPath);
    
    unsigned srcFaceId = faceIterSrc.index();
    faceIterSrc.getVertices(srcVertIds);
    
    unsigned i, j;
    MMatrix m = fSelectedPathDst[0].inclusiveMatrix();
 
    for(i = 0; i < srcPts.
length(); i++)
 
    {
        srcPts[i] = srcPts[i] * m;
    }
    while (!faceIterDst.isDone())
    {
        if (arePointsOverlap(srcPts, dstPts))
        {
            
            fSelectedFaceSrc = srcFaceId;
            fSelectedFaceDst = faceIterDst.index();
            fSelectVtxSrc.
append(srcVertIds[0]);
            fSelectVtxSrc.append(srcVertIds[1]);
            fSelectVtxSrc.append(srcVertIds[2]);
            faceIterDst.getVertices(dstVertIds);
            for (j = 0; j < dstPts.
length(); j++)
 
            {
                if (v * v < epsilon)
                {
                    fSelectVtxDst.
append(dstVertIds[j]);
                    break;
                }
            }
            for (j = 0; j < dstPts.
length(); j++)
 
            {
                if (v * v < epsilon)
                {
                    fSelectVtxDst.
append(dstVertIds[j]);
                    break;
                }
            }
            for (j = 0; j < dstPts.
length(); j++)
 
            {
                if (v * v < epsilon)
                {
                    fSelectVtxDst.
append(dstVertIds[j]);
                    break;
                }
            }
        }
        faceIterDst.next();
    }
}
{
    unsigned i, j;
    for(i = 0; i < 3; i++) 
    {
        bool overlap = false;
        for(j = 0; j < dstPts.
length(); j++) 
 
        {
            if (v * v < epsilon)
            {
                overlap = true;
                break;
            }
        }
        if (!overlap) return false;
    }
    return true;
}
void meshRemapTool::completeAction()
{
    {
        reset();
        return;
    }
    executeCmd();
}
void meshRemapTool::executeCmd()
{
    char cmdString[200];
    sprintf(cmdString, "meshRemap %s.vtx[%d] %s.vtx[%d] %s.vtx[%d] %s.vtx[%d] %s.vtx[%d] %s.vtx[%d]",
        fSelectedPathSrc[0].partialPathName().asChar(), fSelectVtxSrc[0],
        fSelectedPathSrc[1].partialPathName().asChar(), fSelectVtxSrc[1],
        fSelectedPathSrc[2].partialPathName().asChar(), fSelectVtxSrc[2],
        fSelectedPathDst[0].partialPathName().asChar(), fSelectVtxDst[0],
        fSelectedPathDst[1].partialPathName().asChar(), fSelectVtxDst[1],
        fSelectedPathDst[2].partialPathName().asChar(), fSelectVtxDst[2]);
    if (st)
    {
    }
    reset();
}
void meshRemapTool::helpStateHasChanged()
{
    switch (fNumSelectedPoints)
    {
        case 0:
         fCurrentHelpString = "For auto remap select source mesh and then destination mesh and Press Enter. For manual remap select 1st vertex on source mesh.";
         break;
        case 1:
         fCurrentHelpString = "Select 2nd vertex on source mesh.";
         break;
        case 2:
         fCurrentHelpString = "Select 3rd vertex on source mesh.";
         break;
        case 3:
         fCurrentHelpString = "Select 1st vertex on target mesh.";
         break;
        case 4:
         fCurrentHelpString = "Select 2nd vertex on target mesh.";
         break;
        case 5:
         fCurrentHelpString = "Select 3rd vertex on target mesh.";
         break;
        default:
         
         break;
     }
    setHelpString( fCurrentHelpString );
}
{
    return new meshRemapTool;
}
void* meshRemapContextCmd::creator()
{
    return new meshRemapContextCmd;
}