closestPointOnCurveCmd.cpp
#include "closestPointOnCurveCmd.h"
#include "closestTangentUAndDistance.h"
#include "closestPointOnCurveStrings.h"
closestPointOnCurveCommand::closestPointOnCurveCommand()
{
}
closestPointOnCurveCommand::~closestPointOnCurveCommand()
{
}
void *closestPointOnCurveCommand::creator()
{
   return new closestPointOnCurveCommand;
}
MSyntax closestPointOnCurveCommand::newSyntax()
{
   MSyntax syntax;
   
   syntax.addFlag("-na", "-name", MSyntax::kString);
   syntax.addFlag("-ip", "-inPosition", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble);
   
   syntax.addFlag("-p", "-position");
   syntax.addFlag("-nr", "-normal");
   syntax.addFlag("-t", "-tangent");
   syntax.addFlag("-u", "-paramU");
   syntax.addFlag("-d", "-distance");
   
   syntax.useSelectionAsDefault(true);
   syntax.setObjectType(MSyntax::kSelectionList, 1, 1);
   
   syntax.enableQuery(true);
   syntax.enableEdit(false);
   return syntax;
}
bool closestPointOnCurveCommand::isUndoable() const
{
   return true;
}
MStatus closestPointOnCurveCommand::doIt(const MArgList& args)
{
   
   MArgDatabase argData(syntax(), args);
   
   queryFlagSet = argData.isQuery();
   inPositionFlagSet = argData.isFlagSet("inPosition");
   positionFlagSet = argData.isFlagSet("-position");
   normalFlagSet = argData.isFlagSet("-normal");
   tangentFlagSet = argData.isFlagSet("-tangent");
   paramUFlagSet = argData.isFlagSet("-paramU");
   distanceFlagSet = argData.isFlagSet("-distance");
   
   if (argData.isFlagSet("-name"))
      argData.getFlagArgument("-name", 0, closestPointOnCurveNodeName);
   else
      closestPointOnCurveNodeName = "";
   
   if (inPositionFlagSet)
   {
      argData.getFlagArgument("-inPosition", 0, inPosition.x);
      argData.getFlagArgument("-inPosition", 1, inPosition.y);
      argData.getFlagArgument("-inPosition", 2, inPosition.z);
   }
   else
   {
      inPosition.x = 0.0;
      inPosition.y = 0.0;
      inPosition.z = 0.0;
   }
   
   argData.getObjects(sList);
   return redoIt();
}
MStatus closestPointOnCurveCommand::redoIt()
{
   
   if (sList.length() == 0)
   {
           MStatus stat;
           MString msg = MStringResource::getString(kNoValidObject, stat);
       displayError(msg);
       return MStatus::kFailure;
   }
   
   MDagPath curveDagPath;
   sList.getDagPath(0, curveDagPath);
   
   if (!curveDagPath.node().hasFn(MFn::kNurbsCurve) && !(curveDagPath.node().hasFn(MFn::kTransform) && curveDagPath.hasFn(MFn::kNurbsCurve)))
   {
           MStatus stat;
           MString msg; 
           
           MString msgFmt = MStringResource::getString(kInvalidType, stat);
           MStringArray selectionStrings;
           sList.getSelectionStrings(0, selectionStrings);
           msg.format(msgFmt, selectionStrings[0]);
           displayError(msg);
       return MStatus::kFailure;
   }
   
   if (!queryFlagSet)
   {
      
      MFnDependencyNode depNodeFn;
      if (closestPointOnCurveNodeName == "")
         depNodeFn.create("closestPointOnCurve");
      else
         depNodeFn.create("closestPointOnCurve", closestPointOnCurveNodeName);
      closestPointOnCurveNodeName = depNodeFn.name();
      
      if (inPositionFlagSet)
      {
         MPlug inPositionXPlug = depNodeFn.findPlug("inPositionX");
         inPositionXPlug.setValue(inPosition.x);
         MPlug inPositionYPlug = depNodeFn.findPlug("inPositionY");
         inPositionYPlug.setValue(inPosition.y);
         MPlug inPositionZPlug = depNodeFn.findPlug("inPositionZ");
         inPositionZPlug.setValue(inPosition.z);
      }
      
      unsigned instanceNumber=0;
      if (curveDagPath.node().hasFn(MFn::kTransform))
      {
         
         curveDagPath.extendToShape();
         
         instanceNumber = curveDagPath.instanceNumber();
      }
      
      MPlug worldCurvePlug, inCurvePlug;
      inCurvePlug = depNodeFn.findPlug("inCurve");
      depNodeFn.setObject(curveDagPath.node());
      worldCurvePlug = depNodeFn.findPlug("worldSpace");
      worldCurvePlug = worldCurvePlug.elementByLogicalIndex(instanceNumber);
      MDGModifier dgModifier;
      dgModifier.connect(worldCurvePlug, inCurvePlug);
      dgModifier.doIt();
      
      setResult(closestPointOnCurveNodeName);
      return MStatus::kSuccess;
   }
   
   else
   {
      
      MPoint position;
      MVector normal, tangent;
      double paramU, distance;
      closestTangentUAndDistance(curveDagPath, inPosition, position, normal, tangent, paramU, distance);
      
      if (!positionFlagSet && !normalFlagSet && !tangentFlagSet && !paramUFlagSet && !distanceFlagSet)
      {
                  MStatus stat;
                  MString msg = MStringResource::getString(kNoQueryFlag, stat);
                  displayError(msg);
          return MStatus::kFailure;
     }
      
      else if (distanceFlagSet && !(positionFlagSet || normalFlagSet || tangentFlagSet || paramUFlagSet))
         setResult(distance);
      
      else if (paramUFlagSet && !(positionFlagSet || normalFlagSet || tangentFlagSet || distanceFlagSet))
         setResult(paramU);
      
      else
      {
         
         MDoubleArray floatArrayResult;
         
         if (positionFlagSet)
         {
            floatArrayResult.append(position.x);
            floatArrayResult.append(position.y);
            floatArrayResult.append(position.z);
         }
         if (normalFlagSet)
         {
            floatArrayResult.append(normal.x);
            floatArrayResult.append(normal.y);
            floatArrayResult.append(normal.z);
         }
         if (tangentFlagSet)
         {
            floatArrayResult.append(tangent.x);
            floatArrayResult.append(tangent.y);
            floatArrayResult.append(tangent.z);
         }
         if (paramUFlagSet)
            floatArrayResult.append(paramU);
         if (distanceFlagSet)
            floatArrayResult.append(distance);
         
         setResult(floatArrayResult);
      }
      return MStatus::kSuccess;
   }
}
MStatus closestPointOnCurveCommand::undoIt()
{
   
   if (!queryFlagSet)
   {
      MString deleteCmd = "delete ";
      deleteCmd += closestPointOnCurveNodeName;
      MGlobal::executeCommand(deleteCmd);
   }
   return MStatus::kSuccess;
}