input.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. /// An abstract class template for an input device (a button, an analog input, etc.).
  15. template <typename StatusType>
  16. class InputDevice {
  17. public:
  18. virtual ~InputDevice() = default;
  19. virtual StatusType GetStatus() const {
  20. return {};
  21. }
  22. };
  23. /// An abstract class template for a factory that can create input devices.
  24. template <typename InputDeviceType>
  25. class Factory {
  26. public:
  27. virtual ~Factory() = default;
  28. virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0;
  29. };
  30. namespace Impl {
  31. template <typename InputDeviceType>
  32. using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>;
  33. template <typename InputDeviceType>
  34. struct FactoryList {
  35. static FactoryListType<InputDeviceType> list;
  36. };
  37. template <typename InputDeviceType>
  38. FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list;
  39. } // namespace Impl
  40. /**
  41. * Registers an input device factory.
  42. * @tparam InputDeviceType the type of input devices the factory can create
  43. * @param name the name of the factory. Will be used to match the "engine" parameter when creating
  44. * a device
  45. * @param factory the factory object to register
  46. */
  47. template <typename InputDeviceType>
  48. void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
  49. auto pair = std::make_pair(name, std::move(factory));
  50. if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
  51. LOG_ERROR(Input, "Factory '{}' already registered", name);
  52. }
  53. }
  54. /**
  55. * Unregisters an input device factory.
  56. * @tparam InputDeviceType the type of input devices the factory can create
  57. * @param name the name of the factory to unregister
  58. */
  59. template <typename InputDeviceType>
  60. void UnregisterFactory(const std::string& name) {
  61. if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
  62. LOG_ERROR(Input, "Factory '{}' not registered", name);
  63. }
  64. }
  65. /**
  66. * Create an input device from given paramters.
  67. * @tparam InputDeviceType the type of input devices to create
  68. * @param params a serialized ParamPackage string contains all parameters for creating the device
  69. */
  70. template <typename InputDeviceType>
  71. std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) {
  72. const Common::ParamPackage package(params);
  73. const std::string engine = package.Get("engine", "null");
  74. const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
  75. const auto pair = factory_list.find(engine);
  76. if (pair == factory_list.end()) {
  77. if (engine != "null") {
  78. LOG_ERROR(Input, "Unknown engine name: {}", engine);
  79. }
  80. return std::make_unique<InputDeviceType>();
  81. }
  82. return pair->second->Create(package);
  83. }
  84. /**
  85. * A button device is an input device that returns bool as status.
  86. * true for pressed; false for released.
  87. */
  88. using ButtonDevice = InputDevice<bool>;
  89. /**
  90. * An analog device is an input device that returns a tuple of x and y coordinates as status. The
  91. * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up
  92. * direction
  93. */
  94. using AnalogDevice = InputDevice<std::tuple<float, float>>;
  95. /**
  96. * A motion device is an input device that returns a tuple of accelerometer state vector and
  97. * gyroscope state vector.
  98. *
  99. * For both vectors:
  100. * x+ is the same direction as LEFT on D-pad.
  101. * y+ is normal to the touch screen, pointing outward.
  102. * z+ is the same direction as UP on D-pad.
  103. *
  104. * For accelerometer state vector
  105. * Units: g (gravitational acceleration)
  106. *
  107. * For gyroscope state vector:
  108. * Orientation is determined by right-hand rule.
  109. * Units: deg/sec
  110. */
  111. using MotionDevice = InputDevice<std::tuple<Math::Vec3<float>, Math::Vec3<float>>>;
  112. /**
  113. * A touch device is an input device that returns a tuple of two floats and a bool. The floats are
  114. * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed.
  115. */
  116. using TouchDevice = InputDevice<std::tuple<float, float, bool>>;
  117. } // namespace Input