mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-26 05:16:24 -05:00
common: Rewrite and move core/frontend/input.h to common
This commit is contained in:
parent
f078d3d212
commit
ad5142ac2c
2 changed files with 243 additions and 0 deletions
|
@ -73,6 +73,7 @@ add_library(common STATIC
|
||||||
hex_util.h
|
hex_util.h
|
||||||
host_memory.cpp
|
host_memory.cpp
|
||||||
host_memory.h
|
host_memory.h
|
||||||
|
input.h
|
||||||
intrusive_red_black_tree.h
|
intrusive_red_black_tree.h
|
||||||
literals.h
|
literals.h
|
||||||
logging/backend.cpp
|
logging/backend.cpp
|
||||||
|
|
242
src/common/input.h
Normal file
242
src/common/input.h
Normal file
|
@ -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
|
Loading…
Reference in a new issue