BsInput.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "Utility/BsModule.h"
  6. #include "Platform/BsPlatform.h"
  7. #include "Input/BsInputFwd.h"
  8. namespace bs
  9. {
  10. class Mouse;
  11. class Keyboard;
  12. class Gamepad;
  13. struct InputPrivateData;
  14. /** @addtogroup Input
  15. * @{
  16. */
  17. /**
  18. * Primary module used for dealing with input. Allows you to receieve and query raw or OS input for
  19. * mouse/keyboard/gamepad.
  20. */
  21. class BS_CORE_EXPORT Input : public Module<Input>
  22. {
  23. /** Possible button states. */
  24. enum class ButtonState
  25. {
  26. Off, /**< Button is not being pressed. */
  27. On, /**< Button is being pressed. */
  28. ToggledOn, /**< Button has been pressed this frame. */
  29. ToggledOff, /**< Button has been released this frame. */
  30. ToggledOnOff, /**< Button has been pressed and released this frame. */
  31. };
  32. /** Contains axis and device data per device. */
  33. struct DeviceData
  34. {
  35. DeviceData();
  36. Vector<float> axes;
  37. ButtonState keyStates[BC_Count];
  38. };
  39. /** Different types of possible input event callbacks. */
  40. enum class EventType
  41. {
  42. ButtonUp, ButtonDown, PointerMoved, PointerUp, PointerDown, PointerDoubleClick, TextInput, Command
  43. };
  44. /** Stores information about a queued input event that is to be triggered later. */
  45. struct QueuedEvent
  46. {
  47. QueuedEvent(EventType type, UINT32 idx)
  48. :type(type), idx(idx)
  49. { }
  50. EventType type;
  51. UINT32 idx;
  52. };
  53. public:
  54. Input();
  55. ~Input();
  56. /**
  57. * Returns value of the specified input axis. Normally in range [-1.0, 1.0] but can be outside the range for
  58. * devices with unbound axes (for example mouse).
  59. *
  60. * @param[in] type Type of axis to query. Usually a type from InputAxis but can be a custom value.
  61. * @param[in] deviceIdx Index of the device in case more than one is hooked up (0 - primary).
  62. */
  63. float getAxisValue(UINT32 type, UINT32 deviceIdx = 0) const;
  64. /**
  65. * Query if the provided button is currently being held (this frame or previous frames).
  66. *
  67. * @param[in] keyCode Code of the button to query.
  68. * @param[in] deviceIdx Device to query the button on (0 - primary).
  69. */
  70. bool isButtonHeld(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
  71. /**
  72. * Query if the provided button is currently being released (only true for one frame).
  73. *
  74. * @param[in] keyCode Code of the button to query.
  75. * @param[in] deviceIdx Device to query the button on (0 - primary).
  76. */
  77. bool isButtonUp(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
  78. /**
  79. * Query if the provided button is currently being pressed (only true for one frame).
  80. *
  81. * @param[in] keyCode Code of the button to query.
  82. * @param[in] deviceIdx Device to query the button on (0 - primary).
  83. */
  84. bool isButtonDown(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
  85. /** Returns position of the pointer (for example mouse cursor) relative to the screen. */
  86. Vector2I getPointerPosition() const;
  87. /** Returns difference between pointer position between current and last frame. */
  88. Vector2I getPointerDelta() const { return mPointerDelta; }
  89. /**
  90. * Query if the provided pointer button is currently being held (this frame or previous frames).
  91. *
  92. * @param[in] pointerButton Code of the button to query.
  93. */
  94. bool isPointerButtonHeld(PointerEventButton pointerButton) const;
  95. /**
  96. * Query if the provided pointer button is currently being released (only true for one frame).
  97. *
  98. * @param[in] pointerButton Code of the button to query.
  99. */
  100. bool isPointerButtonUp(PointerEventButton pointerButton) const;
  101. /**
  102. * Query if the provided pointer button is currently being pressed (only true for one frame).
  103. *
  104. * @param[in] pointerButton Code of the button to query.
  105. */
  106. bool isPointerButtonDown(PointerEventButton pointerButton) const;
  107. /** Query has the left pointer button has been double-clicked this frame. */
  108. bool isPointerDoubleClicked() const;
  109. /** Enables or disables mouse smoothing. Smoothing makes the changes to mouse axes more gradual. */
  110. void setMouseSmoothing(bool enabled);
  111. /** Returns the number of detected devices of the specified type. */
  112. UINT32 getDeviceCount(InputDevice device) const;
  113. /** Returns the name of a specific input device. Returns empty string if the device doesn't exist. */
  114. String getDeviceName(InputDevice type, UINT32 idx);
  115. /** Triggered whenever a button is first pressed. */
  116. Event<void(const ButtonEvent&)> onButtonDown;
  117. /** Triggered whenever a button is first released. */
  118. Event<void(const ButtonEvent&)> onButtonUp;
  119. /** Triggered whenever user inputs a text character. */
  120. Event<void(const TextInputEvent&)> onCharInput;
  121. /** Triggers when some pointing device (mouse cursor, touch) moves. */
  122. Event<void(const PointerEvent&)> onPointerMoved;
  123. /** Triggers when some pointing device (mouse cursor, touch) button is pressed. */
  124. Event<void(const PointerEvent&)> onPointerPressed;
  125. /** Triggers when some pointing device (mouse cursor, touch) button is released. */
  126. Event<void(const PointerEvent&)> onPointerReleased;
  127. /** Triggers when some pointing device (mouse cursor, touch) button is double clicked. */
  128. Event<void(const PointerEvent&)> onPointerDoubleClick;
  129. // TODO Low priority: Remove this, I can emulate it using virtual input
  130. /** Triggers on special input commands. */
  131. Event<void(InputCommandType)> onInputCommand;
  132. public: // ***** INTERNAL ******
  133. /** @name Internal
  134. * @{
  135. */
  136. /**
  137. * Called every frame. Detects button state changes and prepares callback events to trigger via a call to
  138. * _triggerCallbacks().
  139. */
  140. void _update();
  141. /** Triggers any queued input event callbacks. */
  142. void _triggerCallbacks();
  143. /** Returns internal, platform specific privata data. */
  144. InputPrivateData* _getPrivateData() const { return mPlatformData; }
  145. /** Returns a handle to the window that is currently receiving input. */
  146. UINT64 _getWindowHandle() const { return mWindowHandle; }
  147. /** Called by Mouse when mouse movement is detected. */
  148. void _notifyMouseMoved(INT32 relX, INT32 relY, INT32 relZ);
  149. /** Called by any of the raw input devices when analog axis movement is detected. */
  150. void _notifyAxisMoved(UINT32 gamepadIdx, UINT32 axisIdx, INT32 value);
  151. /** Called by any of the raw input devices when a button is pressed. */
  152. void _notifyButtonPressed(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
  153. /** Called by any of the raw input devices when a button is released. */
  154. void _notifyButtonReleased(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
  155. /** @} */
  156. private:
  157. /** Performs platform specific raw input system initialization. */
  158. void initRawInput();
  159. /** Performs platform specific raw input system cleanup. */
  160. void cleanUpRawInput();
  161. /**
  162. * Smooths the input mouse axis value. Smoothing makes the changes to the axis more gradual depending on previous
  163. * values.
  164. *
  165. * @param[in] value Value to smooth.
  166. * @param[in] idx Index of the mouse axis to smooth, 0 - horizontal, 1 - vertical.
  167. * @return Smoothed value.
  168. */
  169. float smoothMouse(float value, UINT32 idx);
  170. /** Triggered by input handler when a button is pressed. */
  171. void buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
  172. /** Triggered by input handler when a button is released. */
  173. void buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
  174. /** Triggered by input handler when a mouse/joystick axis is moved. */
  175. void axisMoved(UINT32 deviceIdx, float value, UINT32 axis);
  176. /**
  177. * Called from the message loop to notify user has entered a character.
  178. *
  179. * @see onCharInput
  180. */
  181. void charInput(UINT32 character);
  182. /**
  183. * Called from the message loop to notify user has moved the cursor.
  184. *
  185. * @see onCursorMoved
  186. */
  187. void cursorMoved(const Vector2I& cursorPos, const OSPointerButtonStates& btnStates);
  188. /**
  189. * Called from the message loop to notify user has pressed a mouse button.
  190. *
  191. * @see onCursorPressed
  192. */
  193. void cursorPressed(const Vector2I& cursorPos, OSMouseButton button, const OSPointerButtonStates& btnStates);
  194. /**
  195. * Called from the message loop to notify user has released a mouse button.
  196. *
  197. * @see onCursorReleased
  198. */
  199. void cursorReleased(const Vector2I& cursorPos, OSMouseButton button, const OSPointerButtonStates& btnStates);
  200. /**
  201. * Called from the message loop to notify user has double-clicked a mouse button.
  202. *
  203. * @see onDoubleClick
  204. */
  205. void cursorDoubleClick(const Vector2I& cursorPos, const OSPointerButtonStates& btnStates);
  206. /**
  207. * Called from the message loop to notify user has entered an input command.
  208. *
  209. * @see onInputCommand
  210. */
  211. void inputCommandEntered(InputCommandType commandType);
  212. /**
  213. * Called from the message loop to notify user has scrolled the mouse wheel.
  214. *
  215. * @see onMouseWheelScrolled
  216. */
  217. void mouseWheelScrolled(float scrollPos);
  218. /** Called when window in focus changes, as reported by the OS. */
  219. void inputWindowChanged(RenderWindow& win);
  220. /**
  221. * Called when the current window loses input focus. This might be followed by inputWindowChanged() if the focus
  222. * just switched to another of this application's windows.
  223. */
  224. void inputFocusLost();
  225. private:
  226. Mutex mMutex;
  227. Vector<DeviceData> mDevices;
  228. Vector2I mLastPointerPosition;
  229. Vector2I mPointerDelta;
  230. ButtonState mPointerButtonStates[3];
  231. bool mPointerDoubleClicked;
  232. bool mLastPositionSet;
  233. // Thread safe
  234. Vector2I mPointerPosition;
  235. float mMouseScroll;
  236. OSPointerButtonStates mPointerState;
  237. Vector<QueuedEvent> mQueuedEvents[2];
  238. Vector<TextInputEvent> mTextInputEvents[2];
  239. Vector<InputCommandType> mCommandEvents[2];
  240. Vector<PointerEvent> mPointerDoubleClickEvents[2];
  241. Vector<PointerEvent> mPointerReleasedEvents[2];
  242. Vector<PointerEvent> mPointerPressedEvents[2];
  243. Vector<ButtonEvent> mButtonDownEvents[2];
  244. Vector<ButtonEvent> mButtonUpEvents[2];
  245. // OS input events
  246. HEvent mCharInputConn;
  247. HEvent mCursorMovedConn;
  248. HEvent mCursorPressedConn;
  249. HEvent mCursorReleasedConn;
  250. HEvent mCursorDoubleClickConn;
  251. HEvent mInputCommandConn;
  252. HEvent mMouseWheelScrolledConn;
  253. // Raw input
  254. bool mMouseSmoothingEnabled;
  255. UINT64 mWindowHandle;
  256. Mouse* mMouse;
  257. Keyboard* mKeyboard;
  258. Vector<Gamepad*> mGamepads;
  259. float mTotalMouseSamplingTime[2];
  260. UINT32 mTotalMouseNumSamples[2];
  261. float mMouseZeroTime[2];
  262. INT32 mMouseSampleAccumulator[2];
  263. float mMouseSmoothedAxis[2];
  264. UINT64 mLastMouseUpdateFrame;
  265. UINT64 mTimestampClockOffset;
  266. InputPrivateData* mPlatformData;
  267. /************************************************************************/
  268. /* STATICS */
  269. /************************************************************************/
  270. static const int HISTORY_BUFFER_SIZE; // Size of buffer used for input smoothing
  271. static const float WEIGHT_MODIFIER;
  272. };
  273. /** Provides global access to Input. */
  274. BS_CORE_EXPORT Input& gInput();
  275. /** @} */
  276. }