joystick_controller.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. Minetest
  3. Copyright (C) 2016 est31, <MTest31@outlook.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. #include "joystick_controller.h"
  17. #include "irrlichttypes_extrabloated.h"
  18. #include "keys.h"
  19. #include "settings.h"
  20. #include "gettime.h"
  21. bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
  22. {
  23. u32 buttons = ev.ButtonStates;
  24. buttons &= filter_mask;
  25. return buttons == compare_mask;
  26. }
  27. bool JoystickAxisCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
  28. {
  29. s16 ax_val = ev.Axis[axis_to_compare];
  30. return (ax_val * direction < 0) && (thresh * direction > ax_val * direction);
  31. }
  32. // spares many characters
  33. #define JLO_B_PB(A, B, C) jlo.button_keys.push_back(JoystickButtonCmb(A, B, C))
  34. #define JLO_A_PB(A, B, C, D) jlo.axis_keys.push_back(JoystickAxisCmb(A, B, C, D))
  35. static JoystickLayout create_default_layout()
  36. {
  37. JoystickLayout jlo;
  38. jlo.axes_dead_border = 1024;
  39. const JoystickAxisLayout axes[JA_COUNT] = {
  40. {0, 1}, // JA_SIDEWARD_MOVE
  41. {1, 1}, // JA_FORWARD_MOVE
  42. {3, 1}, // JA_FRUSTUM_HORIZONTAL
  43. {4, 1}, // JA_FRUSTUM_VERTICAL
  44. };
  45. memcpy(jlo.axes, axes, sizeof(jlo.axes));
  46. u32 sb = 1 << 7; // START button mask
  47. u32 fb = 1 << 3; // FOUR button mask
  48. u32 bm = sb | fb; // Mask for Both Modifiers
  49. // The back button means "ESC".
  50. JLO_B_PB(KeyType::ESC, 1 << 6, 1 << 6);
  51. // The start button counts as modifier as well as use key.
  52. // JLO_B_PB(KeyType::USE, sb, sb));
  53. // Accessible without start modifier button pressed
  54. // regardless whether four is pressed or not
  55. JLO_B_PB(KeyType::SNEAK, sb | 1 << 2, 1 << 2);
  56. // Accessible without four modifier button pressed
  57. // regardless whether start is pressed or not
  58. JLO_B_PB(KeyType::MOUSE_L, fb | 1 << 4, 1 << 4);
  59. JLO_B_PB(KeyType::MOUSE_R, fb | 1 << 5, 1 << 5);
  60. // Accessible without any modifier pressed
  61. JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0);
  62. JLO_B_PB(KeyType::SPECIAL1, bm | 1 << 1, 1 << 1);
  63. // Accessible with start button not pressed, but four pressed
  64. // TODO find usage for button 0
  65. JLO_B_PB(KeyType::DROP, bm | 1 << 1, fb | 1 << 1);
  66. JLO_B_PB(KeyType::SCROLL_UP, bm | 1 << 4, fb | 1 << 4);
  67. JLO_B_PB(KeyType::SCROLL_DOWN,bm | 1 << 5, fb | 1 << 5);
  68. // Accessible with start button and four pressed
  69. // TODO find usage for buttons 0, 1 and 4, 5
  70. // Now about the buttons simulated by the axes
  71. // Movement buttons, important for vessels
  72. JLO_A_PB(KeyType::FORWARD, 1, 1, 1024);
  73. JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024);
  74. JLO_A_PB(KeyType::LEFT, 0, 1, 1024);
  75. JLO_A_PB(KeyType::RIGHT, 0, -1, 1024);
  76. // Scroll buttons
  77. JLO_A_PB(KeyType::SCROLL_UP, 2, -1, 1024);
  78. JLO_A_PB(KeyType::SCROLL_DOWN, 5, -1, 1024);
  79. return jlo;
  80. }
  81. static const JoystickLayout default_layout = create_default_layout();
  82. JoystickController::JoystickController()
  83. {
  84. m_layout = &default_layout;
  85. doubling_dtime = g_settings->getFloat("repeat_joystick_button_time");
  86. for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
  87. m_past_pressed_time[i] = 0;
  88. }
  89. clear();
  90. }
  91. bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
  92. {
  93. m_internal_time = getTimeMs() / 1000.f;
  94. std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed;
  95. // First generate a list of keys pressed
  96. for (size_t i = 0; i < m_layout->button_keys.size(); i++) {
  97. if (m_layout->button_keys[i].isTriggered(ev)) {
  98. keys_pressed.set(m_layout->button_keys[i].key);
  99. }
  100. }
  101. for (size_t i = 0; i < m_layout->axis_keys.size(); i++) {
  102. if (m_layout->axis_keys[i].isTriggered(ev)) {
  103. keys_pressed.set(m_layout->axis_keys[i].key);
  104. }
  105. }
  106. // Then update the values
  107. for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
  108. if (keys_pressed[i]) {
  109. if (!m_past_pressed_keys[i] &&
  110. m_past_pressed_time[i] < m_internal_time - doubling_dtime) {
  111. m_past_pressed_keys[i] = true;
  112. m_past_pressed_time[i] = m_internal_time;
  113. }
  114. } else if (m_pressed_keys[i]) {
  115. m_past_released_keys[i] = true;
  116. }
  117. m_pressed_keys[i] = keys_pressed[i];
  118. }
  119. for (size_t i = 0; i < JA_COUNT; i++) {
  120. const JoystickAxisLayout &ax_la = m_layout->axes[i];
  121. m_axes_vals[i] = ax_la.invert * ev.Axis[ax_la.axis_id];
  122. }
  123. return true;
  124. }
  125. void JoystickController::clear()
  126. {
  127. m_pressed_keys.reset();
  128. m_past_pressed_keys.reset();
  129. m_past_released_keys.reset();
  130. memset(m_axes_vals, 0, sizeof(m_axes_vals));
  131. }
  132. s16 JoystickController::getAxisWithoutDead(JoystickAxis axis)
  133. {
  134. s16 v = m_axes_vals[axis];
  135. if (((v > 0) && (v < m_layout->axes_dead_border)) ||
  136. ((v < 0) && (v > -m_layout->axes_dead_border)))
  137. return 0;
  138. return v;
  139. }