input_device.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright (c) 2012-2024 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "core/error/error.h"
  6. #include "core/math/constants.h"
  7. #include "core/math/math.h"
  8. #include "core/math/vector3.inl"
  9. #include "core/memory/allocator.h"
  10. #include "core/memory/memory.inl"
  11. #include "core/strings/string.inl"
  12. #include "core/strings/string_id.inl"
  13. #include "device/input_device.h"
  14. #include <string.h> // strcpy, memset
  15. #define CE_BUTTON_STATE_MASK 0x01
  16. #define CE_BUTTON_STATE_SHIFT 0
  17. #define CE_BUTTON_MASK 0xc0
  18. #define CE_BUTTON_SHIFT 6
  19. #define CE_BUTTON_PRESSED 0x40
  20. #define CE_BUTTON_RELEASED 0x80
  21. namespace crown
  22. {
  23. const char *InputDevice::name() const
  24. {
  25. return _name;
  26. }
  27. bool InputDevice::connected() const
  28. {
  29. return _connected;
  30. }
  31. u8 InputDevice::num_buttons() const
  32. {
  33. return _num_buttons;
  34. }
  35. u8 InputDevice::num_axes() const
  36. {
  37. return _num_axes;
  38. }
  39. bool InputDevice::pressed(u8 id) const
  40. {
  41. return id < _num_buttons
  42. ? (_state[id] & CE_BUTTON_PRESSED) != 0
  43. : false
  44. ;
  45. }
  46. bool InputDevice::released(u8 id) const
  47. {
  48. return id < _num_buttons
  49. ? (_state[id] & CE_BUTTON_RELEASED) != 0
  50. : false
  51. ;
  52. }
  53. u8 InputDevice::any_pressed() const
  54. {
  55. return pressed(_first_button[1]) ? _first_button[1] : UINT8_MAX;
  56. }
  57. u8 InputDevice::any_released() const
  58. {
  59. return released(_first_button[0]) ? _first_button[0] : UINT8_MAX;
  60. }
  61. f32 InputDevice::button(u8 id) const
  62. {
  63. return id < _num_buttons
  64. ? f32((_state[id] & CE_BUTTON_STATE_MASK) >> CE_BUTTON_STATE_SHIFT)
  65. : 0.0f
  66. ;
  67. }
  68. Vector3 InputDevice::axis(u8 id) const
  69. {
  70. if (id >= _num_axes)
  71. return VECTOR3_ZERO;
  72. return _axis[id];
  73. }
  74. const char *InputDevice::button_name(u8 id) const
  75. {
  76. return id < _num_buttons
  77. ? _button_name[id]
  78. : NULL
  79. ;
  80. }
  81. const char *InputDevice::axis_name(u8 id) const
  82. {
  83. return id < _num_axes
  84. ? _axis_name[id]
  85. : NULL
  86. ;
  87. }
  88. u8 InputDevice::button_id(StringId32 name) const
  89. {
  90. for (u32 i = 0; i < _num_buttons; ++i) {
  91. if (_button_hash[i] == name)
  92. return i;
  93. }
  94. return UINT8_MAX;
  95. }
  96. u8 InputDevice::axis_id(StringId32 name) const
  97. {
  98. for (u32 i = 0; i < _num_axes; ++i) {
  99. if (_axis_hash[i] == name)
  100. return i;
  101. }
  102. return UINT8_MAX;
  103. }
  104. f32 InputDevice::deadzone(u8 id, DeadzoneMode::Enum *deadzone_mode) const
  105. {
  106. if (id < _num_axes) {
  107. *deadzone_mode = (DeadzoneMode::Enum)_deadzone_mode[id];
  108. return _deadzone_size[id];
  109. } else {
  110. *deadzone_mode = DeadzoneMode::COUNT;
  111. return 0.0f;
  112. }
  113. }
  114. void InputDevice::set_deadzone(u8 id, DeadzoneMode::Enum deadzone_mode, f32 deadzone_size)
  115. {
  116. if (id < _num_axes) {
  117. _deadzone_mode[id] = deadzone_mode;
  118. _deadzone_size[id] = deadzone_size;
  119. }
  120. }
  121. void InputDevice::set_button(u8 id, u8 state)
  122. {
  123. CE_ASSERT(id < _num_buttons, "Index out of bounds");
  124. bool pressed = (_state[id] & CE_BUTTON_STATE_MASK) >> CE_BUTTON_STATE_SHIFT == 1;
  125. if (pressed && state == 0)
  126. _state[id] |= CE_BUTTON_RELEASED;
  127. if (!pressed && state == 1)
  128. _state[id] |= CE_BUTTON_PRESSED;
  129. _state[id] = (_state[id] & ~(1 << CE_BUTTON_STATE_SHIFT))
  130. | (state << CE_BUTTON_STATE_SHIFT);
  131. if (_first_button[state % countof(_first_button)] == UINT8_MAX)
  132. _first_button[state % countof(_first_button)] = id;
  133. }
  134. void InputDevice::set_axis(u8 id, f32 x, f32 y, f32 z)
  135. {
  136. CE_ASSERT(id < _num_axes, "Index out of bounds");
  137. _axis[id].x = x;
  138. _axis[id].y = y;
  139. _axis[id].z = z;
  140. }
  141. void InputDevice::update()
  142. {
  143. for (u32 ii = 0; ii < _num_buttons; ++ii)
  144. _state[ii] &= ~CE_BUTTON_MASK;
  145. _first_button[0] = UINT8_MAX;
  146. _first_button[1] = UINT8_MAX;
  147. }
  148. namespace input_device
  149. {
  150. InputDevice *create(Allocator &a, const char *name, u8 num_buttons, u8 num_axes, const char **button_names, const char **axis_names)
  151. {
  152. const u32 size = 0
  153. + sizeof(InputDevice) + alignof(InputDevice)
  154. + sizeof(u8)*num_buttons*2 + alignof(u8)
  155. + sizeof(Vector3)*num_axes + alignof(Vector3)
  156. + sizeof(u32)*num_axes + alignof(u32)
  157. + sizeof(f32)*num_axes + alignof(f32)
  158. + sizeof(StringId32)*num_buttons + alignof(StringId32)
  159. + sizeof(StringId32)*num_axes + alignof(StringId32)
  160. + strlen32(name) + 1 + alignof(char)
  161. ;
  162. InputDevice *id = (InputDevice *)a.allocate(size);
  163. id->_connected = false;
  164. id->_num_buttons = num_buttons;
  165. id->_num_axes = num_axes;
  166. id->_first_button[0] = UINT8_MAX;
  167. id->_first_button[1] = UINT8_MAX;
  168. id->_button_name = button_names;
  169. id->_axis_name = axis_names;
  170. id->_state = (u8 * )&id[1];
  171. id->_axis = (Vector3 * )memory::align_top(id->_state + num_buttons, alignof(Vector3));
  172. id->_deadzone_mode = (u32 * )memory::align_top(id->_axis + num_axes, alignof(u32));
  173. id->_deadzone_size = (f32 * )memory::align_top(id->_deadzone_mode + num_axes, alignof(f32));
  174. id->_button_hash = (StringId32 *)memory::align_top(id->_deadzone_size + num_axes, alignof(StringId32));
  175. id->_axis_hash = (StringId32 *)memory::align_top(id->_button_hash + num_buttons, alignof(StringId32));
  176. id->_name = (char * )memory::align_top(id->_axis_hash + num_axes, alignof(char));
  177. id->_lua_object = 0;
  178. memset(id->_state, 0, sizeof(u8)*num_buttons);
  179. memset(id->_axis, 0, sizeof(Vector3)*num_axes);
  180. memset(id->_deadzone_mode, 0, sizeof(*id->_deadzone_mode)*num_axes);
  181. memset(id->_deadzone_size, 0, sizeof(*id->_deadzone_size)*num_axes);
  182. for (u32 i = 0; i < num_buttons; ++i)
  183. id->_button_hash[i] = StringId32(button_names[i]);
  184. for (u32 i = 0; i < num_axes; ++i)
  185. id->_axis_hash[i] = StringId32(axis_names[i]);
  186. strcpy(id->_name, name);
  187. return id;
  188. }
  189. void destroy(Allocator &a, InputDevice &id)
  190. {
  191. a.deallocate(&id);
  192. }
  193. } // namespace input_device
  194. } // namespace crown