BsInput.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Input/BsInput.h"
  4. #include "Utility/BsTime.h"
  5. #include "Math/BsMath.h"
  6. #include "Math/BsRect2I.h"
  7. #include "Debug/BsDebug.h"
  8. #include "Managers/BsRenderWindowManager.h"
  9. using namespace std::placeholders;
  10. namespace bs
  11. {
  12. const int Input::HISTORY_BUFFER_SIZE = 10; // Size of buffer used for input smoothing
  13. const float Input::WEIGHT_MODIFIER = 0.5f;
  14. Input::DeviceData::DeviceData()
  15. {
  16. for (int i = 0; i < BC_Count; i++)
  17. keyStates[i] = ButtonState::Off;
  18. }
  19. Input::Input()
  20. :mPointerDoubleClicked(false), mLastPositionSet(false)
  21. {
  22. mOSInputHandler = bs_shared_ptr_new<OSInputHandler>();
  23. mOSInputHandler->onCharInput.connect(std::bind(&Input::charInput, this, _1));
  24. mOSInputHandler->onCursorMoved.connect(std::bind(&Input::cursorMoved, this, _1));
  25. mOSInputHandler->onCursorPressed.connect(std::bind(&Input::cursorPressed, this, _1));
  26. mOSInputHandler->onCursorReleased.connect(std::bind(&Input::cursorReleased, this, _1));
  27. mOSInputHandler->onDoubleClick.connect(std::bind(&Input::cursorDoubleClick, this, _1));
  28. mOSInputHandler->onInputCommand.connect(std::bind(&Input::inputCommandEntered, this, _1));
  29. RenderWindowManager::instance().onFocusGained.connect(std::bind(&Input::inputWindowChanged, this, _1));
  30. for (int i = 0; i < 3; i++)
  31. mPointerButtonStates[i] = ButtonState::Off;
  32. }
  33. Input::~Input()
  34. { }
  35. void Input::_registerRawInputHandler(SPtr<RawInputHandler> inputHandler)
  36. {
  37. if(mRawInputHandler != inputHandler)
  38. {
  39. mRawInputHandler = inputHandler;
  40. if(mRawInputHandler != nullptr)
  41. {
  42. mRawInputHandler->onButtonDown.connect(std::bind(&Input::buttonDown, this, _1, _2, _3));
  43. mRawInputHandler->onButtonUp.connect(std::bind(&Input::buttonUp, this, _1, _2, _3));
  44. mRawInputHandler->onAxisMoved.connect(std::bind(&Input::axisMoved, this, _1, _2, _3));
  45. }
  46. }
  47. }
  48. void Input::_update()
  49. {
  50. // Toggle states only remain active for a single frame before they are transitioned
  51. // into permanent state
  52. for (auto& deviceData : mDevices)
  53. {
  54. for (UINT32 i = 0; i < BC_Count; i++)
  55. {
  56. if (deviceData.keyStates[i] == ButtonState::ToggledOff || deviceData.keyStates[i] == ButtonState::ToggledOnOff)
  57. deviceData.keyStates[i] = ButtonState::Off;
  58. else if (deviceData.keyStates[i] == ButtonState::ToggledOn)
  59. deviceData.keyStates[i] = ButtonState::On;
  60. }
  61. UINT32 numAxes = (UINT32)deviceData.axes.size();
  62. for (UINT32 i = 0; i < numAxes; i++)
  63. {
  64. deviceData.axes[i].rel = 0.0f;
  65. }
  66. }
  67. for (UINT32 i = 0; i < 3; i++)
  68. {
  69. if (mPointerButtonStates[i] == ButtonState::ToggledOff || mPointerButtonStates[i] == ButtonState::ToggledOnOff)
  70. mPointerButtonStates[i] = ButtonState::Off;
  71. else if (mPointerButtonStates[i] == ButtonState::ToggledOn)
  72. mPointerButtonStates[i] = ButtonState::On;
  73. }
  74. mPointerDelta = Vector2I::ZERO; // Reset delta in case we don't receive any mouse input this frame
  75. mPointerDoubleClicked = false;
  76. if(mRawInputHandler == nullptr)
  77. {
  78. LOGERR("Raw input handler not initialized!");
  79. return;
  80. }
  81. else
  82. mRawInputHandler->_update();
  83. if(mOSInputHandler == nullptr)
  84. {
  85. LOGERR("OS input handler not initialized!");
  86. return;
  87. }
  88. else
  89. mOSInputHandler->_update();
  90. }
  91. void Input::_triggerCallbacks()
  92. {
  93. for (auto& event : mQueuedEvents)
  94. {
  95. switch (event.type)
  96. {
  97. case EventType::ButtonDown:
  98. onButtonDown(mButtonDownEvents[event.idx]);
  99. break;
  100. case EventType::ButtonUp:
  101. onButtonUp(mButtonUpEvents[event.idx]);
  102. break;
  103. case EventType::PointerDown:
  104. onPointerPressed(mPointerPressedEvents[event.idx]);
  105. break;
  106. case EventType::PointerUp:
  107. onPointerReleased(mPointerReleasedEvents[event.idx]);
  108. break;
  109. case EventType::PointerDoubleClick:
  110. onPointerDoubleClick(mPointerDoubleClickEvents[event.idx]);
  111. break;
  112. case EventType::PointerMoved:
  113. onPointerMoved(mPointerMovedEvents[event.idx]);
  114. break;
  115. case EventType::TextInput:
  116. onCharInput(mTextInputEvents[event.idx]);
  117. break;
  118. case EventType::Command:
  119. onInputCommand(mCommandEvents[event.idx]);
  120. break;
  121. }
  122. }
  123. mQueuedEvents.clear();
  124. mButtonDownEvents.clear();
  125. mButtonUpEvents.clear();
  126. mPointerPressedEvents.clear();
  127. mPointerReleasedEvents.clear();
  128. mPointerDoubleClickEvents.clear();
  129. mPointerMovedEvents.clear();
  130. mTextInputEvents.clear();
  131. mCommandEvents.clear();
  132. }
  133. void Input::inputWindowChanged(RenderWindow& win)
  134. {
  135. if(mRawInputHandler != nullptr)
  136. mRawInputHandler->_inputWindowChanged(win);
  137. if(mOSInputHandler != nullptr)
  138. mOSInputHandler->_inputWindowChanged(win);
  139. }
  140. void Input::buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp)
  141. {
  142. while (deviceIdx >= (UINT32)mDevices.size())
  143. mDevices.push_back(DeviceData());
  144. mDevices[deviceIdx].keyStates[code & 0x0000FFFF] = ButtonState::ToggledOn;
  145. ButtonEvent btnEvent;
  146. btnEvent.buttonCode = code;
  147. btnEvent.timestamp = timestamp;
  148. btnEvent.deviceIdx = deviceIdx;
  149. mQueuedEvents.push_back(QueuedEvent(EventType::ButtonDown, (UINT32)mButtonDownEvents.size()));
  150. mButtonDownEvents.push_back(btnEvent);
  151. }
  152. void Input::buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp)
  153. {
  154. while (deviceIdx >= (UINT32)mDevices.size())
  155. mDevices.push_back(DeviceData());
  156. if (mDevices[deviceIdx].keyStates[code & 0x0000FFFF] == ButtonState::ToggledOn)
  157. mDevices[deviceIdx].keyStates[code & 0x0000FFFF] = ButtonState::ToggledOnOff;
  158. else
  159. mDevices[deviceIdx].keyStates[code & 0x0000FFFF] = ButtonState::ToggledOff;
  160. ButtonEvent btnEvent;
  161. btnEvent.buttonCode = code;
  162. btnEvent.timestamp = timestamp;
  163. btnEvent.deviceIdx = deviceIdx;
  164. mQueuedEvents.push_back(QueuedEvent(EventType::ButtonUp, (UINT32)mButtonUpEvents.size()));
  165. mButtonUpEvents.push_back(btnEvent);
  166. }
  167. void Input::axisMoved(UINT32 deviceIdx, const RawAxisState& state, UINT32 axis)
  168. {
  169. while (deviceIdx >= (UINT32)mDevices.size())
  170. mDevices.push_back(DeviceData());
  171. Vector<RawAxisState>& axes = mDevices[deviceIdx].axes;
  172. while (axis >= (UINT32)axes.size())
  173. axes.push_back(RawAxisState());
  174. mDevices[deviceIdx].axes[axis] = state;
  175. }
  176. void Input::cursorMoved(const PointerEvent& event)
  177. {
  178. mQueuedEvents.push_back(QueuedEvent(EventType::PointerMoved, (UINT32)mPointerMovedEvents.size()));
  179. mPointerMovedEvents.push_back(event);
  180. if (mLastPositionSet)
  181. mPointerDelta = event.screenPos - mPointerPosition;
  182. mPointerPosition = event.screenPos;
  183. mLastPositionSet = true;
  184. }
  185. void Input::cursorPressed(const PointerEvent& event)
  186. {
  187. mPointerButtonStates[(UINT32)event.button] = ButtonState::ToggledOn;
  188. mQueuedEvents.push_back(QueuedEvent(EventType::PointerDown, (UINT32)mPointerPressedEvents.size()));
  189. mPointerPressedEvents.push_back(event);
  190. }
  191. void Input::cursorReleased(const PointerEvent& event)
  192. {
  193. if (mPointerButtonStates[(UINT32)event.button] == ButtonState::ToggledOn)
  194. mPointerButtonStates[(UINT32)event.button] = ButtonState::ToggledOnOff;
  195. else
  196. mPointerButtonStates[(UINT32)event.button] = ButtonState::ToggledOff;
  197. mQueuedEvents.push_back(QueuedEvent(EventType::PointerUp, (UINT32)mPointerReleasedEvents.size()));
  198. mPointerReleasedEvents.push_back(event);
  199. }
  200. void Input::cursorDoubleClick(const PointerEvent& event)
  201. {
  202. mPointerDoubleClicked = true;
  203. mQueuedEvents.push_back(QueuedEvent(EventType::PointerDoubleClick, (UINT32)mPointerDoubleClickEvents.size()));
  204. mPointerDoubleClickEvents.push_back(event);
  205. }
  206. void Input::inputCommandEntered(InputCommandType commandType)
  207. {
  208. mQueuedEvents.push_back(QueuedEvent(EventType::Command, (UINT32)mCommandEvents.size()));
  209. mCommandEvents.push_back(commandType);
  210. }
  211. void Input::charInput(UINT32 chr)
  212. {
  213. TextInputEvent textInputEvent;
  214. textInputEvent.textChar = chr;
  215. mQueuedEvents.push_back(QueuedEvent(EventType::TextInput, (UINT32)mTextInputEvents.size()));
  216. mTextInputEvents.push_back(textInputEvent);
  217. }
  218. float Input::getAxisValue(UINT32 type, UINT32 deviceIdx) const
  219. {
  220. if (deviceIdx >= (UINT32)mDevices.size())
  221. return 0.0f;
  222. const Vector<RawAxisState>& axes = mDevices[deviceIdx].axes;
  223. if (type >= (UINT32)axes.size())
  224. return 0.0f;
  225. return axes[type].rel;
  226. }
  227. bool Input::isButtonHeld(ButtonCode button, UINT32 deviceIdx) const
  228. {
  229. if (deviceIdx >= (UINT32)mDevices.size())
  230. return false;
  231. return mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::On ||
  232. mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::ToggledOn ||
  233. mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::ToggledOnOff;
  234. }
  235. bool Input::isButtonUp(ButtonCode button, UINT32 deviceIdx) const
  236. {
  237. if (deviceIdx >= (UINT32)mDevices.size())
  238. return false;
  239. return mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::ToggledOff ||
  240. mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::ToggledOnOff;
  241. }
  242. bool Input::isButtonDown(ButtonCode button, UINT32 deviceIdx) const
  243. {
  244. if (deviceIdx >= (UINT32)mDevices.size())
  245. return false;
  246. return mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::ToggledOn ||
  247. mDevices[deviceIdx].keyStates[button & 0x0000FFFF] == ButtonState::ToggledOnOff;
  248. }
  249. bool Input::isPointerButtonHeld(PointerEventButton pointerButton) const
  250. {
  251. return mPointerButtonStates[(UINT32)pointerButton] == ButtonState::On ||
  252. mPointerButtonStates[(UINT32)pointerButton] == ButtonState::ToggledOn ||
  253. mPointerButtonStates[(UINT32)pointerButton] == ButtonState::ToggledOnOff;
  254. }
  255. bool Input::isPointerButtonUp(PointerEventButton pointerButton) const
  256. {
  257. return mPointerButtonStates[(UINT32)pointerButton] == ButtonState::ToggledOff ||
  258. mPointerButtonStates[(UINT32)pointerButton] == ButtonState::ToggledOnOff;
  259. }
  260. bool Input::isPointerButtonDown(PointerEventButton pointerButton) const
  261. {
  262. return mPointerButtonStates[(UINT32)pointerButton] == ButtonState::ToggledOn ||
  263. mPointerButtonStates[(UINT32)pointerButton] == ButtonState::ToggledOnOff;
  264. }
  265. bool Input::isPointerDoubleClicked() const
  266. {
  267. return mPointerDoubleClicked;
  268. }
  269. Vector2I Input::getPointerPosition() const
  270. {
  271. return mPointerPosition;
  272. }
  273. void Input::setMouseSmoothing(bool enable)
  274. {
  275. mRawInputHandler->setMouseSmoothing(enable);
  276. }
  277. Input& gInput()
  278. {
  279. return Input::instance();
  280. }
  281. }