input.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 <memory>
  6. #include <string>
  7. #include <tuple>
  8. #include <unordered_map>
  9. #include <utility>
  10. #include "common/logging/log.h"
  11. #include "common/param_package.h"
  12. #include "common/vector_math.h"
  13. namespace Input {
  14. enum class AnalogDirection : u8 {
  15. RIGHT,
  16. LEFT,
  17. UP,
  18. DOWN,
  19. };
  20. /// An abstract class template for an input device (a button, an analog input, etc.).
  21. template <typename StatusType>
  22. class InputDevice {
  23. public:
  24. virtual ~InputDevice() = default;
  25. virtual StatusType GetStatus() const {
  26. return {};
  27. }
  28. virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
  29. return {};
  30. }
  31. virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const {
  32. return {};
  33. }
  34. };
  35. /// An abstract class template for a factory that can create input devices.
  36. template <typename InputDeviceType>
  37. class Factory {
  38. public:
  39. virtual ~Factory() = default;
  40. virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0;
  41. };
  42. namespace Impl {
  43. template <typename InputDeviceType>
  44. using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>;
  45. template <typename InputDeviceType>
  46. struct FactoryList {
  47. static FactoryListType<InputDeviceType> list;
  48. };
  49. template <typename InputDeviceType>
  50. FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list;
  51. } // namespace Impl
  52. /**
  53. * Registers an input device factory.
  54. * @tparam InputDeviceType the type of input devices the factory can create
  55. * @param name the name of the factory. Will be used to match the "engine" parameter when creating
  56. * a device
  57. * @param factory the factory object to register
  58. */
  59. template <typename InputDeviceType>
  60. void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
  61. auto pair = std::make_pair(name, std::move(factory));
  62. if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
  63. LOG_ERROR(Input, "Factory '{}' already registered", name);
  64. }
  65. }
  66. /**
  67. * Unregisters an input device factory.
  68. * @tparam InputDeviceType the type of input devices the factory can create
  69. * @param name the name of the factory to unregister
  70. */
  71. template <typename InputDeviceType>
  72. void UnregisterFactory(const std::string& name) {
  73. if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
  74. LOG_ERROR(Input, "Factory '{}' not registered", name);
  75. }
  76. }
  77. /**
  78. * Create an input device from given paramters.
  79. * @tparam InputDeviceType the type of input devices to create
  80. * @param params a serialized ParamPackage string contains all parameters for creating the device
  81. */
  82. template <typename InputDeviceType>
  83. std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) {
  84. const Common::ParamPackage package(params);
  85. const std::string engine = package.Get("engine", "null");
  86. const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
  87. const auto pair = factory_list.find(engine);
  88. if (pair == factory_list.end()) {
  89. if (engine != "null") {
  90. LOG_ERROR(Input, "Unknown engine name: {}", engine);
  91. }
  92. return std::make_unique<InputDeviceType>();
  93. }
  94. return pair->second->Create(package);
  95. }
  96. /**
  97. * A button device is an input device that returns bool as status.
  98. * true for pressed; false for released.
  99. */
  100. using ButtonDevice = InputDevice<bool>;
  101. /**
  102. * An analog device is an input device that returns a tuple of x and y coordinates as status. The
  103. * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up
  104. * direction
  105. */
  106. using AnalogDevice = InputDevice<std::tuple<float, float>>;
  107. /**
  108. * A vibration device is an input device that returns an unsigned byte as status.
  109. * It represents whether the vibration device supports vibration or not.
  110. * If the status returns 1, it supports vibration. Otherwise, it does not support vibration.
  111. */
  112. using VibrationDevice = InputDevice<u8>;
  113. /**
  114. * A motion status is an object that returns a tuple of accelerometer state vector,
  115. * gyroscope state vector, rotation state vector and orientation state matrix.
  116. *
  117. * For both vectors:
  118. * x+ is the same direction as RIGHT on D-pad.
  119. * y+ is normal to the touch screen, pointing outward.
  120. * z+ is the same direction as UP on D-pad.
  121. *
  122. * For accelerometer state vector
  123. * Units: g (gravitational acceleration)
  124. *
  125. * For gyroscope state vector:
  126. * Orientation is determined by right-hand rule.
  127. * Units: deg/sec
  128. *
  129. * For rotation state vector
  130. * Units: rotations
  131. *
  132. * For orientation state matrix
  133. * x vector
  134. * y vector
  135. * z vector
  136. */
  137. using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>,
  138. std::array<Common::Vec3f, 3>>;
  139. /**
  140. * A motion device is an input device that returns a motion status object
  141. */
  142. using MotionDevice = InputDevice<MotionStatus>;
  143. /**
  144. * A touch status is an object that returns a tuple of two floats and a bool. The floats are
  145. * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed.
  146. */
  147. using TouchStatus = std::tuple<float, float, bool>;
  148. /**
  149. * A touch device is an input device that returns a touch status object
  150. */
  151. using TouchDevice = InputDevice<TouchStatus>;
  152. /**
  153. * A mouse device is an input device that returns a tuple of two floats and four ints.
  154. * The first two floats are X and Y device coordinates of the mouse (from 0-1).
  155. * The s32s are the mouse wheel.
  156. */
  157. using MouseDevice = InputDevice<std::tuple<float, float, s32, s32>>;
  158. } // namespace Input