inputhandler.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include "irrlichttypes_extrabloated.h"
  18. #include "joystick_controller.h"
  19. #include <list>
  20. #include "keycode.h"
  21. #include "renderingengine.h"
  22. class InputHandler;
  23. /****************************************************************************
  24. Fast key cache for main game loop
  25. ****************************************************************************/
  26. /* This is faster than using getKeySetting with the tradeoff that functions
  27. * using it must make sure that it's initialised before using it and there is
  28. * no error handling (for example bounds checking). This is really intended for
  29. * use only in the main running loop of the client (the_game()) where the faster
  30. * (up to 10x faster) key lookup is an asset. Other parts of the codebase
  31. * (e.g. formspecs) should continue using getKeySetting().
  32. */
  33. struct KeyCache
  34. {
  35. KeyCache()
  36. {
  37. handler = NULL;
  38. populate();
  39. populate_nonchanging();
  40. }
  41. void populate();
  42. // Keys that are not settings dependent
  43. void populate_nonchanging();
  44. KeyPress key[KeyType::INTERNAL_ENUM_COUNT];
  45. InputHandler *handler;
  46. };
  47. class KeyList : private std::list<KeyPress>
  48. {
  49. typedef std::list<KeyPress> super;
  50. typedef super::iterator iterator;
  51. typedef super::const_iterator const_iterator;
  52. virtual const_iterator find(const KeyPress &key) const
  53. {
  54. const_iterator f(begin());
  55. const_iterator e(end());
  56. while (f != e) {
  57. if (*f == key)
  58. return f;
  59. ++f;
  60. }
  61. return e;
  62. }
  63. virtual iterator find(const KeyPress &key)
  64. {
  65. iterator f(begin());
  66. iterator e(end());
  67. while (f != e) {
  68. if (*f == key)
  69. return f;
  70. ++f;
  71. }
  72. return e;
  73. }
  74. public:
  75. void clear() { super::clear(); }
  76. void set(const KeyPress &key)
  77. {
  78. if (find(key) == end())
  79. push_back(key);
  80. }
  81. void unset(const KeyPress &key)
  82. {
  83. iterator p(find(key));
  84. if (p != end())
  85. erase(p);
  86. }
  87. void toggle(const KeyPress &key)
  88. {
  89. iterator p(this->find(key));
  90. if (p != end())
  91. erase(p);
  92. else
  93. push_back(key);
  94. }
  95. void append(const KeyList &other)
  96. {
  97. for (const KeyPress &key : other) {
  98. set(key);
  99. }
  100. }
  101. bool operator[](const KeyPress &key) const { return find(key) != end(); }
  102. };
  103. class MyEventReceiver : public IEventReceiver
  104. {
  105. public:
  106. // This is the one method that we have to implement
  107. virtual bool OnEvent(const SEvent &event);
  108. bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown[keyCode]; }
  109. // Checks whether a key was down and resets the state
  110. bool WasKeyDown(const KeyPress &keyCode)
  111. {
  112. bool b = keyWasDown[keyCode];
  113. if (b)
  114. keyWasDown.unset(keyCode);
  115. return b;
  116. }
  117. // Checks whether a key was just pressed. State will be cleared
  118. // in the subsequent iteration of Game::processPlayerInteraction
  119. bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed[keycode]; }
  120. // Checks whether a key was just released. State will be cleared
  121. // in the subsequent iteration of Game::processPlayerInteraction
  122. bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased[keycode]; }
  123. void listenForKey(const KeyPress &keyCode)
  124. {
  125. keysListenedFor.set(keyCode);
  126. }
  127. void dontListenForKeys()
  128. {
  129. keysListenedFor.clear();
  130. }
  131. s32 getMouseWheel()
  132. {
  133. s32 a = mouse_wheel;
  134. mouse_wheel = 0;
  135. return a;
  136. }
  137. void clearInput()
  138. {
  139. keyIsDown.clear();
  140. keyWasDown.clear();
  141. keyWasPressed.clear();
  142. keyWasReleased.clear();
  143. mouse_wheel = 0;
  144. }
  145. void releaseAllKeys()
  146. {
  147. keyWasReleased.append(keyIsDown);
  148. keyIsDown.clear();
  149. }
  150. void clearWasKeyPressed()
  151. {
  152. keyWasPressed.clear();
  153. }
  154. void clearWasKeyReleased()
  155. {
  156. keyWasReleased.clear();
  157. }
  158. JoystickController *joystick = nullptr;
  159. private:
  160. s32 mouse_wheel = 0;
  161. // The current state of keys
  162. KeyList keyIsDown;
  163. // Like keyIsDown but only reset when that key is read
  164. KeyList keyWasDown;
  165. // Whether a key has just been pressed
  166. KeyList keyWasPressed;
  167. // Whether a key has just been released
  168. KeyList keyWasReleased;
  169. // List of keys we listen for
  170. // TODO perhaps the type of this is not really
  171. // performant as KeyList is designed for few but
  172. // often changing keys, and keysListenedFor is expected
  173. // to change seldomly but contain lots of keys.
  174. KeyList keysListenedFor;
  175. };
  176. class InputHandler
  177. {
  178. public:
  179. InputHandler()
  180. {
  181. keycache.handler = this;
  182. keycache.populate();
  183. }
  184. virtual ~InputHandler() = default;
  185. virtual bool isRandom() const
  186. {
  187. return false;
  188. }
  189. virtual bool isKeyDown(GameKeyType k) = 0;
  190. virtual bool wasKeyDown(GameKeyType k) = 0;
  191. virtual bool wasKeyPressed(GameKeyType k) = 0;
  192. virtual bool wasKeyReleased(GameKeyType k) = 0;
  193. virtual bool cancelPressed() = 0;
  194. virtual float getMovementSpeed() = 0;
  195. virtual float getMovementDirection() = 0;
  196. virtual void clearWasKeyPressed() {}
  197. virtual void clearWasKeyReleased() {}
  198. virtual void listenForKey(const KeyPress &keyCode) {}
  199. virtual void dontListenForKeys() {}
  200. virtual v2s32 getMousePos() = 0;
  201. virtual void setMousePos(s32 x, s32 y) = 0;
  202. virtual s32 getMouseWheel() = 0;
  203. virtual void step(float dtime) {}
  204. virtual void clear() {}
  205. virtual void releaseAllKeys() {}
  206. JoystickController joystick;
  207. KeyCache keycache;
  208. };
  209. /*
  210. Separated input handler
  211. */
  212. class RealInputHandler : public InputHandler
  213. {
  214. public:
  215. RealInputHandler(MyEventReceiver *receiver) : m_receiver(receiver)
  216. {
  217. m_receiver->joystick = &joystick;
  218. }
  219. virtual ~RealInputHandler()
  220. {
  221. m_receiver->joystick = nullptr;
  222. }
  223. virtual bool isKeyDown(GameKeyType k)
  224. {
  225. return m_receiver->IsKeyDown(keycache.key[k]) || joystick.isKeyDown(k);
  226. }
  227. virtual bool wasKeyDown(GameKeyType k)
  228. {
  229. return m_receiver->WasKeyDown(keycache.key[k]) || joystick.wasKeyDown(k);
  230. }
  231. virtual bool wasKeyPressed(GameKeyType k)
  232. {
  233. return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyPressed(k);
  234. }
  235. virtual bool wasKeyReleased(GameKeyType k)
  236. {
  237. return m_receiver->WasKeyReleased(keycache.key[k]) || joystick.wasKeyReleased(k);
  238. }
  239. virtual float getMovementSpeed();
  240. virtual float getMovementDirection();
  241. virtual bool cancelPressed()
  242. {
  243. return wasKeyDown(KeyType::ESC) || m_receiver->WasKeyDown(CancelKey);
  244. }
  245. virtual void clearWasKeyPressed()
  246. {
  247. m_receiver->clearWasKeyPressed();
  248. }
  249. virtual void clearWasKeyReleased()
  250. {
  251. m_receiver->clearWasKeyReleased();
  252. }
  253. virtual void listenForKey(const KeyPress &keyCode)
  254. {
  255. m_receiver->listenForKey(keyCode);
  256. }
  257. virtual void dontListenForKeys()
  258. {
  259. m_receiver->dontListenForKeys();
  260. }
  261. virtual v2s32 getMousePos()
  262. {
  263. auto control = RenderingEngine::get_raw_device()->getCursorControl();
  264. if (control) {
  265. return control->getPosition();
  266. }
  267. return m_mousepos;
  268. }
  269. virtual void setMousePos(s32 x, s32 y)
  270. {
  271. auto control = RenderingEngine::get_raw_device()->getCursorControl();
  272. if (control) {
  273. control->setPosition(x, y);
  274. } else {
  275. m_mousepos = v2s32(x, y);
  276. }
  277. }
  278. virtual s32 getMouseWheel()
  279. {
  280. return m_receiver->getMouseWheel();
  281. }
  282. void clear()
  283. {
  284. joystick.clear();
  285. m_receiver->clearInput();
  286. }
  287. void releaseAllKeys()
  288. {
  289. joystick.releaseAllKeys();
  290. m_receiver->releaseAllKeys();
  291. }
  292. private:
  293. MyEventReceiver *m_receiver = nullptr;
  294. v2s32 m_mousepos;
  295. };
  296. class RandomInputHandler : public InputHandler
  297. {
  298. public:
  299. RandomInputHandler() = default;
  300. bool isRandom() const
  301. {
  302. return true;
  303. }
  304. virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; }
  305. virtual bool wasKeyDown(GameKeyType k) { return false; }
  306. virtual bool wasKeyPressed(GameKeyType k) { return false; }
  307. virtual bool wasKeyReleased(GameKeyType k) { return false; }
  308. virtual bool cancelPressed() { return false; }
  309. virtual float getMovementSpeed() { return movementSpeed; }
  310. virtual float getMovementDirection() { return movementDirection; }
  311. virtual v2s32 getMousePos() { return mousepos; }
  312. virtual void setMousePos(s32 x, s32 y) { mousepos = v2s32(x, y); }
  313. virtual s32 getMouseWheel() { return 0; }
  314. virtual void step(float dtime);
  315. s32 Rand(s32 min, s32 max);
  316. private:
  317. KeyList keydown;
  318. v2s32 mousepos;
  319. v2s32 mousespeed;
  320. float movementSpeed;
  321. float movementDirection;
  322. };