Просмотр исходного кода

common: Rewrite and move core/frontend/input.h to common

german77 4 лет назад
Родитель
Сommit
ad5142ac2c
2 измененных файлов с 243 добавлено и 0 удалено
  1. 1 0
      src/common/CMakeLists.txt
  2. 242 0
      src/common/input.h

+ 1 - 0
src/common/CMakeLists.txt

@@ -73,6 +73,7 @@ add_library(common STATIC
     hex_util.h
     host_memory.cpp
     host_memory.h
+    input.h
     intrusive_red_black_tree.h
     literals.h
     logging/backend.cpp

+ 242 - 0
src/common/input.h

@@ -0,0 +1,242 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include "common/logging/log.h"
+#include "common/param_package.h"
+
+namespace Input {
+
+enum class InputType {
+    None,
+    Battery,
+    Button,
+    Stick,
+    Analog,
+    Trigger,
+    Motion,
+    Touch,
+    Color,
+    Vibration,
+    Nfc,
+    Ir,
+};
+
+enum class BatteryLevel {
+    Empty,
+    Critical,
+    Low,
+    Medium,
+    Full,
+    Charging,
+};
+
+struct AnalogProperties {
+    float deadzone{};
+    float range{1.0f};
+    float threshold{0.5f};
+    float offset{};
+    bool inverted{};
+};
+
+struct AnalogStatus {
+    float value{};
+    float raw_value{};
+    AnalogProperties properties{};
+};
+
+struct ButtonStatus {
+    bool value{};
+    bool inverted{};
+    bool toggle{};
+    bool locked{};
+};
+
+using BatteryStatus = BatteryLevel;
+
+struct StickStatus {
+    AnalogStatus x{};
+    AnalogStatus y{};
+    bool left{};
+    bool right{};
+    bool up{};
+    bool down{};
+};
+
+struct TriggerStatus {
+    AnalogStatus analog{};
+    bool pressed{};
+};
+
+struct MotionSensor {
+    AnalogStatus x{};
+    AnalogStatus y{};
+    AnalogStatus z{};
+};
+
+struct MotionStatus {
+    MotionSensor gyro{};
+    MotionSensor accel{};
+    u64 delta_timestamp{};
+};
+
+struct TouchStatus {
+    ButtonStatus pressed{};
+    AnalogStatus x{};
+    AnalogStatus y{};
+    u32 id{};
+};
+
+struct BodyColorStatus {
+    u32 body{};
+    u32 buttons{};
+};
+
+struct VibrationStatus {
+    f32 low_amplitude{};
+    f32 low_frequency{};
+    f32 high_amplitude{};
+    f32 high_frequency{};
+};
+
+struct LedStatus {
+    bool led_1{};
+    bool led_2{};
+    bool led_3{};
+    bool led_4{};
+};
+
+struct CallbackStatus {
+    InputType type{InputType::None};
+    ButtonStatus button_status{};
+    StickStatus stick_status{};
+    AnalogStatus analog_status{};
+    TriggerStatus trigger_status{};
+    MotionStatus motion_status{};
+    TouchStatus touch_status{};
+    BodyColorStatus color_status{};
+    BatteryStatus battery_status{};
+    VibrationStatus vibration_status{};
+};
+
+struct InputCallback {
+    std::function<void(CallbackStatus)> on_change;
+};
+
+/// An abstract class template for an input device (a button, an analog input, etc.).
+class InputDevice {
+public:
+    virtual ~InputDevice() = default;
+
+    void SetCallback(InputCallback callback_) {
+        callback = std::move(callback_);
+    }
+
+    void TriggerOnChange(CallbackStatus status) {
+        if (callback.on_change) {
+            callback.on_change(status);
+        }
+    }
+
+private:
+    InputCallback callback;
+};
+
+/// 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 that contains all parameters for creating the
+ * device
+ */
+template <typename InputDeviceType>
+std::unique_ptr<InputDeviceType> CreateDeviceFromString(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);
+}
+
+/**
+ * Create an input device from given paramters.
+ * @tparam InputDeviceType the type of input devices to create
+ * @param A ParamPackage that contains all parameters for creating the device
+ */
+template <typename InputDeviceType>
+std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package) {
+    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);
+}
+
+} // namespace Input