yuzu/src/core/hid/emulated_controller.h

366 lines
12 KiB
C++
Raw Normal View History

2021-09-21 03:43:16 +03:00
// 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/input.h"
#include "common/param_package.h"
#include "common/point.h"
#include "common/quaternion.h"
#include "common/settings.h"
#include "common/vector_math.h"
#include "core/hid/hid_types.h"
#include "core/hid/motion_input.h"
namespace Core::HID {
struct ControllerMotionInfo {
Input::MotionStatus raw_status;
MotionInput emulated{};
};
using ButtonDevices =
std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeButton::NumButtons>;
using StickDevices =
std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
using ControllerMotionDevices =
std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeMotion::NumMotions>;
using TriggerDevices =
std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, 2>;
2021-10-11 08:43:11 +03:00
using OutputDevices = std::array<std::unique_ptr<Input::OutputDevice>, 2>;
2021-09-21 03:43:16 +03:00
using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
using BatteryParams = std::array<Common::ParamPackage, 2>;
2021-10-11 08:43:11 +03:00
using OutputParams = std::array<Common::ParamPackage, 2>;
2021-09-21 03:43:16 +03:00
using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
using TriggerValues = std::array<Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>;
using ColorValues = std::array<Input::BodyColorStatus, 3>;
using BatteryValues = std::array<Input::BatteryStatus, 3>;
using VibrationValues = std::array<Input::VibrationStatus, 2>;
struct AnalogSticks {
AnalogStickState left;
AnalogStickState right;
};
struct ControllerColors {
NpadControllerColor fullkey;
NpadControllerColor left;
NpadControllerColor right;
};
struct BatteryLevelState {
NpadPowerInfo dual;
NpadPowerInfo left;
NpadPowerInfo right;
};
struct ControllerMotion {
bool is_at_rest;
Common::Vec3f accel{};
Common::Vec3f gyro{};
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
};
using MotionState = std::array<ControllerMotion, 2>;
struct ControllerStatus {
// Data from input_common
ButtonValues button_values{};
SticksValues stick_values{};
ControllerMotionValues motion_values{};
TriggerValues trigger_values{};
ColorValues color_values{};
BatteryValues battery_values{};
VibrationValues vibration_values{};
2021-10-17 08:33:00 +03:00
// Data for HID serices
2021-09-21 03:43:16 +03:00
NpadButtonState npad_button_state{};
DebugPadButton debug_pad_button_state{};
AnalogSticks analog_stick_state{};
MotionState motion_state{};
NpadGcTriggerState gc_trigger_state{};
ControllerColors colors_state{};
BatteryLevelState battery_state{};
};
2021-10-11 08:43:11 +03:00
2021-09-21 03:43:16 +03:00
enum class ControllerTriggerType {
Button,
Stick,
Trigger,
Motion,
Color,
Battery,
Vibration,
Connected,
Disconnected,
Type,
All,
};
struct ControllerUpdateCallback {
std::function<void(ControllerTriggerType)> on_change;
2021-10-19 08:12:24 +03:00
bool is_service;
2021-09-21 03:43:16 +03:00
};
class EmulatedController {
public:
/**
2021-10-17 08:33:00 +03:00
* Contains all input data related to this controller. Like buttons, joysticks, motion.
* @param Npad id type for this specific controller
2021-09-21 03:43:16 +03:00
*/
explicit EmulatedController(NpadIdType npad_id_type_);
~EmulatedController();
YUZU_NON_COPYABLE(EmulatedController);
YUZU_NON_MOVEABLE(EmulatedController);
2021-10-17 08:33:00 +03:00
/// Converts the controller type from settings to npad type
2021-09-21 03:43:16 +03:00
static NpadType MapSettingsTypeToNPad(Settings::ControllerType type);
2021-10-17 08:33:00 +03:00
/// Converts npad type to the equivalent of controller type from settings
2021-09-21 03:43:16 +03:00
static Settings::ControllerType MapNPadToSettingsType(NpadType type);
2021-10-17 08:33:00 +03:00
/// Gets the NpadIdType for this controller
2021-09-21 03:43:16 +03:00
NpadIdType GetNpadIdType() const;
2021-10-17 08:33:00 +03:00
/// Sets the NpadType for this controller
2021-09-21 03:43:16 +03:00
void SetNpadType(NpadType npad_type_);
/**
* Gets the NpadType for this controller
* @param Returns the temporary value if true
* @return NpadType set on the controller
*/
NpadType GetNpadType(bool temporary = false) const;
2021-09-21 03:43:16 +03:00
2021-10-17 08:33:00 +03:00
/// Sets the connected status to true
2021-09-21 03:43:16 +03:00
void Connect();
2021-10-17 08:33:00 +03:00
/// Sets the connected status to false
2021-09-21 03:43:16 +03:00
void Disconnect();
/**
* Is the emulated connected
* @param Returns the temporary value if true
* @return true if the controller has the connected status
*/
bool IsConnected(bool temporary = false) const;
2021-10-17 08:33:00 +03:00
/// Returns true if vibration is enabled
2021-09-21 03:43:16 +03:00
bool IsVibrationEnabled() const;
2021-10-17 08:33:00 +03:00
/// Removes all callbacks created from input devices
2021-09-21 03:43:16 +03:00
void UnloadInput();
2021-10-17 08:33:00 +03:00
/// Sets the emulated console into configuring mode. Locking all HID service events from being
/// moddified
2021-09-21 03:43:16 +03:00
void EnableConfiguration();
2021-10-17 08:33:00 +03:00
/// Returns the emulated console to the normal behaivour
2021-09-21 03:43:16 +03:00
void DisableConfiguration();
2021-10-17 08:33:00 +03:00
/// Returns true if the emulated device is on configuring mode
2021-09-21 03:43:16 +03:00
bool IsConfiguring() const;
2021-10-17 08:33:00 +03:00
/// Reload all input devices
void ReloadInput();
/// Overrides current mapped devices with the stored configuration and reloads all input devices
void ReloadFromSettings();
/// Saves the current mapped configuration
2021-09-21 03:43:16 +03:00
void SaveCurrentConfig();
2021-10-17 08:33:00 +03:00
/// Reverts any mapped changes made that weren't saved
2021-09-21 03:43:16 +03:00
void RestoreConfig();
2021-10-17 08:33:00 +03:00
/// Returns a vector of mapped devices from the mapped button and stick parameters
2021-09-21 03:43:16 +03:00
std::vector<Common::ParamPackage> GetMappedDevices() const;
2021-10-17 08:33:00 +03:00
// Returns the current mapped button device
2021-09-21 03:43:16 +03:00
Common::ParamPackage GetButtonParam(std::size_t index) const;
2021-10-17 08:33:00 +03:00
// Returns the current mapped stick device
2021-09-21 03:43:16 +03:00
Common::ParamPackage GetStickParam(std::size_t index) const;
2021-10-17 08:33:00 +03:00
// Returns the current mapped motion device
2021-09-21 03:43:16 +03:00
Common::ParamPackage GetMotionParam(std::size_t index) const;
2021-10-17 08:33:00 +03:00
/**
* Updates the current mapped button device
* @param ParamPackage with controller data to be mapped
*/
2021-09-21 03:43:16 +03:00
void SetButtonParam(std::size_t index, Common::ParamPackage param);
2021-10-17 08:33:00 +03:00
/**
* Updates the current mapped stick device
* @param ParamPackage with controller data to be mapped
*/
2021-09-21 03:43:16 +03:00
void SetStickParam(std::size_t index, Common::ParamPackage param);
2021-10-17 08:33:00 +03:00
/**
* Updates the current mapped motion device
* @param ParamPackage with controller data to be mapped
*/
2021-09-21 03:43:16 +03:00
void SetMotionParam(std::size_t index, Common::ParamPackage param);
2021-10-17 08:33:00 +03:00
/// Returns the latest button status from the controller with parameters
2021-09-21 03:43:16 +03:00
ButtonValues GetButtonsValues() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest analog stick status from the controller with parameters
2021-09-21 03:43:16 +03:00
SticksValues GetSticksValues() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest trigger status from the controller with parameters
2021-09-21 03:43:16 +03:00
TriggerValues GetTriggersValues() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest motion status from the controller with parameters
2021-09-21 03:43:16 +03:00
ControllerMotionValues GetMotionValues() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest color status from the controller with parameters
2021-09-21 03:43:16 +03:00
ColorValues GetColorsValues() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest battery status from the controller with parameters
2021-09-21 03:43:16 +03:00
BatteryValues GetBatteryValues() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest status of button input for the npad service
2021-09-21 03:43:16 +03:00
NpadButtonState GetNpadButtons() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest status of button input for the debug pad service
2021-09-21 03:43:16 +03:00
DebugPadButton GetDebugPadButtons() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest status of stick input from the mouse
2021-09-21 03:43:16 +03:00
AnalogSticks GetSticks() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest status of trigger input from the mouse
2021-09-21 03:43:16 +03:00
NpadGcTriggerState GetTriggers() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest status of motion input from the mouse
2021-09-21 03:43:16 +03:00
MotionState GetMotions() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest color value from the controller
2021-09-21 03:43:16 +03:00
ControllerColors GetColors() const;
2021-10-17 08:33:00 +03:00
/// Returns the latest battery status from the controller
2021-09-21 03:43:16 +03:00
BatteryLevelState GetBattery() const;
2021-10-17 08:33:00 +03:00
/*
* Sends a specific vibration to the output device
* @return returns true if vibration had no errors
*/
2021-09-21 03:43:16 +03:00
bool SetVibration(std::size_t device_index, VibrationValue vibration);
2021-10-17 08:33:00 +03:00
/*
* Sends a small vibration to the output device
* @return returns true if SetVibration was successfull
*/
2021-10-11 08:43:11 +03:00
bool TestVibration(std::size_t device_index);
2021-10-17 08:33:00 +03:00
/// Returns the led pattern corresponding to this emulated controller
LedPattern GetLedPattern() const;
/// Asks the output device to change the player led pattern
2021-10-11 08:43:11 +03:00
void SetLedPattern();
2021-09-21 03:43:16 +03:00
2021-10-17 08:33:00 +03:00
/**
* Adds a callback to the list of events
* @param ConsoleUpdateCallback that will be triggered
* @return an unique key corresponding to the callback index in the list
*/
2021-09-21 03:43:16 +03:00
int SetCallback(ControllerUpdateCallback update_callback);
2021-10-17 08:33:00 +03:00
/**
* Removes a callback from the list stopping any future events to this object
* @param Key corresponding to the callback index in the list
*/
2021-09-21 03:43:16 +03:00
void DeleteCallback(int key);
private:
/**
2021-10-17 08:33:00 +03:00
* Updates the button status of the controller
* @param callback: A CallbackStatus containing the button status
* @param index: Button ID of the to be updated
2021-09-21 03:43:16 +03:00
*/
void SetButton(Input::CallbackStatus callback, std::size_t index);
2021-10-17 08:33:00 +03:00
/**
* Updates the analog stick status of the controller
* @param callback: A CallbackStatus containing the analog stick status
* @param index: stick ID of the to be updated
*/
2021-09-21 03:43:16 +03:00
void SetStick(Input::CallbackStatus callback, std::size_t index);
2021-10-17 08:33:00 +03:00
/**
* Updates the trigger status of the controller
* @param callback: A CallbackStatus containing the trigger status
* @param index: trigger ID of the to be updated
*/
2021-09-21 03:43:16 +03:00
void SetTrigger(Input::CallbackStatus callback, std::size_t index);
2021-10-17 08:33:00 +03:00
/**
* Updates the motion status of the controller
* @param callback: A CallbackStatus containing gyro and accelerometer data
* @param index: motion ID of the to be updated
*/
2021-09-21 03:43:16 +03:00
void SetMotion(Input::CallbackStatus callback, std::size_t index);
2021-10-17 08:33:00 +03:00
/**
* Updates the battery status of the controller
* @param callback: A CallbackStatus containing the battery status
* @param index: Button ID of the to be updated
*/
2021-09-21 03:43:16 +03:00
void SetBattery(Input::CallbackStatus callback, std::size_t index);
/**
2021-10-17 08:33:00 +03:00
* Triggers a callback that something has changed on the controller status
2021-10-19 08:12:24 +03:00
* @param type: Input type of the event to trigger
* @param is_service_update: indicates if this event should be sended to only services
2021-09-21 03:43:16 +03:00
*/
2021-10-19 08:12:24 +03:00
void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
2021-09-21 03:43:16 +03:00
NpadIdType npad_id_type;
NpadType npad_type{NpadType::None};
NpadType temporary_npad_type{NpadType::None};
2021-09-21 03:43:16 +03:00
bool is_connected{false};
bool temporary_is_connected{false};
2021-09-21 03:43:16 +03:00
bool is_configuring{false};
bool is_vibration_enabled{true};
f32 motion_sensitivity{0.01f};
ButtonParams button_params;
StickParams stick_params;
ControllerMotionParams motion_params;
TriggerParams trigger_params;
BatteryParams battery_params;
2021-10-11 08:43:11 +03:00
OutputParams output_params;
2021-09-21 03:43:16 +03:00
ButtonDevices button_devices;
StickDevices stick_devices;
ControllerMotionDevices motion_devices;
TriggerDevices trigger_devices;
BatteryDevices battery_devices;
2021-10-11 08:43:11 +03:00
OutputDevices output_devices;
2021-09-21 03:43:16 +03:00
mutable std::mutex mutex;
std::unordered_map<int, ControllerUpdateCallback> callback_list;
int last_callback_key = 0;
2021-10-17 08:33:00 +03:00
// Stores the current status of all controller input
2021-09-21 03:43:16 +03:00
ControllerStatus controller;
};
} // namespace Core::HID