You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

274 lines
7.0 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2017—2019 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. #include <string>
  14. #include <vector>
  15. #include <unordered_set>
  16. #include <memory>
  17. namespace lol
  18. {
  19. // FIXME: maybe m_key_names is no longer required?
  20. class input
  21. {
  22. public:
  23. enum class key : uint16_t
  24. {
  25. #define _SC(id, str, name) SC_##name = id,
  26. #include "ui/keys.inc"
  27. };
  28. enum class button : uint16_t
  29. {
  30. #define _BTN(id, name) BTN_##name = id,
  31. #include "ui/buttons.inc"
  32. };
  33. enum class axis : uint16_t
  34. {
  35. // Mouse
  36. Wheel,
  37. X,
  38. Y,
  39. ScreenX,
  40. ScreenY,
  41. MoveX,
  42. MoveY,
  43. ScreenMoveX,
  44. ScreenMoveY,
  45. // Joystick
  46. LeftX,
  47. LeftY,
  48. RightX,
  49. RightY,
  50. LeftShoulder,
  51. RightShoulder,
  52. };
  53. class device
  54. {
  55. public:
  56. device(std::string const &name) : m_name(name) {}
  57. class mouse;
  58. class keyboard;
  59. class joystick;
  60. // Get the name of this input device
  61. const std::string& name() const { return m_name; }
  62. #if 0
  63. //
  64. // Bindings section
  65. //
  66. void bind(input::key key, uint16_t event);
  67. void unbind(input::key key, uint16_t event);
  68. void bind(input::button button, uint16_t event);
  69. void unbind(input::button button, uint16_t event);
  70. void bind(input::axis axis, uint16_t event);
  71. void unbind(input::axis axis, uint16_t event);
  72. #endif
  73. //
  74. // Key, button etc. state
  75. //
  76. // Get the current state of the given key
  77. bool key(input::key key) const
  78. {
  79. return (size_t)key >= m_keys.size() ? false : m_keys[(int)key];
  80. }
  81. bool key_released(input::key key) const
  82. {
  83. return m_released_keys.find(key) != m_released_keys.end();
  84. }
  85. bool key_pressed(input::key key) const
  86. {
  87. return m_pressed_keys.find(key) != m_pressed_keys.end();
  88. }
  89. // Get the current state of the given button
  90. bool button(input::button button) const
  91. {
  92. return (size_t)button >= m_buttons.size() ? false : m_buttons[(int)button];
  93. }
  94. bool button_released(input::button button) const
  95. {
  96. return m_released_buttons.find(button) != m_released_buttons.end();
  97. }
  98. bool button_pressed(input::button button) const
  99. {
  100. return m_pressed_buttons.find(button) != m_pressed_buttons.end();
  101. }
  102. // Get the current state of the given axis
  103. float axis(input::axis axis) const
  104. {
  105. return (size_t)axis >= m_axes.size() ? 0.0f : m_axes[(int)axis];
  106. }
  107. bool axis_changed(input::axis axis) const
  108. {
  109. return m_changed_axes.find(axis) != m_changed_axes.end();
  110. }
  111. // TODO: axis sensitivity was removed
  112. public:
  113. /** Internal functions that allow to construct an input device
  114. * dynamically, when the keys, axis and cursors are not known at
  115. * compile time. */
  116. void internal_add_button(input::button, char const *name);
  117. void internal_add_axis(input::axis, char const *name);
  118. void internal_add_key(input::key, char const *name);
  119. /* Internal functions for the platform-specific drivers. */
  120. void internal_begin_frame()
  121. {
  122. m_pressed_keys.clear();
  123. m_released_keys.clear();
  124. m_pressed_buttons.clear();
  125. m_released_buttons.clear();
  126. m_changed_axes.clear();
  127. }
  128. void internal_set_key(input::key key, bool state)
  129. {
  130. if (m_keys[(int)key] != state)
  131. (state ? m_pressed_keys : m_released_keys).insert(key);
  132. m_keys[(int)key] = state;
  133. }
  134. void internal_set_button(input::button button, bool state)
  135. {
  136. if (m_buttons[(int)button] != state)
  137. (state ? m_pressed_buttons : m_released_buttons).insert(button);
  138. m_buttons[(int)button] = state;
  139. }
  140. void internal_set_axis(input::axis axis, float value)
  141. {
  142. if (m_axes[(int)axis] != value)
  143. m_changed_axes.insert(axis);
  144. m_axes[(int)axis] = value;
  145. }
  146. protected:
  147. std::string m_name;
  148. std::vector<std::string> m_key_names;
  149. std::vector<std::string> m_button_names;
  150. std::vector<std::string> m_axis_names;
  151. /** Key and button states (pressed/released) */
  152. std::vector<bool> m_keys;
  153. std::unordered_set<input::key> m_pressed_keys, m_released_keys;
  154. std::vector<bool> m_buttons;
  155. std::unordered_set<input::button> m_pressed_buttons, m_released_buttons;
  156. std::vector<float> m_axes;
  157. std::unordered_set<input::axis> m_changed_axes;
  158. };
  159. // Default devices
  160. static std::shared_ptr<class device::keyboard> keyboard() { return get()->m_keyboard; }
  161. static std::shared_ptr<class device::mouse> mouse() { return get()->m_mouse; }
  162. static std::shared_ptr<class device::joystick> joystick(int n);
  163. static std::vector<key> const &all_keys();
  164. static std::string const &key_to_name(key k);
  165. static key name_to_key(std::string const &name);
  166. private:
  167. input();
  168. static std::shared_ptr<input> get();
  169. std::shared_ptr<device::keyboard> m_keyboard;
  170. std::shared_ptr<device::mouse> m_mouse;
  171. std::map<int, std::shared_ptr<device::joystick>> m_joysticks;
  172. };
  173. //
  174. // The mouse class
  175. //
  176. class input::device::mouse : public input::device
  177. {
  178. public:
  179. mouse(std::string const &name) : input::device(name) {}
  180. // Gets and sets whether the mouse cursor should be captured.
  181. void capture(bool value) { m_capture = value; }
  182. bool capture() const { return m_capture; }
  183. private:
  184. // Capture mouse pointer
  185. bool m_capture = false;
  186. };
  187. //
  188. // The keyboard class
  189. //
  190. class input::device::keyboard : public input::device
  191. {
  192. public:
  193. keyboard(std::string const &name) : input::device(name) {}
  194. // Get the names of all available keys on this device
  195. std::vector<std::string> const& key_names() const { return m_key_names; }
  196. // Get the current state of all keys
  197. std::vector<bool> const &keys() const { return m_keys; }
  198. // Gets the latest contents of text input.
  199. std::string text();
  200. bool capture_text();
  201. void capture_text(bool status);
  202. void internal_add_text(std::string const &text)
  203. {
  204. m_text += text;
  205. }
  206. private:
  207. // Text input state
  208. std::string m_text;
  209. bool m_input_active = false;
  210. };
  211. //
  212. // The joystick class
  213. //
  214. class input::device::joystick : public input::device
  215. {
  216. public:
  217. joystick(std::string const &name) : input::device(name) {}
  218. };
  219. } /* namespace lol */