/*****************************
File:      StickyDynamic.h
Language:   C++ (header)
Project:    H3DNetworkingUtils
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is H3DNetworkingUtils v1.0.

The Initial Developer of the Original Code is CSIRO.
Portions created by the Initial Developer are Copyright (C) 1009 CSIRO. All Rights Reserved.
Contributor(s):
    Chris Gunn  <Chris.Gunn@csiro.au> <ChrisJGunn@gmail.com>
***************************/

/// \file StickyDynamic.h
/// \brief Header file for StickyDynamic, a Dynamic that has 'stickyness'.

#ifndef StickyDynamic_H
#define StickyDynamic_H


#include "H3DNetworkingUtils/Config.h"
#include "H3DNetworkingUtils/Dynamic.h"
#include <H3D/X3DGeometryNode.h> // Can't see any reason to require this line but the is a compilation error without it.
#include <H3D/SFBool.h>
#include <H3D/SFFloat.h>
#include <H3D/SFTime.h>

namespace H3DNetworkingUtils {

/// \class StickyDynamic
/// The StickyDynamic class is a Dynamic that has three types of
/// stickiness:
///
///   (1) when the "locked" field is true, it will not move at all
///   (2) the "startForce" and "slideForce" fields set the minimum amount
///       of force necessary to start it moving and keep it moving
///       respectively
///   (3) a resisting force of magnitude "friction" * velocity is applied
///       when moving  \n
/// <b>Examples:</b>
///   - <a href="../../examples/StickyDynamicTest.x3d">StickyDynamicTest.x3d</a>

class H3D_NETWORKING_UTILS_DLL_SPEC StickyDynamic : public H3DNetworkingUtils::Dynamic {
public:
   /// Constructor
   StickyDynamic(H3D::Inst<H3D::SFBool> locked = 0,
                 H3D::Inst<H3D::SFFloat> startForce = 0,
                 H3D::Inst<H3D::SFFloat> slideForce = 0,
                 H3D::Inst<H3D::SFFloat> friction = 0,
					  H3D::Inst<H3D::SFTime> stopDelay = 0);
   
   // The X3D interface
   static H3D::H3DNodeDatabase database;

   // Public fields

   /// Stops movement
   /// access type: inputOutput \n
   /// basic type: SFBool \n
   /// default value: FALSE
   auto_ptr<H3D::SFBool> locked;

   /// Amount of force needed to start moving
   /// access type: inputOutput \n
   /// basic type: SFFloat \n
   /// default value: 40.0
   auto_ptr<H3D::SFFloat> startForce;

   /// Amount of force needed to keep moving
   /// access type: inputOutput \n
   /// basic type: SFFloat \n
   /// default value: 0.05
   auto_ptr<H3D::SFFloat> slideForce;

   /// Resistance to movement
   /// access type: inputOutput \n
   /// basic type: SFFloat \n
   /// default value: 50.0
   auto_ptr<H3D::SFFloat> friction;

   /// The time period that the StickyDynamic needs to be stopped before it is really treated as stopped \n
	/// We need this because, if we consider it stopped if the force on it is zero momentarily, it can
	/// produce jerky movement when pushing an object, as the haptic tool bounces on the surface.
   /// access type: inputOutput \n
   /// basic type: SFFloat \n
   /// default value: 0.2
   auto_ptr<H3D::SFTime> stopDelay;

protected:

   virtual void traverseSG(H3D::TraverseInfo & ti);

   virtual void stopIt();
   
   class FrictionForce : public H3D::TypedField<H3D::SFVec3f, H3D::Types<H3D::SFFloat, H3D::SFVec3f> > {
   public:
      virtual void update();
   };
   
   auto_ptr<FrictionForce> friction_force;
	bool stopped;
	H3D::H3DTime stop_time;
};

}

#endif

