////////////////////////////////////////////////////////////////////////
//
// Description:
//    Rotate the rotateDiscDragger based on mouse motion.
//
// Use: private
//
void
SoRotateDiscDragger::drag()
//
////////////////////////////////////////////////////////////////////////
{
    // Set up the projector space and view.
    // Working space is space at end of motion matrix.
	planeProj->setViewVolume( getViewVolume() );    
	planeProj->setWorkingSpace( getLocalToWorldMatrix() );

    // Get newHitPt and startHitPt in workspace.
	SbVec3f newHitPt 
	    = planeProj->project( getNormalizedLocaterPosition()); 
	SbVec3f startHitPt = getLocalStartingPoint();

    // Find the amount of rotation
    SbVec3f oldVec = startHitPt;
    SbVec3f newVec = newHitPt;
    // Remove the part of these vectors that is parallel to the normal
    oldVec -= SbVec3f( 0, 0, oldVec[2] );
    newVec -= SbVec3f( 0, 0, newVec[2] );

    // deltaRot is how much we rotated since the mouse button went down.
    SbRotation deltaRot = SbRotation( oldVec, newVec );
	
    // Append this to the startMotionMatrix, which we saved at the beginning
    // of the drag, to find the current motion matrix.
	setMotionMatrix( 
	    appendRotation( getStartMotionMatrix(), deltaRot, SbVec3f(0,0,0)));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
//    Stretch the dragger according to the motion along the plane
//    projector
//
// Use: private
//
void
SoTranslate2Dragger::drag()
//
////////////////////////////////////////////////////////////////////////
{
    // Set up the projector space and view.
    // Working space is space at end of motion matrix.
	planeProj->setViewVolume( getViewVolume() );    
	planeProj->setWorkingSpace( getLocalToWorldMatrix() );

    // Get newHitPt and startHitPt in workspace.
	SbVec3f newHitPt = planeProj->project( getNormalizedLocaterPosition()); 
	SbVec3f startHitPt = getLocalStartingPoint();

    // Convert newHitPt to world space and save this as our new worldRestartPt
	getLocalToWorldMatrix().multVecMatrix( newHitPt, worldRestartPt );

    // Figure out the translation relative to start position.
        SbVec3f motion = newHitPt - startHitPt;

    // Maybe we need to constrain the motion...
    if ( !shftDown )
	translateDir = -1;
    else {
	// The shift key is pressed. This means 1-D translation.
	if ( translateDir == -1 ) {
	    // The 1-D direction is not defined. Calculate it based on which
	    // direction got the maximum locater motion.
            if ( isAdequateConstraintMotion() ) {
		if ( fabs( motion[0]) > fabs( motion[1]))
		    translateDir = 0;
		else 
		    translateDir = 1;

		// Set the axis feedback switch to the given direction.
		setSwitchValue( axisFeedbackSwitch.getValue(), translateDir );
	    }
	    else {
		// Not ready to pick a direction yet. Don't move.
		return;
	    }
	}
	// get the projection of 'motion' onto the preferred axis.
	SbVec3f constrainedMotion(0,0,0);
	constrainedMotion[translateDir] = motion[translateDir];
	motion = constrainedMotion;
    }

    // Append this to the startMotionMatrix, which we saved at the beginning
    // of the drag, to find the current motion matrix.
	setMotionMatrix( appendTranslation( getStartMotionMatrix(), motion ) );
}
void TranslateRadialDragger::
drag()
{
  // Things can change between renderings. To be safe, update
  // the projector with the current values.
  lineProj->setViewVolume(getViewVolume());
  lineProj->setWorkingSpace(getLocalToWorldMatrix());

  // Find the new intersection on the projector.
  SbVec3f newHitPt
    = lineProj->project(getNormalizedLocaterPosition());

  // Get initial point expressed in our current local space.
  SbVec3f startHitPt = getLocalStartingPoint();

  // Motion in local space is difference between old and
  // new positions.
  SbVec3f motion = newHitPt - startHitPt;

  // Append this to the startMotionMatrix, which was saved
  // automatically at the beginning of the drag, to find
  // the current motion matrix.
  setMotionMatrix( appendTranslation(getStartMotionMatrix(), motion));
}