/*****************************
File:      MouseHapticDevice.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 MouseHapticDevice.h
/// \brief Header file for MouseHapticDevice, makes the mouse look like a haptic device.

#ifndef MouseHapticDevice_H
#define MouseHapticDevice_H


#include "H3DNetworkingUtils/Config.h"
#include <H3D/FakeHapticsDevice.h>
#include "H3DNetworkingUtils/Config.h"
#include <H3D/SFNode.h>
#include <H3D/MouseSensor.h>
#include <H3D/SFVec3f.h>
#include <H3D/H3DNavigation.h>

namespace H3DNetworkingUtils {

/// \class MouseHapticDevice
/// The MouseHapticsDevice class provides an alternative interface to use on haptics 
/// programs when a haptic device is not available. It assigns mouse motion to haptic device position. 
/// Also assigns the mouse middle button to the haptic main button
/// This is useful to use when there is no haptic device available.
/// It is only active (ie only 'grabs' the proxy) when the mouse left button is pressed.
/// Assignments:
/// mouse right = +ve x
/// mouse left = -ve x
/// mouse up = +ve y
/// mouse down = -ve y
/// mouse up with right button pressed = -ve z (push away)
/// mouse down with right button pressed = +ve z (pull forward)
/// mouse middle button to haptic device main button
/// The node only works if a MouseSensor has been entered into the mouseSensor field.
/// This MouseSensor must be included as a child else where in the scene.
/// Typical (X3D) usage:
/// @code
///   <MouseSensor DEF="mouse"/>
///	<DeviceInfo>
///      <MouseHapticDevice DEF="HDEV">
///         <MouseSensor USE="mouse" containerField="mouseSensor"/>
///         <RuspiniRenderer/>
///      </MouseHapticDevice>
///	</DeviceInfo>
/// @endcode
/// <b>Examples:</b>
///   - <a href="../../examples/GrabableDynamicTest.x3d">GrabableDynamicTest.x3d</a>

class H3D_NETWORKING_UTILS_DLL_SPEC MouseHapticDevice : public H3D::FakeHapticsDevice {
public:
   
   typedef H3D::TypedSFNode<H3D::MouseSensor> SFMouseSensor;

   /// Constructor
   MouseHapticDevice(H3D::Inst<SFMouseSensor> mouseSensor = 0);

   virtual ~MouseHapticDevice() {
      H3D::H3DNavigation::enableDevice( H3D::H3DNavigation::MOUSE );// Revert to default
   }
   
   /// X3D database
   static H3D::H3DNodeDatabase database;

   /// Initialize
   virtual void initialize();

   /// The mouseSensor node that is used \n
   /// access type: inputOutput \n
   /// basic type: SFNode \n
   /// default value: 
   auto_ptr<SFMouseSensor> mouseSensor;

protected:
   // Input fields are 'grab' boolean, current proxy pos, mouse vec2f motion and the right button for z direction
   struct MouseMotion : public H3D::AutoUpdate< H3D::TypedField< H3D::SFVec3f, 
      H3D::Types<H3D::SFBool, H3D::SFVec3f, H3D::SFVec2f, H3D::SFBool> > > {
      virtual void update();
   };

private:
   auto_ptr<MouseMotion> motion_converter;
};

}

#endif
