input.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Copyright 2017 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <functional>
  6. #include <memory>
  7. #include <string>
  8. #include <unordered_map>
  9. #include <utility>
  10. #include "common/logging/log.h"
  11. #include "common/param_package.h"
  12. namespace Input {
  13. enum class InputType {
  14. None,
  15. Battery,
  16. Button,
  17. Stick,
  18. Analog,
  19. Trigger,
  20. Motion,
  21. Touch,
  22. Color,
  23. Vibration,
  24. Nfc,
  25. Ir,
  26. };
  27. enum class BatteryLevel {
  28. Empty,
  29. Critical,
  30. Low,
  31. Medium,
  32. Full,
  33. Charging,
  34. };
  35. enum class PollingMode {
  36. Active,
  37. Pasive,
  38. Camera,
  39. NCF,
  40. IR,
  41. };
  42. enum class VibrationError {
  43. None,
  44. NotSupported,
  45. Disabled,
  46. Unknown,
  47. };
  48. enum class PollingError {
  49. None,
  50. NotSupported,
  51. Unknown,
  52. };
  53. struct AnalogProperties {
  54. float deadzone{};
  55. float range{1.0f};
  56. float threshold{0.5f};
  57. float offset{};
  58. bool inverted{};
  59. };
  60. struct AnalogStatus {
  61. float value{};
  62. float raw_value{};
  63. AnalogProperties properties{};
  64. };
  65. struct ButtonStatus {
  66. bool value{};
  67. bool inverted{};
  68. bool toggle{};
  69. bool locked{};
  70. };
  71. using BatteryStatus = BatteryLevel;
  72. struct StickStatus {
  73. AnalogStatus x{};
  74. AnalogStatus y{};
  75. bool left{};
  76. bool right{};
  77. bool up{};
  78. bool down{};
  79. };
  80. struct TriggerStatus {
  81. AnalogStatus analog{};
  82. bool pressed{};
  83. };
  84. struct MotionSensor {
  85. AnalogStatus x{};
  86. AnalogStatus y{};
  87. AnalogStatus z{};
  88. };
  89. struct MotionStatus {
  90. MotionSensor gyro{};
  91. MotionSensor accel{};
  92. u64 delta_timestamp{};
  93. };
  94. struct TouchStatus {
  95. ButtonStatus pressed{};
  96. AnalogStatus x{};
  97. AnalogStatus y{};
  98. u32 id{};
  99. };
  100. struct BodyColorStatus {
  101. u32 body{};
  102. u32 buttons{};
  103. };
  104. struct VibrationStatus {
  105. f32 low_amplitude{};
  106. f32 low_frequency{};
  107. f32 high_amplitude{};
  108. f32 high_frequency{};
  109. };
  110. struct LedStatus {
  111. bool led_1{};
  112. bool led_2{};
  113. bool led_3{};
  114. bool led_4{};
  115. };
  116. struct CallbackStatus {
  117. InputType type{InputType::None};
  118. ButtonStatus button_status{};
  119. StickStatus stick_status{};
  120. AnalogStatus analog_status{};
  121. TriggerStatus trigger_status{};
  122. MotionStatus motion_status{};
  123. TouchStatus touch_status{};
  124. BodyColorStatus color_status{};
  125. BatteryStatus battery_status{};
  126. VibrationStatus vibration_status{};
  127. };
  128. struct InputCallback {
  129. std::function<void(CallbackStatus)> on_change;
  130. };
  131. /// An abstract class template for an input device (a button, an analog input, etc.).
  132. class InputDevice {
  133. public:
  134. virtual ~InputDevice() = default;
  135. void SetCallback(InputCallback callback_) {
  136. callback = std::move(callback_);
  137. }
  138. void TriggerOnChange(CallbackStatus status) {
  139. if (callback.on_change) {
  140. callback.on_change(status);
  141. }
  142. }
  143. private:
  144. InputCallback callback;
  145. };
  146. /// An abstract class template for an output device (rumble, LED pattern, polling mode).
  147. class OutputDevice {
  148. public:
  149. virtual ~OutputDevice() = default;
  150. virtual void SetLED([[maybe_unused]] LedStatus led_status) {
  151. return;
  152. }
  153. virtual VibrationError SetVibration([[maybe_unused]] VibrationStatus vibration_status) {
  154. return VibrationError::NotSupported;
  155. }
  156. virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
  157. return PollingError::NotSupported;
  158. }
  159. };
  160. /// An abstract class template for a factory that can create input devices.
  161. template <typename InputDeviceType>
  162. class Factory {
  163. public:
  164. virtual ~Factory() = default;
  165. virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0;
  166. };
  167. namespace Impl {
  168. template <typename InputDeviceType>
  169. using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>;
  170. template <typename InputDeviceType>
  171. struct FactoryList {
  172. static FactoryListType<InputDeviceType> list;
  173. };
  174. template <typename InputDeviceType>
  175. FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list;
  176. } // namespace Impl
  177. /**
  178. * Registers an input device factory.
  179. * @tparam InputDeviceType the type of input devices the factory can create
  180. * @param name the name of the factory. Will be used to match the "engine" parameter when creating
  181. * a device
  182. * @param factory the factory object to register
  183. */
  184. template <typename InputDeviceType>
  185. void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
  186. auto pair = std::make_pair(name, std::move(factory));
  187. if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
  188. LOG_ERROR(Input, "Factory '{}' already registered", name);
  189. }
  190. }
  191. /**
  192. * Unregisters an input device factory.
  193. * @tparam InputDeviceType the type of input devices the factory can create
  194. * @param name the name of the factory to unregister
  195. */
  196. template <typename InputDeviceType>
  197. void UnregisterFactory(const std::string& name) {
  198. if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
  199. LOG_ERROR(Input, "Factory '{}' not registered", name);
  200. }
  201. }
  202. /**
  203. * Create an input device from given paramters.
  204. * @tparam InputDeviceType the type of input devices to create
  205. * @param params a serialized ParamPackage string that contains all parameters for creating the
  206. * device
  207. */
  208. template <typename InputDeviceType>
  209. std::unique_ptr<InputDeviceType> CreateDeviceFromString(const std::string& params) {
  210. const Common::ParamPackage package(params);
  211. const std::string engine = package.Get("engine", "null");
  212. const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
  213. const auto pair = factory_list.find(engine);
  214. if (pair == factory_list.end()) {
  215. if (engine != "null") {
  216. LOG_ERROR(Input, "Unknown engine name: {}", engine);
  217. }
  218. return std::make_unique<InputDeviceType>();
  219. }
  220. return pair->second->Create(package);
  221. }
  222. /**
  223. * Create an input device from given paramters.
  224. * @tparam InputDeviceType the type of input devices to create
  225. * @param A ParamPackage that contains all parameters for creating the device
  226. */
  227. template <typename InputDeviceType>
  228. std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package) {
  229. const std::string engine = package.Get("engine", "null");
  230. const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
  231. const auto pair = factory_list.find(engine);
  232. if (pair == factory_list.end()) {
  233. if (engine != "null") {
  234. LOG_ERROR(Input, "Unknown engine name: {}", engine);
  235. }
  236. return std::make_unique<InputDeviceType>();
  237. }
  238. return pair->second->Create(package);
  239. }
  240. } // namespace Input