suyu/src/input_common/input_engine.h

259 lines
9 KiB
C++
Raw Normal View History

// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2021-09-20 17:34:05 -04:00
#pragma once
#include <functional>
#include <mutex>
#include <unordered_map>
#include "common/common_types.h"
#include "common/input.h"
#include "common/param_package.h"
#include "common/uuid.h"
2021-09-20 17:34:05 -04:00
#include "input_common/main.h"
// Pad Identifier of data source
struct PadIdentifier {
Common::UUID guid{};
2021-09-20 17:34:05 -04:00
std::size_t port{};
std::size_t pad{};
friend constexpr bool operator==(const PadIdentifier&, const PadIdentifier&) = default;
};
// Basic motion data containing data from the sensors and a timestamp in microseconds
2021-09-20 17:34:05 -04:00
struct BasicMotion {
float gyro_x{};
float gyro_y{};
float gyro_z{};
float accel_x{};
float accel_y{};
float accel_z{};
u64 delta_timestamp{};
2021-09-20 17:34:05 -04:00
};
// Types of input that are stored in the engine
enum class EngineInputType {
None,
2022-06-19 00:32:07 -04:00
Analog,
Battery,
2021-09-20 17:34:05 -04:00
Button,
2022-06-19 00:32:07 -04:00
Camera,
2021-09-20 17:34:05 -04:00
HatButton,
Motion,
Nfc,
2021-09-20 17:34:05 -04:00
};
namespace std {
// Hash used to create lists from PadIdentifier data
template <>
struct hash<PadIdentifier> {
size_t operator()(const PadIdentifier& pad_id) const noexcept {
u64 hash_value = pad_id.guid.Hash();
2021-09-20 17:34:05 -04:00
hash_value ^= (static_cast<u64>(pad_id.port) << 32);
hash_value ^= static_cast<u64>(pad_id.pad);
return static_cast<size_t>(hash_value);
}
};
} // namespace std
namespace InputCommon {
// Data from the engine and device needed for creating a ParamPackage
struct MappingData {
std::string engine{};
PadIdentifier pad{};
EngineInputType type{};
int index{};
bool button_value{};
std::string hat_name{};
f32 axis_value{};
BasicMotion motion_value{};
};
// Triggered if data changed on the controller
struct UpdateCallback {
std::function<void()> on_change;
};
// Triggered if data changed on the controller and the engine is on configuring mode
struct MappingCallback {
std::function<void(const MappingData&)> on_data;
2021-09-20 17:34:05 -04:00
};
// Input Identifier of data source
struct InputIdentifier {
PadIdentifier identifier;
EngineInputType type;
int index;
2021-09-20 17:34:05 -04:00
UpdateCallback callback;
};
class InputEngine {
public:
explicit InputEngine(std::string input_engine_) : input_engine{std::move(input_engine_)} {}
2021-09-20 17:34:05 -04:00
virtual ~InputEngine() = default;
// Enable configuring mode for mapping
void BeginConfiguration();
// Disable configuring mode for mapping
void EndConfiguration();
// Sets a led pattern for a controller
virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const Common::Input::LedStatus& led_status) {}
2021-09-20 17:34:05 -04:00
2021-10-11 01:43:11 -04:00
// Sets rumble to a controller
2022-10-21 01:23:12 -04:00
virtual Common::Input::VibrationError SetVibration(
[[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
return Common::Input::VibrationError::NotSupported;
2021-10-11 01:43:11 -04:00
}
2022-10-21 01:23:12 -04:00
// Returns true if device supports vibrations
virtual bool IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
return false;
}
2021-10-11 01:43:11 -04:00
// Sets polling mode to a controller
virtual Common::Input::PollingError SetPollingMode(
[[maybe_unused]] const PadIdentifier& identifier,
2022-06-19 00:32:07 -04:00
[[maybe_unused]] const Common::Input::PollingMode polling_mode) {
return Common::Input::PollingError::NotSupported;
2021-10-11 01:43:11 -04:00
}
2022-06-19 00:32:07 -04:00
// Sets camera format to a controller
virtual Common::Input::CameraError SetCameraFormat(
[[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] Common::Input::CameraFormat camera_format) {
return Common::Input::CameraError::NotSupported;
}
// Returns success if nfc is supported
2022-09-24 23:52:33 -04:00
virtual Common::Input::NfcState SupportsNfc(
[[maybe_unused]] const PadIdentifier& identifier) const {
return Common::Input::NfcState::NotSupported;
}
// Writes data to an nfc tag
virtual Common::Input::NfcState WriteNfcData([[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const std::vector<u8>& data) {
return Common::Input::NfcState::NotSupported;
}
2021-09-20 17:34:05 -04:00
// Returns the engine name
[[nodiscard]] const std::string& GetEngineName() const;
/// Used for automapping features
virtual std::vector<Common::ParamPackage> GetInputDevices() const {
return {};
}
2021-09-20 17:34:05 -04:00
/// Retrieves the button mappings for the given device
virtual ButtonMapping GetButtonMappingForDevice(
2021-09-20 17:34:05 -04:00
[[maybe_unused]] const Common::ParamPackage& params) {
return {};
}
2021-09-20 17:34:05 -04:00
/// Retrieves the analog mappings for the given device
virtual AnalogMapping GetAnalogMappingForDevice(
2021-09-20 17:34:05 -04:00
[[maybe_unused]] const Common::ParamPackage& params) {
return {};
}
2021-09-20 17:34:05 -04:00
/// Retrieves the motion mappings for the given device
virtual MotionMapping GetMotionMappingForDevice(
2021-09-20 17:34:05 -04:00
[[maybe_unused]] const Common::ParamPackage& params) {
return {};
}
2021-09-20 17:34:05 -04:00
/// Retrieves the name of the given input.
virtual Common::Input::ButtonNames GetUIName(
[[maybe_unused]] const Common::ParamPackage& params) const {
return Common::Input::ButtonNames::Engine;
}
2021-09-20 17:34:05 -04:00
/// Retrieves the index number of the given hat button direction
virtual u8 GetHatButtonId([[maybe_unused]] const std::string& direction_name) const {
2021-09-20 17:34:05 -04:00
return 0;
}
2021-09-20 17:34:05 -04:00
/// Returns true if axis of a stick aren't mapped in the correct direction
virtual bool IsStickInverted([[maybe_unused]] const Common::ParamPackage& params) {
return false;
}
2021-09-20 17:34:05 -04:00
void PreSetController(const PadIdentifier& identifier);
void PreSetButton(const PadIdentifier& identifier, int button);
void PreSetHatButton(const PadIdentifier& identifier, int button);
void PreSetAxis(const PadIdentifier& identifier, int axis);
void PreSetMotion(const PadIdentifier& identifier, int motion);
void ResetButtonState();
void ResetAnalogState();
bool GetButton(const PadIdentifier& identifier, int button) const;
bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const;
f32 GetAxis(const PadIdentifier& identifier, int axis) const;
Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const;
2021-09-20 17:34:05 -04:00
BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const;
2022-06-19 00:32:07 -04:00
Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const;
Common::Input::NfcStatus GetNfc(const PadIdentifier& identifier) const;
2021-09-20 17:34:05 -04:00
int SetCallback(InputIdentifier input_identifier);
void SetMappingCallback(MappingCallback callback);
void DeleteCallback(int key);
protected:
void SetButton(const PadIdentifier& identifier, int button, bool value);
void SetHatButton(const PadIdentifier& identifier, int button, u8 value);
void SetAxis(const PadIdentifier& identifier, int axis, f32 value);
void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value);
void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value);
2022-06-19 00:32:07 -04:00
void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value);
void SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value);
2021-09-20 17:34:05 -04:00
virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const {
return "Unknown";
}
private:
struct ControllerData {
std::unordered_map<int, bool> buttons;
std::unordered_map<int, u8> hat_buttons;
std::unordered_map<int, float> axes;
std::unordered_map<int, BasicMotion> motions;
Common::Input::BatteryLevel battery{};
2022-06-19 00:32:07 -04:00
Common::Input::CameraStatus camera{};
Common::Input::NfcStatus nfc{};
2021-09-20 17:34:05 -04:00
};
void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value);
void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value);
void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value);
void TriggerOnBatteryChange(const PadIdentifier& identifier, Common::Input::BatteryLevel value);
void TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
const BasicMotion& value);
2022-06-19 00:32:07 -04:00
void TriggerOnCameraChange(const PadIdentifier& identifier,
const Common::Input::CameraStatus& value);
void TriggerOnNfcChange(const PadIdentifier& identifier, const Common::Input::NfcStatus& value);
2021-09-20 17:34:05 -04:00
bool IsInputIdentifierEqual(const InputIdentifier& input_identifier,
const PadIdentifier& identifier, EngineInputType type,
int index) const;
2021-09-20 17:34:05 -04:00
mutable std::mutex mutex;
mutable std::mutex mutex_callback;
bool configuring{false};
const std::string input_engine;
int last_callback_key = 0;
std::unordered_map<PadIdentifier, ControllerData> controller_list;
std::unordered_map<int, InputIdentifier> callback_list;
MappingCallback mapping_callback;
};
} // namespace InputCommon