input.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "../higan-ui.hpp"
  2. #include "hotkeys.cpp"
  3. InputManager inputManager;
  4. Hotkeys& hotkeys = inputManager.hotkeys;
  5. auto InputButton::value() -> int16_t {
  6. auto value = device->group(groupID).input(inputID).value();
  7. if(device->isKeyboard() && groupID == HID::Keyboard::Button) {
  8. return value == 1;
  9. }
  10. if(device->isJoypad() && (groupID == HID::Joypad::Axis || groupID == HID::Joypad::Hat)) {
  11. if(qualifier == Qualifier::Lo && value < -16384) return 1;
  12. if(qualifier == Qualifier::Hi && value > +16384) return 1;
  13. return 0;
  14. }
  15. if(device->isJoypad() && groupID == HID::Joypad::Button) {
  16. return value == 1;
  17. }
  18. return 0;
  19. }
  20. //
  21. auto InputAxis::value() -> int16_t {
  22. if(!inputInstance.acquired()) return 0;
  23. auto value = device->group(groupID).input(inputID).value();
  24. if(device->isMouse() && groupID == HID::Mouse::Axis) {
  25. return value;
  26. }
  27. return 0;
  28. }
  29. //
  30. auto InputManager::bind(maybe<higan::Node::Object> newRoot) -> void {
  31. if(newRoot) root = newRoot();
  32. if(!root) return;
  33. for(auto& input : root->find<higan::Node::Input>()) {
  34. //not strictly necessary; but release any shared_pointer instances to free up the allocated memory
  35. input->setAttribute<shared_pointer<InputButton>>("instance");
  36. auto _pathID = input->attribute("pathID"); if(!_pathID) continue;
  37. auto _vendorID = input->attribute("vendorID"); if(!_vendorID) continue;
  38. auto _productID = input->attribute("productID"); if(!_productID) continue;
  39. auto pathID = _pathID.natural();
  40. auto vendorID = _vendorID.natural();
  41. auto productID = _productID.natural();
  42. for(auto& device : devices) {
  43. if(pathID != device->pathID()) continue;
  44. if(vendorID != device->vendorID()) continue;
  45. if(productID != device->productID()) continue;
  46. if(input->cast<higan::Node::Button>()) {
  47. auto instance = shared_pointer_make<InputButton>();
  48. instance->device = device;
  49. instance->groupID = input->attribute("groupID").natural();
  50. instance->inputID = input->attribute("inputID").natural();
  51. if(input->attribute("qualifier") == "Lo") instance->qualifier = InputButton::Qualifier::Lo;
  52. if(input->attribute("qualifier") == "Hi") instance->qualifier = InputButton::Qualifier::Hi;
  53. input->setAttribute<shared_pointer<InputButton>>("instance", instance);
  54. break;
  55. }
  56. if(input->cast<higan::Node::Axis>()) {
  57. auto instance = shared_pointer_make<InputAxis>();
  58. instance->device = device;
  59. instance->groupID = input->attribute("groupID").natural();
  60. instance->inputID = input->attribute("inputID").natural();
  61. input->setAttribute<shared_pointer<InputAxis>>("instance", instance);
  62. break;
  63. }
  64. }
  65. }
  66. }
  67. auto InputManager::unbind() -> void {
  68. this->root = {};
  69. }
  70. auto InputManager::poll() -> void {
  71. //polling actual hardware is very time-consuming: skip call if poll was called too recently
  72. auto thisPoll = chrono::millisecond();
  73. if(thisPoll - lastPoll < pollFrequency) return;
  74. lastPoll = thisPoll;
  75. //poll hardware, detect when the available devices have changed:
  76. //existing in-use devices may have been disconnected; or mapped but disconnected devices may now be available.
  77. //as such, when the returned devices tree changes, rebind all inputs
  78. auto devices = inputInstance.poll();
  79. bool changed = devices.size() != this->devices.size();
  80. if(!changed) {
  81. for(uint n : range(devices.size())) {
  82. if(changed = devices[n] != this->devices[n]) break;
  83. }
  84. }
  85. if(changed) {
  86. this->devices = devices;
  87. bind();
  88. }
  89. }
  90. auto InputManager::eventInput(shared_pointer<HID::Device> device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void {
  91. inputMapper.eventInput(device, group, input, oldValue, newValue);
  92. hotkeySettings.eventInput(device, group, input, oldValue, newValue);
  93. }