committed by
Narr the Reg
2 changed files with 243 additions and 0 deletions
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue