| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- // Copyright 2017 Citra Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #pragma once
- #include <memory>
- #include <string>
- #include <tuple>
- #include <unordered_map>
- #include <utility>
- #include "common/logging/log.h"
- #include "common/param_package.h"
- #include "common/vector_math.h"
- namespace Input {
- enum class AnalogDirection : u8 {
- RIGHT,
- LEFT,
- UP,
- DOWN,
- };
- /// An abstract class template for an input device (a button, an analog input, etc.).
- template <typename StatusType>
- class InputDevice {
- public:
- virtual ~InputDevice() = default;
- virtual StatusType GetStatus() const {
- return {};
- }
- virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
- return {};
- }
- virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const {
- return {};
- }
- };
- /// An abstract class template for a factory that can create input devices.
- template <typename InputDeviceType>
- class Factory {
- public:
- virtual ~Factory() = default;
- virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0;
- };
- namespace Impl {
- template <typename InputDeviceType>
- using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>;
- template <typename InputDeviceType>
- struct FactoryList {
- static FactoryListType<InputDeviceType> list;
- };
- template <typename InputDeviceType>
- FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list;
- } // namespace Impl
- /**
- * Registers an input device factory.
- * @tparam InputDeviceType the type of input devices the factory can create
- * @param name the name of the factory. Will be used to match the "engine" parameter when creating
- * a device
- * @param factory the factory object to register
- */
- template <typename InputDeviceType>
- void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
- auto pair = std::make_pair(name, std::move(factory));
- if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
- LOG_ERROR(Input, "Factory '{}' already registered", name);
- }
- }
- /**
- * Unregisters an input device factory.
- * @tparam InputDeviceType the type of input devices the factory can create
- * @param name the name of the factory to unregister
- */
- template <typename InputDeviceType>
- void UnregisterFactory(const std::string& name) {
- if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
- LOG_ERROR(Input, "Factory '{}' not registered", name);
- }
- }
- /**
- * Create an input device from given paramters.
- * @tparam InputDeviceType the type of input devices to create
- * @param params a serialized ParamPackage string contains all parameters for creating the device
- */
- template <typename InputDeviceType>
- std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) {
- const Common::ParamPackage package(params);
- const std::string engine = package.Get("engine", "null");
- const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;
- const auto pair = factory_list.find(engine);
- if (pair == factory_list.end()) {
- if (engine != "null") {
- LOG_ERROR(Input, "Unknown engine name: {}", engine);
- }
- return std::make_unique<InputDeviceType>();
- }
- return pair->second->Create(package);
- }
- /**
- * A button device is an input device that returns bool as status.
- * true for pressed; false for released.
- */
- using ButtonDevice = InputDevice<bool>;
- /**
- * An analog device is an input device that returns a tuple of x and y coordinates as status. The
- * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up
- * direction
- */
- using AnalogDevice = InputDevice<std::tuple<float, float>>;
- /**
- * A vibration device is an input device that returns an unsigned byte as status.
- * It represents whether the vibration device supports vibration or not.
- * If the status returns 1, it supports vibration. Otherwise, it does not support vibration.
- */
- using VibrationDevice = InputDevice<u8>;
- /**
- * A motion status is an object that returns a tuple of accelerometer state vector,
- * gyroscope state vector, rotation state vector and orientation state matrix.
- *
- * For both vectors:
- * x+ is the same direction as RIGHT on D-pad.
- * y+ is normal to the touch screen, pointing outward.
- * z+ is the same direction as UP on D-pad.
- *
- * For accelerometer state vector
- * Units: g (gravitational acceleration)
- *
- * For gyroscope state vector:
- * Orientation is determined by right-hand rule.
- * Units: deg/sec
- *
- * For rotation state vector
- * Units: rotations
- *
- * For orientation state matrix
- * x vector
- * y vector
- * z vector
- */
- using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>,
- std::array<Common::Vec3f, 3>>;
- /**
- * A motion device is an input device that returns a motion status object
- */
- using MotionDevice = InputDevice<MotionStatus>;
- /**
- * A touch status is an object that returns a tuple of two floats and a bool. The floats are
- * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed.
- */
- using TouchStatus = std::tuple<float, float, bool>;
- /**
- * A touch device is an input device that returns a touch status object
- */
- using TouchDevice = InputDevice<TouchStatus>;
- /**
- * A mouse device is an input device that returns a tuple of two floats and four ints.
- * The first two floats are X and Y device coordinates of the mouse (from 0-1).
- * The s32s are the mouse wheel.
- */
- using MouseDevice = InputDevice<std::tuple<float, float, s32, s32>>;
- } // namespace Input
|