summaryrefslogtreecommitdiffstats
path: root/src/input_common/input_engine.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/input_common/input_engine.h229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
new file mode 100644
index 000000000..390581c94
--- /dev/null
+++ b/src/input_common/input_engine.h
@@ -0,0 +1,229 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included
+
+#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"
+#include "input_common/main.h"
+
+// Pad Identifier of data source
+struct PadIdentifier {
+ Common::UUID guid{};
+ 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
+struct BasicMotion {
+ float gyro_x{};
+ float gyro_y{};
+ float gyro_z{};
+ float accel_x{};
+ float accel_y{};
+ float accel_z{};
+ u64 delta_timestamp{};
+};
+
+// Stages of a battery charge
+enum class BatteryLevel {
+ Empty,
+ Critical,
+ Low,
+ Medium,
+ Full,
+ Charging,
+};
+
+// Types of input that are stored in the engine
+enum class EngineInputType {
+ None,
+ Button,
+ HatButton,
+ Analog,
+ Motion,
+ Battery,
+};
+
+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.uuid[1] ^ pad_id.guid.uuid[0];
+ 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(MappingData)> on_data;
+};
+
+// Input Identifier of data source
+struct InputIdentifier {
+ PadIdentifier identifier;
+ EngineInputType type;
+ int index;
+ UpdateCallback callback;
+};
+
+class InputEngine {
+public:
+ explicit InputEngine(std::string input_engine_) : input_engine{std::move(input_engine_)} {}
+
+ 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) {}
+
+ // Sets rumble to a controller
+ virtual Common::Input::VibrationError SetRumble(
+ [[maybe_unused]] const PadIdentifier& identifier,
+ [[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
+ return Common::Input::VibrationError::NotSupported;
+ }
+
+ // Sets polling mode to a controller
+ virtual Common::Input::PollingError SetPollingMode(
+ [[maybe_unused]] const PadIdentifier& identifier,
+ [[maybe_unused]] const Common::Input::PollingMode vibration) {
+ return Common::Input::PollingError::NotSupported;
+ }
+
+ // Returns the engine name
+ [[nodiscard]] const std::string& GetEngineName() const;
+
+ /// Used for automapping features
+ virtual std::vector<Common::ParamPackage> GetInputDevices() const {
+ return {};
+ }
+
+ /// Retrieves the button mappings for the given device
+ virtual ButtonMapping GetButtonMappingForDevice(
+ [[maybe_unused]] const Common::ParamPackage& params) {
+ return {};
+ }
+
+ /// Retrieves the analog mappings for the given device
+ virtual AnalogMapping GetAnalogMappingForDevice(
+ [[maybe_unused]] const Common::ParamPackage& params) {
+ return {};
+ }
+
+ /// Retrieves the motion mappings for the given device
+ virtual MotionMapping GetMotionMappingForDevice(
+ [[maybe_unused]] const Common::ParamPackage& params) {
+ return {};
+ }
+
+ /// Retrieves the name of the given input.
+ virtual Common::Input::ButtonNames GetUIName(
+ [[maybe_unused]] const Common::ParamPackage& params) const {
+ return Common::Input::ButtonNames::Engine;
+ }
+
+ /// Retrieves the index number of the given hat button direction
+ virtual u8 GetHatButtonId([[maybe_unused]] const std::string& direction_name) const {
+ return 0;
+ }
+
+ 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;
+ BatteryLevel GetBattery(const PadIdentifier& identifier) const;
+ BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const;
+
+ 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, BatteryLevel value);
+ void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value);
+
+ 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;
+ BatteryLevel battery{};
+ };
+
+ 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, BatteryLevel value);
+ void TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
+ const BasicMotion& value);
+
+ bool IsInputIdentifierEqual(const InputIdentifier& input_identifier,
+ const PadIdentifier& identifier, EngineInputType type,
+ int index) const;
+
+ 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