💿🐜 Antkeeper source code https://antkeeper.com
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.

299 lines
8.4 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "input/control-map.hpp"
  20. #include <algorithm>
  21. #include <cmath>
  22. #include <type_traits>
  23. #include <utility>
  24. namespace input {
  25. void control_map::connect(::event::queue& queue)
  26. {
  27. subscriptions.emplace_back(queue.subscribe<gamepad_axis_moved_event>(std::bind_front(&control_map::handle_gamepad_axis_moved, this)));
  28. subscriptions.emplace_back(queue.subscribe<gamepad_button_pressed_event>(std::bind_front(&control_map::handle_gamepad_button_pressed, this)));
  29. subscriptions.emplace_back(queue.subscribe<gamepad_button_released_event>(std::bind_front(&control_map::handle_gamepad_button_released, this)));
  30. subscriptions.emplace_back(queue.subscribe<key_pressed_event>(std::bind_front(&control_map::handle_key_pressed, this)));
  31. subscriptions.emplace_back(queue.subscribe<key_released_event>(std::bind_front(&control_map::handle_key_released, this)));
  32. subscriptions.emplace_back(queue.subscribe<mouse_button_pressed_event>(std::bind_front(&control_map::handle_mouse_button_pressed, this)));
  33. subscriptions.emplace_back(queue.subscribe<mouse_button_released_event>(std::bind_front(&control_map::handle_mouse_button_released, this)));
  34. subscriptions.emplace_back(queue.subscribe<mouse_moved_event>(std::bind_front(&control_map::handle_mouse_moved, this)));
  35. subscriptions.emplace_back(queue.subscribe<mouse_scrolled_event>(std::bind_front(&control_map::handle_mouse_scrolled, this)));
  36. }
  37. void control_map::disconnect()
  38. {
  39. subscriptions.clear();
  40. }
  41. void control_map::add_mapping(control& control, const mapping& mapping)
  42. {
  43. switch (mapping.get_mapping_type())
  44. {
  45. case mapping_type::gamepad_axis:
  46. add_mapping(control, static_cast<const gamepad_axis_mapping&>(mapping));
  47. break;
  48. case mapping_type::gamepad_button:
  49. add_mapping(control, static_cast<const gamepad_button_mapping&>(mapping));
  50. break;
  51. case mapping_type::key:
  52. add_mapping(control, static_cast<const key_mapping&>(mapping));
  53. break;
  54. case mapping_type::mouse_button:
  55. add_mapping(control, static_cast<const mouse_button_mapping&>(mapping));
  56. break;
  57. case mapping_type::mouse_motion:
  58. add_mapping(control, static_cast<const mouse_motion_mapping&>(mapping));
  59. break;
  60. case mapping_type::mouse_scroll:
  61. add_mapping(control, static_cast<const mouse_scroll_mapping&>(mapping));
  62. break;
  63. default:
  64. //std::unreachable();
  65. break;
  66. }
  67. }
  68. void control_map::add_mapping(control& control, gamepad_axis_mapping&& mapping)
  69. {
  70. gamepad_axis_mappings.emplace_back(&control, mapping);
  71. }
  72. void control_map::add_mapping(control& control, gamepad_button_mapping&& mapping)
  73. {
  74. gamepad_button_mappings.emplace_back(&control, mapping);
  75. }
  76. void control_map::add_mapping(control& control, key_mapping&& mapping)
  77. {
  78. key_mappings.emplace_back(&control, mapping);
  79. }
  80. void control_map::add_mapping(control& control, mouse_button_mapping&& mapping)
  81. {
  82. mouse_button_mappings.emplace_back(&control, mapping);
  83. }
  84. void control_map::add_mapping(control& control, mouse_motion_mapping&& mapping)
  85. {
  86. mouse_motion_mappings.emplace_back(&control, mapping);
  87. }
  88. void control_map::add_mapping(control& control, mouse_scroll_mapping&& mapping)
  89. {
  90. mouse_scroll_mappings.emplace_back(&control, mapping);
  91. }
  92. void control_map::remove_mappings(control& control, mapping_type type)
  93. {
  94. auto predicate = [&](const auto& tuple) -> bool
  95. {
  96. return std::get<0>(tuple) == &control;
  97. };
  98. switch (type)
  99. {
  100. case mapping_type::gamepad_axis:
  101. std::erase_if(gamepad_axis_mappings, predicate);
  102. break;
  103. case mapping_type::gamepad_button:
  104. std::erase_if(gamepad_button_mappings, predicate);
  105. break;
  106. case mapping_type::key:
  107. std::erase_if(key_mappings, predicate);
  108. break;
  109. case mapping_type::mouse_button:
  110. std::erase_if(mouse_button_mappings, predicate);
  111. break;
  112. case mapping_type::mouse_motion:
  113. std::erase_if(mouse_motion_mappings, predicate);
  114. break;
  115. case mapping_type::mouse_scroll:
  116. std::erase_if(mouse_scroll_mappings, predicate);
  117. break;
  118. default:
  119. //std::unreachable();
  120. break;
  121. }
  122. }
  123. void control_map::remove_mappings(control& control)
  124. {
  125. auto predicate = [&](const auto& tuple) -> bool
  126. {
  127. return std::get<0>(tuple) == &control;
  128. };
  129. std::erase_if(gamepad_axis_mappings, predicate);
  130. std::erase_if(gamepad_button_mappings, predicate);
  131. std::erase_if(key_mappings, predicate);
  132. std::erase_if(mouse_button_mappings, predicate);
  133. std::erase_if(mouse_motion_mappings, predicate);
  134. std::erase_if(mouse_scroll_mappings, predicate);
  135. }
  136. void control_map::remove_mappings()
  137. {
  138. gamepad_axis_mappings.clear();
  139. gamepad_button_mappings.clear();
  140. key_mappings.clear();
  141. mouse_button_mappings.clear();
  142. mouse_motion_mappings.clear();
  143. mouse_scroll_mappings.clear();
  144. }
  145. void control_map::handle_gamepad_axis_moved(const gamepad_axis_moved_event& event)
  146. {
  147. for (const auto& [control, mapping]: gamepad_axis_mappings)
  148. {
  149. if (mapping.axis == event.axis &&
  150. (!mapping.gamepad || mapping.gamepad == event.gamepad))
  151. {
  152. if (std::signbit(event.position) == mapping.direction)
  153. {
  154. control->evaluate(std::abs(event.position));
  155. }
  156. else
  157. {
  158. control->evaluate(0.0f);
  159. }
  160. }
  161. }
  162. }
  163. void control_map::handle_gamepad_button_pressed(const gamepad_button_pressed_event& event)
  164. {
  165. for (const auto& [control, mapping]: gamepad_button_mappings)
  166. {
  167. if (mapping.button == event.button &&
  168. (!mapping.gamepad || mapping.gamepad == event.gamepad))
  169. {
  170. control->evaluate(1.0f);
  171. }
  172. }
  173. }
  174. void control_map::handle_gamepad_button_released(const gamepad_button_released_event& event)
  175. {
  176. for (const auto& [control, mapping]: gamepad_button_mappings)
  177. {
  178. if (mapping.button == event.button &&
  179. (!mapping.gamepad || mapping.gamepad == event.gamepad))
  180. {
  181. control->evaluate(0.0f);
  182. }
  183. }
  184. }
  185. void control_map::handle_key_pressed(const key_pressed_event& event)
  186. {
  187. for (const auto& [control, mapping]: key_mappings)
  188. {
  189. if (mapping.scancode == event.scancode &&
  190. (!mapping.keyboard || mapping.keyboard == event.keyboard))
  191. {
  192. control->evaluate(1.0f);
  193. }
  194. }
  195. }
  196. void control_map::handle_key_released(const key_released_event& event)
  197. {
  198. for (const auto& [control, mapping]: key_mappings)
  199. {
  200. if (mapping.scancode == event.scancode &&
  201. (!mapping.keyboard || mapping.keyboard == event.keyboard))
  202. {
  203. control->evaluate(0.0f);
  204. }
  205. }
  206. }
  207. void control_map::handle_mouse_moved(const mouse_moved_event& event)
  208. {
  209. for (const auto& [control, mapping]: mouse_motion_mappings)
  210. {
  211. if (!mapping.mouse || mapping.mouse == event.mouse)
  212. {
  213. const float difference = static_cast<float>(event.difference[static_cast<std::underlying_type_t<mouse_motion_axis>>(mapping.axis)]);
  214. if (difference && std::signbit(difference) == mapping.direction)
  215. {
  216. control->evaluate(std::abs(difference));
  217. control->evaluate(0.0f);
  218. }
  219. }
  220. }
  221. }
  222. void control_map::handle_mouse_scrolled(const mouse_scrolled_event& event)
  223. {
  224. for (const auto& [control, mapping]: mouse_scroll_mappings)
  225. {
  226. if (!mapping.mouse || mapping.mouse == event.mouse)
  227. {
  228. const auto velocity = event.velocity[static_cast<std::underlying_type_t<mouse_scroll_axis>>(mapping.axis)];
  229. if (velocity && std::signbit(velocity) == mapping.direction)
  230. {
  231. control->evaluate(std::abs(velocity));
  232. control->evaluate(0.0f);
  233. }
  234. }
  235. }
  236. }
  237. void control_map::handle_mouse_button_pressed(const mouse_button_pressed_event& event)
  238. {
  239. for (const auto& [control, mapping]: mouse_button_mappings)
  240. {
  241. if (mapping.button == event.button &&
  242. (!mapping.mouse || mapping.mouse == event.mouse))
  243. {
  244. control->evaluate(1.0f);
  245. }
  246. }
  247. }
  248. void control_map::handle_mouse_button_released(const mouse_button_released_event& event)
  249. {
  250. for (const auto& [control, mapping]: mouse_button_mappings)
  251. {
  252. if (mapping.button == event.button &&
  253. (!mapping.mouse || mapping.mouse == event.mouse))
  254. {
  255. control->evaluate(0.0f);
  256. }
  257. }
  258. }
  259. } // namespace input