text: 
  #ifndef GAINPUTINPUTDEVICE_H_
  #define GAINPUTINPUTDEVICE_H_
  
  namespace gainput
  {
  
  
  /// Type of an input device button.
  enum ButtonType
  {
  	BT_BOOL,	///< A boolean value button, either down (true) or up (false).
  	BT_FLOAT,	///< A floating-point value button, between -1.0f and 1.0f or 0.0f and 1.0f.
  	BT_COUNT	///< The number of different button types.
  };
  
  
  /// Interface for anything that provides device inputs.
  /**
   * An InputDevice can be anything from a physical device, like a mouse or keyboard, to the more abstract
   * concept of gestures that in turn themselves depend on other InputDevices. What they have in common is
   * that they provide a number of device buttons (identified by a DeviceButtonId) which can be queried for
   * their state.
   *
   * Note that you may not instantiate an InputDevice (or any derived implementation) directly. Instead you
   * have to call InputManager::CreateDevice() or InputManager::CreateAndGetDevice() with the device you want
   * to instantiate as the template parameter. That way the device will be properly registered with the
   * InputManager and continuously updated.
   *
   * Normally, you won't interact with an InputDevice directly, but instead use its device ID and its device
   * buttons' IDs to map the device buttons to user buttons (see InputMap).
   */
  class GAINPUT_LIBEXPORT InputDevice
  {
  public:
  	/// Type of an input device.
  	enum DeviceType
  	{
  		DT_MOUSE,		///< A mouse/cursor input device featuring one pointer.
  		DT_KEYBOARD,		///< A keyboard input device.
  		DT_PAD,			///< A joypad/gamepad input device.
  		DT_TOUCH,		///< A touch-sensitive input device supporting multiple simultaneous pointers.
  		DT_BUILTIN,		///< Any controls directly built into the device that also contains the screen.
  		DT_REMOTE,		///< A generic networked input device.
  		DT_GESTURE,		///< A gesture input device, building on top of other input devices.
  		DT_CUSTOM,		///< A custom, user-created input device.
  		DT_COUNT		///< The count of input device types.
  	};
  
  	/// Variant of an input device type.
  	enum DeviceVariant
  	{
  		DV_STANDARD,		///< The standard implementation of the given device type.
  		DV_RAW,			///< The raw input implementation of the given device type.
  		DV_NULL			///< The null/empty implementation of the given device type.
  	};
  
  	/// State of an input device.
  	enum DeviceState
  	{
  		DS_OK,			///< Everything is okay.
  		DS_LOW_BATTERY,		///< The input device is low on battery.
  		DS_UNAVAILABLE		///< The input device is currently not available.
  	};
  
  	static const unsigned AutoIndex = unsigned(-1);
  
  	/// Initializes the input device.
  	/**
  	 * Do not instantiate any input device directly. Call InputManager::CreateDevice() instead.
  	 */
  	InputDevice(InputManager& manager, DeviceId device, unsigned index);
  
  	/// Empty virtual destructor.
  	virtual ~InputDevice();
  
  	/// Update this device, internally called by InputManager.
  	/**
  	 * \param delta The delta state to add changes to. May be 0.
  	 */
  	void Update(InputDeltaState* delta);
  
  	/// Returns this device's ID.
  	DeviceId GetDeviceId() const { return deviceId_; }
  	/// Returns the device's index among devices of the same type.
  	unsigned GetIndex() const { return index_; }
  
  	/// Returns the device type.
  	virtual DeviceType GetType() const = 0;
  	/// Returns the device variant.
  	virtual DeviceVariant GetVariant() const { return DV_STANDARD; }
  	/// Returns the device type's name.
  	virtual const char* GetTypeName() const = 0;
  	/// Returns if this device should be updated after other devices.
  	virtual bool IsLateUpdate() const { return false; }
  	/// Returns the device state.
  	DeviceState GetState() const;
  	/// Returns if this device is available.
  	virtual bool IsAvailable() const { return GetState() == DS_OK || GetState() == DS_LOW_BATTERY; }
  
  	/// Returns if the given button is valid for this device.
  	virtual bool IsValidButtonId(DeviceButtonId deviceButton) const = 0;
  
  	/// Returns the current state of the given button.
  	bool GetBool(DeviceButtonId deviceButton) const;
  	/// Returns the previous state of the given button.
  	bool GetBoolPrevious(DeviceButtonId deviceButton) const;
  	/// Returns the current state of the given button.
  	float GetFloat(DeviceButtonId deviceButton) const;
  	/// Returns the previous state of the given button.
  	float GetFloatPrevious(DeviceButtonId deviceButton) const;
  
  	/// Checks if any button on this device is down.
  	/**
  	 * \param[out] outButtons An array with maxButtonCount fields to receive the device buttons that are down.
  	 * \param maxButtonCount The number of fields in outButtons.
  	 * \return The number of device buttons written to outButtons.
  	 */
  	virtual size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const { GAINPUT_UNUSED(outButtons); GAINPUT_UNUSED(maxButtonCount); return 0; }
  
  	/// Gets the name of the given button.
  	/**
  	 * \param deviceButton ID of the button.
  	 * \param buffer A char-buffer to receive the button name.
  	 * \param bufferLength Length of the buffer receiving the button name in bytes.
  	 * \return The number of bytes written to buffer (includes the trailing \0).
  	 */
  	virtual size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const { GAINPUT_UNUSED(deviceButton); GAINPUT_UNUSED(buffer); GAINPUT_UNUSED(bufferLength); return 0; }
  	/// Returns the type of the given button.
  	virtual ButtonType GetButtonType(DeviceButtonId deviceButton) const = 0;
  
  	/// Returns the button's ID if the name is of this device's buttons.
  	/**
  	 * \param name Name of the device button to look for.
  	 * \return The device button ID.
  	 */
  	virtual DeviceButtonId GetButtonByName(const char* name) const { GAINPUT_UNUSED(name); return InvalidDeviceButtonId; }
  
  	/// Returns the device's state, probably best if only used internally.
  	InputState* GetInputState() { return state_; }
  	/// Returns the device's state, probably best if only used internally.
  	const InputState* GetInputState() const { return state_; }
  	/// Returns the device's previous state, probably best if only used internally.
  	InputState* GetPreviousInputState() { return previousState_; }
  	/// Returns the device's state that is currently being determined, may be 0 if not available.
  	virtual InputState* GetNextInputState() { return 0; }
  
  	/// Returns the previously set dead zone for the given button or 0.0f if none was set yet.
  	float GetDeadZone(DeviceButtonId buttonId) const;
  	/// Sets the dead zone for the given button.
  	void SetDeadZone(DeviceButtonId buttonId, float value);
  
  	/// Enable/disable debug rendering of this device.
  	void SetDebugRenderingEnabled(bool enabled);
  	/// Returns true if debug rendering is enabled, false otherwise.
  	bool IsDebugRenderingEnabled() const { return debugRenderingEnabled_; }
  
  #if defined(GAINPUT_DEV) || defined(GAINPUT_ENABLE_RECORDER)
  	/// Returns true if this device is being controlled by a remote device 
  	/// or a recorded input sequence, false otherwise.
  	bool IsSynced() const { return synced_; }
  	/// Sets if this device is being controlled remotely or from a recording.
  	/**
  	 * \sa IsSynced()
  	 */
  	void SetSynced(bool synced) { synced_ = synced; }
  #endif
  
  protected:
  	/// The manager this device belongs to.
  	InputManager& manager_;
  
  	/// The ID of this device.
  	DeviceId deviceId_;
  
  	/// Index of this device among devices of the same type.
  	unsigned index_;
  
  	/// The current state of this device.
  	InputState* state_;
  	/// The previous state of this device.
  	InputState* previousState_;
  
  	float* deadZones_;
  
  	/// Specifies if this device is currently rendering debug information.
  	bool debugRenderingEnabled_;
  
  #if defined(GAINPUT_DEV) || defined(GAINPUT_ENABLE_RECORDER)
  	/// Specifies if this device's state is actually set from a device
  	/// or manually set by some other system.
  	bool synced_;
  #endif
  
  	/// Implementation of the device's Update function.
  	/**
  	 * \param delta The delta state to add changes to. May be 0.
  	 */
  	virtual void InternalUpdate(InputDeltaState* delta) = 0;
  
  	/// Implementation of the device's GetState function.
  	/**
  	 * \return The device's state.
  	 */
  	virtual DeviceState InternalGetState() const = 0;
  
  	/// Checks which buttons are down.
  	/**
  	 * This function is normally used by GetAnyButtonDown implementations internally.
  	 * \param outButtons An array to write buttons that are down to.
  	 * \param maxButtonCount The size of outButtons.
  	 * \param start The lowest device button ID to check.
  	 * \param end The biggest device button ID to check.
  	 * \return The number of buttons written to outButtons.
  	 */
  	size_t CheckAllButtonsDown(DeviceButtonSpec* outButtons, size_t maxButtonCount, unsigned start, unsigned end) const;
  };
  
  
  inline
  bool
  InputDevice::GetBool(DeviceButtonId deviceButton) const
  {
  	if (!IsAvailable())
  	{
  		return false;
  	}
  	GAINPUT_ASSERT(state_);
  	return state_->GetBool(deviceButton);
  }
  
  inline
  bool
  InputDevice::GetBoolPrevious(DeviceButtonId deviceButton) const
  {
  	if (!IsAvailable())
  	{
  		return false;
  	}
  	GAINPUT_ASSERT(previousState_);
  	return previousState_->GetBool(deviceButton);
  }
  
  inline
  float
  InputDevice::GetFloat(DeviceButtonId deviceButton) const
  {
  	if (!IsAvailable())
  	{
  		return 0.0f;
  	}
  	GAINPUT_ASSERT(state_);
  	return state_->GetFloat(deviceButton);
  }
  
  inline
  float
  InputDevice::GetFloatPrevious(DeviceButtonId deviceButton) const
  {
  	if (!IsAvailable())
  	{
  		return 0.0f;
  	}
  	GAINPUT_ASSERT(previousState_);
  	return previousState_->GetFloat(deviceButton);
  }
  
  }
  
  #endif
  
  