input_engine.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/logging/log.h"
  4. #include "input_common/input_engine.h"
  5. namespace InputCommon {
  6. void InputEngine::PreSetController(const PadIdentifier& identifier) {
  7. std::scoped_lock lock{mutex};
  8. controller_list.try_emplace(identifier);
  9. }
  10. void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) {
  11. std::scoped_lock lock{mutex};
  12. ControllerData& controller = controller_list.at(identifier);
  13. controller.buttons.try_emplace(button, false);
  14. }
  15. void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) {
  16. std::scoped_lock lock{mutex};
  17. ControllerData& controller = controller_list.at(identifier);
  18. controller.hat_buttons.try_emplace(button, u8{0});
  19. }
  20. void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) {
  21. std::scoped_lock lock{mutex};
  22. ControllerData& controller = controller_list.at(identifier);
  23. controller.axes.try_emplace(axis, 0.0f);
  24. }
  25. void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) {
  26. std::scoped_lock lock{mutex};
  27. ControllerData& controller = controller_list.at(identifier);
  28. controller.motions.try_emplace(motion);
  29. }
  30. void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) {
  31. {
  32. std::scoped_lock lock{mutex};
  33. ControllerData& controller = controller_list.at(identifier);
  34. if (!configuring) {
  35. controller.buttons.insert_or_assign(button, value);
  36. }
  37. }
  38. TriggerOnButtonChange(identifier, button, value);
  39. }
  40. void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) {
  41. {
  42. std::scoped_lock lock{mutex};
  43. ControllerData& controller = controller_list.at(identifier);
  44. if (!configuring) {
  45. controller.hat_buttons.insert_or_assign(button, value);
  46. }
  47. }
  48. TriggerOnHatButtonChange(identifier, button, value);
  49. }
  50. void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) {
  51. {
  52. std::scoped_lock lock{mutex};
  53. ControllerData& controller = controller_list.at(identifier);
  54. if (!configuring) {
  55. controller.axes.insert_or_assign(axis, value);
  56. }
  57. }
  58. TriggerOnAxisChange(identifier, axis, value);
  59. }
  60. void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value) {
  61. {
  62. std::scoped_lock lock{mutex};
  63. ControllerData& controller = controller_list.at(identifier);
  64. if (!configuring) {
  65. controller.battery = value;
  66. }
  67. }
  68. TriggerOnBatteryChange(identifier, value);
  69. }
  70. void InputEngine::SetColor(const PadIdentifier& identifier, Common::Input::BodyColorStatus value) {
  71. {
  72. std::scoped_lock lock{mutex};
  73. ControllerData& controller = controller_list.at(identifier);
  74. if (!configuring) {
  75. controller.color = value;
  76. }
  77. }
  78. TriggerOnColorChange(identifier, value);
  79. }
  80. void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) {
  81. {
  82. std::scoped_lock lock{mutex};
  83. ControllerData& controller = controller_list.at(identifier);
  84. if (!configuring) {
  85. controller.motions.insert_or_assign(motion, value);
  86. }
  87. }
  88. TriggerOnMotionChange(identifier, motion, value);
  89. }
  90. void InputEngine::SetCamera(const PadIdentifier& identifier,
  91. const Common::Input::CameraStatus& value) {
  92. {
  93. std::scoped_lock lock{mutex};
  94. ControllerData& controller = controller_list.at(identifier);
  95. if (!configuring) {
  96. controller.camera = value;
  97. }
  98. }
  99. TriggerOnCameraChange(identifier, value);
  100. }
  101. void InputEngine::SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value) {
  102. {
  103. std::scoped_lock lock{mutex};
  104. ControllerData& controller = controller_list.at(identifier);
  105. if (!configuring) {
  106. controller.nfc = value;
  107. }
  108. }
  109. TriggerOnNfcChange(identifier, value);
  110. }
  111. bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const {
  112. std::scoped_lock lock{mutex};
  113. const auto controller_iter = controller_list.find(identifier);
  114. if (controller_iter == controller_list.cend()) {
  115. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  116. identifier.pad, identifier.port);
  117. return false;
  118. }
  119. const ControllerData& controller = controller_iter->second;
  120. const auto button_iter = controller.buttons.find(button);
  121. if (button_iter == controller.buttons.cend()) {
  122. LOG_ERROR(Input, "Invalid button {}", button);
  123. return false;
  124. }
  125. return button_iter->second;
  126. }
  127. bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const {
  128. std::scoped_lock lock{mutex};
  129. const auto controller_iter = controller_list.find(identifier);
  130. if (controller_iter == controller_list.cend()) {
  131. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  132. identifier.pad, identifier.port);
  133. return false;
  134. }
  135. const ControllerData& controller = controller_iter->second;
  136. const auto hat_iter = controller.hat_buttons.find(button);
  137. if (hat_iter == controller.hat_buttons.cend()) {
  138. LOG_ERROR(Input, "Invalid hat button {}", button);
  139. return false;
  140. }
  141. return (hat_iter->second & direction) != 0;
  142. }
  143. f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const {
  144. std::scoped_lock lock{mutex};
  145. const auto controller_iter = controller_list.find(identifier);
  146. if (controller_iter == controller_list.cend()) {
  147. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  148. identifier.pad, identifier.port);
  149. return 0.0f;
  150. }
  151. const ControllerData& controller = controller_iter->second;
  152. const auto axis_iter = controller.axes.find(axis);
  153. if (axis_iter == controller.axes.cend()) {
  154. LOG_ERROR(Input, "Invalid axis {}", axis);
  155. return 0.0f;
  156. }
  157. return axis_iter->second;
  158. }
  159. Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const {
  160. std::scoped_lock lock{mutex};
  161. const auto controller_iter = controller_list.find(identifier);
  162. if (controller_iter == controller_list.cend()) {
  163. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  164. identifier.pad, identifier.port);
  165. return Common::Input::BatteryLevel::Charging;
  166. }
  167. const ControllerData& controller = controller_iter->second;
  168. return controller.battery;
  169. }
  170. Common::Input::BodyColorStatus InputEngine::GetColor(const PadIdentifier& identifier) const {
  171. std::scoped_lock lock{mutex};
  172. const auto controller_iter = controller_list.find(identifier);
  173. if (controller_iter == controller_list.cend()) {
  174. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  175. identifier.pad, identifier.port);
  176. return {};
  177. }
  178. const ControllerData& controller = controller_iter->second;
  179. return controller.color;
  180. }
  181. BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const {
  182. std::scoped_lock lock{mutex};
  183. const auto controller_iter = controller_list.find(identifier);
  184. if (controller_iter == controller_list.cend()) {
  185. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  186. identifier.pad, identifier.port);
  187. return {};
  188. }
  189. const ControllerData& controller = controller_iter->second;
  190. return controller.motions.at(motion);
  191. }
  192. Common::Input::CameraStatus InputEngine::GetCamera(const PadIdentifier& identifier) const {
  193. std::scoped_lock lock{mutex};
  194. const auto controller_iter = controller_list.find(identifier);
  195. if (controller_iter == controller_list.cend()) {
  196. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  197. identifier.pad, identifier.port);
  198. return {};
  199. }
  200. const ControllerData& controller = controller_iter->second;
  201. return controller.camera;
  202. }
  203. Common::Input::NfcStatus InputEngine::GetNfc(const PadIdentifier& identifier) const {
  204. std::scoped_lock lock{mutex};
  205. const auto controller_iter = controller_list.find(identifier);
  206. if (controller_iter == controller_list.cend()) {
  207. LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(),
  208. identifier.pad, identifier.port);
  209. return {};
  210. }
  211. const ControllerData& controller = controller_iter->second;
  212. return controller.nfc;
  213. }
  214. void InputEngine::ResetButtonState() {
  215. for (const auto& controller : controller_list) {
  216. for (const auto& button : controller.second.buttons) {
  217. SetButton(controller.first, button.first, false);
  218. }
  219. for (const auto& button : controller.second.hat_buttons) {
  220. SetHatButton(controller.first, button.first, 0);
  221. }
  222. }
  223. }
  224. void InputEngine::ResetAnalogState() {
  225. for (const auto& controller : controller_list) {
  226. for (const auto& axis : controller.second.axes) {
  227. SetAxis(controller.first, axis.first, 0.0);
  228. }
  229. }
  230. }
  231. void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) {
  232. std::scoped_lock lock{mutex_callback};
  233. for (const auto& poller_pair : callback_list) {
  234. const InputIdentifier& poller = poller_pair.second;
  235. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) {
  236. continue;
  237. }
  238. if (poller.callback.on_change) {
  239. poller.callback.on_change();
  240. }
  241. }
  242. if (!configuring || !mapping_callback.on_data) {
  243. return;
  244. }
  245. PreSetButton(identifier, button);
  246. if (value == GetButton(identifier, button)) {
  247. return;
  248. }
  249. mapping_callback.on_data(MappingData{
  250. .engine = GetEngineName(),
  251. .pad = identifier,
  252. .type = EngineInputType::Button,
  253. .index = button,
  254. .button_value = value,
  255. });
  256. }
  257. void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) {
  258. std::scoped_lock lock{mutex_callback};
  259. for (const auto& poller_pair : callback_list) {
  260. const InputIdentifier& poller = poller_pair.second;
  261. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) {
  262. continue;
  263. }
  264. if (poller.callback.on_change) {
  265. poller.callback.on_change();
  266. }
  267. }
  268. if (!configuring || !mapping_callback.on_data) {
  269. return;
  270. }
  271. for (std::size_t index = 1; index < 0xff; index <<= 1) {
  272. bool button_value = (value & index) != 0;
  273. if (button_value == GetHatButton(identifier, button, static_cast<u8>(index))) {
  274. continue;
  275. }
  276. mapping_callback.on_data(MappingData{
  277. .engine = GetEngineName(),
  278. .pad = identifier,
  279. .type = EngineInputType::HatButton,
  280. .index = button,
  281. .hat_name = GetHatButtonName(static_cast<u8>(index)),
  282. });
  283. }
  284. }
  285. void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) {
  286. std::scoped_lock lock{mutex_callback};
  287. for (const auto& poller_pair : callback_list) {
  288. const InputIdentifier& poller = poller_pair.second;
  289. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) {
  290. continue;
  291. }
  292. if (poller.callback.on_change) {
  293. poller.callback.on_change();
  294. }
  295. }
  296. if (!configuring || !mapping_callback.on_data) {
  297. return;
  298. }
  299. if (std::abs(value - GetAxis(identifier, axis)) < 0.5f) {
  300. return;
  301. }
  302. mapping_callback.on_data(MappingData{
  303. .engine = GetEngineName(),
  304. .pad = identifier,
  305. .type = EngineInputType::Analog,
  306. .index = axis,
  307. .axis_value = value,
  308. });
  309. }
  310. void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
  311. [[maybe_unused]] Common::Input::BatteryLevel value) {
  312. std::scoped_lock lock{mutex_callback};
  313. for (const auto& poller_pair : callback_list) {
  314. const InputIdentifier& poller = poller_pair.second;
  315. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) {
  316. continue;
  317. }
  318. if (poller.callback.on_change) {
  319. poller.callback.on_change();
  320. }
  321. }
  322. }
  323. void InputEngine::TriggerOnColorChange(const PadIdentifier& identifier,
  324. [[maybe_unused]] Common::Input::BodyColorStatus value) {
  325. std::scoped_lock lock{mutex_callback};
  326. for (const auto& poller_pair : callback_list) {
  327. const InputIdentifier& poller = poller_pair.second;
  328. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Color, 0)) {
  329. continue;
  330. }
  331. if (poller.callback.on_change) {
  332. poller.callback.on_change();
  333. }
  334. }
  335. }
  336. void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
  337. const BasicMotion& value) {
  338. std::scoped_lock lock{mutex_callback};
  339. for (const auto& poller_pair : callback_list) {
  340. const InputIdentifier& poller = poller_pair.second;
  341. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) {
  342. continue;
  343. }
  344. if (poller.callback.on_change) {
  345. poller.callback.on_change();
  346. }
  347. }
  348. if (!configuring || !mapping_callback.on_data) {
  349. return;
  350. }
  351. const auto old_value = GetMotion(identifier, motion);
  352. bool is_active = false;
  353. if (std::abs(value.accel_x - old_value.accel_x) > 1.5f ||
  354. std::abs(value.accel_y - old_value.accel_y) > 1.5f ||
  355. std::abs(value.accel_z - old_value.accel_z) > 1.5f) {
  356. is_active = true;
  357. }
  358. if (std::abs(value.gyro_x - old_value.gyro_x) > 0.6f ||
  359. std::abs(value.gyro_y - old_value.gyro_y) > 0.6f ||
  360. std::abs(value.gyro_z - old_value.gyro_z) > 0.6f) {
  361. is_active = true;
  362. }
  363. if (!is_active) {
  364. return;
  365. }
  366. mapping_callback.on_data(MappingData{
  367. .engine = GetEngineName(),
  368. .pad = identifier,
  369. .type = EngineInputType::Motion,
  370. .index = motion,
  371. .motion_value = value,
  372. });
  373. }
  374. void InputEngine::TriggerOnCameraChange(const PadIdentifier& identifier,
  375. [[maybe_unused]] const Common::Input::CameraStatus& value) {
  376. std::scoped_lock lock{mutex_callback};
  377. for (const auto& poller_pair : callback_list) {
  378. const InputIdentifier& poller = poller_pair.second;
  379. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Camera, 0)) {
  380. continue;
  381. }
  382. if (poller.callback.on_change) {
  383. poller.callback.on_change();
  384. }
  385. }
  386. }
  387. void InputEngine::TriggerOnNfcChange(const PadIdentifier& identifier,
  388. [[maybe_unused]] const Common::Input::NfcStatus& value) {
  389. std::scoped_lock lock{mutex_callback};
  390. for (const auto& poller_pair : callback_list) {
  391. const InputIdentifier& poller = poller_pair.second;
  392. if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Nfc, 0)) {
  393. continue;
  394. }
  395. if (poller.callback.on_change) {
  396. poller.callback.on_change();
  397. }
  398. }
  399. }
  400. bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier,
  401. const PadIdentifier& identifier, EngineInputType type,
  402. int index) const {
  403. if (input_identifier.type != type) {
  404. return false;
  405. }
  406. if (input_identifier.index != index) {
  407. return false;
  408. }
  409. if (input_identifier.identifier != identifier) {
  410. return false;
  411. }
  412. return true;
  413. }
  414. void InputEngine::BeginConfiguration() {
  415. configuring = true;
  416. }
  417. void InputEngine::EndConfiguration() {
  418. configuring = false;
  419. }
  420. const std::string& InputEngine::GetEngineName() const {
  421. return input_engine;
  422. }
  423. int InputEngine::SetCallback(InputIdentifier input_identifier) {
  424. std::scoped_lock lock{mutex_callback};
  425. callback_list.insert_or_assign(last_callback_key, std::move(input_identifier));
  426. return last_callback_key++;
  427. }
  428. void InputEngine::SetMappingCallback(MappingCallback callback) {
  429. std::scoped_lock lock{mutex_callback};
  430. mapping_callback = std::move(callback);
  431. }
  432. void InputEngine::DeleteCallback(int key) {
  433. std::scoped_lock lock{mutex_callback};
  434. const auto& iterator = callback_list.find(key);
  435. if (iterator == callback_list.end()) {
  436. LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
  437. return;
  438. }
  439. callback_list.erase(iterator);
  440. }
  441. } // namespace InputCommon