//------------------------------------------------------------------------------
// File: client_cmddrag.cs
// This file contains the drag object group methods, which are responsible for
// rendering and updating the drag line
// Author: Matthew Rudge
//------------------------------------------------------------------------------

//-Constants and Globals--------------------------------------------------------
$CSD_DRAGOFFSET = 3;
$CSD_DRAGOBJECT = 0;
$DestinationObject = 0;
//------------------------------------------------------------------------------

//-Functions--------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Creates the drag group
////////////////////////////////////////////////////////////////////////////////
function csCreateDragGroup()
{
   if(!isObject(DragGroup)) {
      new SimGroup(DragGroup);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Destroys the drag group
////////////////////////////////////////////////////////////////////////////////
function csDestroyDragGroup()
{
   if(isObject(DragGroup)) {
      DragGroup.delete();
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets the drag line's start coordinates
//! \param %dragObj Object being dragged
//! \param %starty Y coordinate
////////////////////////////////////////////////////////////////////////////////
function csSetDragStart(%dragObj)
{
   $CSD_DRAGOBJECT = %dragObj;
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the drag line's start x coordinate
//! \retval int X coordinate
////////////////////////////////////////////////////////////////////////////////
function csGetDragStartX()
{
   return getWord($CSD_DRAGOBJECT.getPosition(), 0);
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the drag line's start y coordinate
//! \retval int Y coordinate
////////////////////////////////////////////////////////////////////////////////
function csGetDragStartY()
{
   return getWord($CSD_DRAGOBJECT.getPosition(), 1);
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the target of the drag operation (separate ray cast for collision 
//! only with the terrain
//! \retval point Point location
////////////////////////////////////////////////////////////////////////////////
function csGetDragTarget()
{
   PlayGui.pointRollover(
   $pointSelectionLength, 
   $TypeMasks::TerrainObjectType + $TypeMasks::CliffObjectType + $TypeMasks::WalkingObjectType
   );
   return (PlayGui.getPointRollover());
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the drag vector given a start and end coordinate
//! \param %startx Start x coordinate
//! \param %starty Start y coordinate
//! \param %endx End x coordinate
//! \param %endy End y coordinate
//! \retval vector Drag vector, from start to end coordinate
////////////////////////////////////////////////////////////////////////////////
function csGetDragVector(%startx, %starty, %endx, %endy)
{
   %xDrag = %endx - %startx;
   %yDrag = %endy - %starty;
   %vDrag = slgFormVector(%xDrag, %yDrag, "");
   return %vDrag;
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the drag object offset vector given the drag vector, its length,
//! and the desired offset
//! \param %vDrag Drag vector
//! \param %vDragLen Length of drag vector
//! \param %off Offset distance for drag object offset vector
//! \retval vector Drag object offset vector
////////////////////////////////////////////////////////////////////////////////
function csGetDragObjOffsetVector(%vDrag, %vDragLen, %off)
{
   // If the drag vector length is shorter than the offset length then there is
   // no drag line
   if(%vDragLen < %off) {
      return "";      
   }
   
   // Normalize drag vector and multiply by offset
   %vDragOff = VectorScale(VectorNormalize(%vDrag), %off);
   
   // Return offset vector
   return %vDragOff;
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the current drag group by adding or removing drag objects up to the
//! end point and by setting the position of all drag objects in the drag group
//! \param %startx Start x coordinate of drag line
//! \param %starty Start y coordinate of drag line
//! \param %endx End x coordinate of drag line
//! \param %endy End y coordinate of drag line
////////////////////////////////////////////////////////////////////////////////
function csUpdateDragGroup(%startx, %starty, %endx, %endy, %endz)
{
   if(!isObject(DragGroup)) {
      return;
   }
   
   // Get current drag object offset vector
   %vDrag    = csGetDragVector(%startx, %starty, %endx, %endy);
   %vDragLen = VectorLen(%vDrag);
   %vDragOff = csGetDragObjOffsetVector(%vDrag, %vDragLen, $CSD_DRAGOFFSET);
   if (%vDragOff $= "")
   {
      if (isObject($DestinationObject) == false)
      {
         $DestinationObject = new StaticShape()
         {
            dataBlock = DestinationFlagData;
         };
      }
      
      $DestinationObject.setPosition(%endx, %endy, %endz);
      csRemoveDragObjects(0);
      return;
   }
   
   // Keep track of current length, max length, current position
   %xPos = %startx;
   %yPos = %starty;
   %cLen = 0;
   %mLen = %vDragLen;
   
   // Get x and y offset from drag offset
   %xOff = getWord(%vDragOff, 0);
   %yOff = getWord(%vDragOff, 1);
   
   // For each drag object in group do
   %iObj = 0;
   %grpCnt = DragGroup.getCount();
   for (%iObj; %iObj < %grpCnt; %iObj++) {
      // If we've reached or exceeded max length of vector then exit loop
      if(%cLen + $CSD_DRAGOFFSET >= %mLen) {
         break;
      }
      
      // Update its position
      %dragObj = DragGroup.getObject(%iObj);
      %xPos += %xOff;
      %yPos += %yOff;
      %dragObj.setPosition(%xPos, %yPos);
      //%dragObj.setPosition(slgRound(%xPos), slgRound(%yPos));
   
      // Update current length on drag vector
      %cLen += $CSD_DRAGOFFSET;
   }
   
   // Add drag objects if needed
   %iObj += csAddDragObjects(%cLen, %mLen, %xPos, %yPos, %xOff, %yOff);
   $DestinationObject.setPosition(%endx, %endy, %endz);
   
   // Remove drag objects if needed
   csRemoveDragObjects(%iObj);
}

////////////////////////////////////////////////////////////////////////////////
//! Adds drag objects to the drag object group up to the end point and maximum
//! distance
//! \param %cLen Current length traveled along the drag line
//! \param %mLen Maximum length of drag line
//! \param %xPos Current x position on drag line
//! \param %yPos Current y position on drag line
//! \param %xOff X offset to move for next drag object in drag line
//! \param %yOff Y offset to move for next drag object in drag line
//! \retval int Number of objects added to the drag line
////////////////////////////////////////////////////////////////////////////////
function csAddDragObjects(%cLen, %mLen, %xPos, %yPos, %xOff, %yOff)
{
   %objCnt = 0;
   
   // Add new objects while true
   while(%cLen + $CSD_DRAGOFFSET < %mLen) {
      // Create new object
      %iObj = new StaticShape() {
         dataBlock = DragShapeData;
      };
      %objCnt++;
      
      // Set its position
      %xPos += %xOff;
      %yPos += %yOff;
      %iObj.setPosition(%xPos, %yPos, "");
      //%iObj.setPosition(slgRound(%xPos), slgRound(%yPos));
      
      // Add it to the drag group
      DragGroup.add(%iObj);
      
      // Update current length
      %cLen += $CSD_DRAGOFFSET;
   }
   
   if (isObject($DestinationObject) == false)
   {
      $DestinationObject = new StaticShape()
      {
         dataBlock = DestinationFlagData;
      };
   }
   
   return %objCnt;
}

////////////////////////////////////////////////////////////////////////////////
//! Removes extra objects (beyond the end point and maximum distance) from the 
//! drag group
//! \param %iObj First index of object to remove
////////////////////////////////////////////////////////////////////////////////
function csRemoveDragObjects(%iObj)
{
   while(%iObj < DragGroup.getCount()) {
      %dragObj = DragGroup.getObject(%iObj);
      DragGroup.remove(%dragObj);
      %dragObj.delete();
   }
}
//------------------------------------------------------------------------------

// End client_cmddrag.cs