early-access version 2258

This commit is contained in:
pineappleEA 2021-11-30 05:49:07 +01:00
parent eeba1aa6f2
commit 3c5094eec0
24 changed files with 387 additions and 136 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 2256. This is the source code for early-access 2258.
## Legal Notice ## Legal Notice

View file

@ -78,9 +78,9 @@ struct ConsoleUpdateCallback {
class EmulatedConsole { class EmulatedConsole {
public: public:
/** /**
* Contains all input data related to the console like motion and touch input * Contains all input data within the emulated switch console tablet such as touch and motion
*/ */
EmulatedConsole(); explicit EmulatedConsole();
~EmulatedConsole(); ~EmulatedConsole();
YUZU_NON_COPYABLE(EmulatedConsole); YUZU_NON_COPYABLE(EmulatedConsole);
@ -89,14 +89,16 @@ public:
/// Removes all callbacks created from input devices /// Removes all callbacks created from input devices
void UnloadInput(); void UnloadInput();
/// Sets the emulated console into configuring mode. Locking all HID service events from being /**
/// moddified * Sets the emulated console into configuring mode
* This prevents the modification of the HID state of the emulated console by input commands
*/
void EnableConfiguration(); void EnableConfiguration();
/// Returns the emulated console to the normal behaivour /// Returns the emulated console into normal mode, allowing the modification of the HID state
void DisableConfiguration(); void DisableConfiguration();
/// Returns true if the emulated console is on configuring mode /// Returns true if the emulated console is in configuring mode
bool IsConfiguring() const; bool IsConfiguring() const;
/// Reload all input devices /// Reload all input devices
@ -116,7 +118,7 @@ public:
/** /**
* Updates the current mapped motion device * Updates the current mapped motion device
* @param ParamPackage with controller data to be mapped * @param param ParamPackage with controller data to be mapped
*/ */
void SetMotionParam(Common::ParamPackage param); void SetMotionParam(Common::ParamPackage param);
@ -134,14 +136,14 @@ public:
/** /**
* Adds a callback to the list of events * Adds a callback to the list of events
* @param ConsoleUpdateCallback that will be triggered * @param update_callback A ConsoleUpdateCallback that will be triggered
* @return an unique key corresponding to the callback index in the list * @return an unique key corresponding to the callback index in the list
*/ */
int SetCallback(ConsoleUpdateCallback update_callback); int SetCallback(ConsoleUpdateCallback update_callback);
/** /**
* Removes a callback from the list stopping any future events to this object * Removes a callback from the list stopping any future events to this object
* @param Key corresponding to the callback index in the list * @param key Key corresponding to the callback index in the list
*/ */
void DeleteCallback(int key); void DeleteCallback(int key);
@ -151,20 +153,20 @@ private:
/** /**
* Updates the motion status of the console * Updates the motion status of the console
* @param A CallbackStatus containing gyro and accelerometer data * @param callback A CallbackStatus containing gyro and accelerometer data
*/ */
void SetMotion(Common::Input::CallbackStatus callback); void SetMotion(Common::Input::CallbackStatus callback);
/** /**
* Updates the touch status of the console * Updates the touch status of the console
* @param callback: A CallbackStatus containing the touch position * @param callback A CallbackStatus containing the touch position
* @param index: Finger ID to be updated * @param index Finger ID to be updated
*/ */
void SetTouch(Common::Input::CallbackStatus callback, std::size_t index); void SetTouch(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Triggers a callback that something has changed on the console status * Triggers a callback that something has changed on the console status
* @param Input type of the event to trigger * @param type Input type of the event to trigger
*/ */
void TriggerOnChange(ConsoleTriggerType type); void TriggerOnChange(ConsoleTriggerType type);

View file

@ -132,8 +132,8 @@ struct ControllerUpdateCallback {
class EmulatedController { class EmulatedController {
public: public:
/** /**
* Contains all input data related to this controller. Like buttons, joysticks, motion. * Contains all input data (buttons, joysticks, vibration, and motion) within this controller.
* @param Npad id type for this specific controller * @param npad_id_type npad id type for this specific controller
*/ */
explicit EmulatedController(NpadIdType npad_id_type_); explicit EmulatedController(NpadIdType npad_id_type_);
~EmulatedController(); ~EmulatedController();
@ -155,7 +155,7 @@ public:
/** /**
* Gets the NpadStyleIndex for this controller * Gets the NpadStyleIndex for this controller
* @param If true tmp_npad_type will be returned * @param get_temporary_value If true tmp_npad_type will be returned
* @return NpadStyleIndex set on the controller * @return NpadStyleIndex set on the controller
*/ */
NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const;
@ -168,7 +168,7 @@ public:
/** /**
* Is the emulated connected * Is the emulated connected
* @param If true tmp_is_connected will be returned * @param get_temporary_value If true tmp_is_connected will be returned
* @return true if the controller has the connected status * @return true if the controller has the connected status
*/ */
bool IsConnected(bool get_temporary_value = false) const; bool IsConnected(bool get_temporary_value = false) const;
@ -179,14 +179,16 @@ public:
/// Removes all callbacks created from input devices /// Removes all callbacks created from input devices
void UnloadInput(); void UnloadInput();
/// Sets the emulated console into configuring mode. Locking all HID service events from being /**
/// moddified * Sets the emulated controller into configuring mode
* This prevents the modification of the HID state of the emulated controller by input commands
*/
void EnableConfiguration(); void EnableConfiguration();
/// Returns the emulated console to the normal behaivour /// Returns the emulated controller into normal mode, allowing the modification of the HID state
void DisableConfiguration(); void DisableConfiguration();
/// Returns true if the emulated device is on configuring mode /// Returns true if the emulated controller is in configuring mode
bool IsConfiguring() const; bool IsConfiguring() const;
/// Reload all input devices /// Reload all input devices
@ -215,19 +217,19 @@ public:
/** /**
* Updates the current mapped button device * Updates the current mapped button device
* @param ParamPackage with controller data to be mapped * @param param ParamPackage with controller data to be mapped
*/ */
void SetButtonParam(std::size_t index, Common::ParamPackage param); void SetButtonParam(std::size_t index, Common::ParamPackage param);
/** /**
* Updates the current mapped stick device * Updates the current mapped stick device
* @param ParamPackage with controller data to be mapped * @param param ParamPackage with controller data to be mapped
*/ */
void SetStickParam(std::size_t index, Common::ParamPackage param); void SetStickParam(std::size_t index, Common::ParamPackage param);
/** /**
* Updates the current mapped motion device * Updates the current mapped motion device
* @param ParamPackage with controller data to be mapped * @param param ParamPackage with controller data to be mapped
*/ */
void SetMotionParam(std::size_t index, Common::ParamPackage param); void SetMotionParam(std::size_t index, Common::ParamPackage param);
@ -270,13 +272,13 @@ public:
/// Returns the latest battery status from the controller /// Returns the latest battery status from the controller
BatteryLevelState GetBattery() const; BatteryLevelState GetBattery() const;
/* /**
* Sends a specific vibration to the output device * Sends a specific vibration to the output device
* @return returns true if vibration had no errors * @return returns true if vibration had no errors
*/ */
bool SetVibration(std::size_t device_index, VibrationValue vibration); bool SetVibration(std::size_t device_index, VibrationValue vibration);
/* /**
* Sends a small vibration to the output device * Sends a small vibration to the output device
* @return returns true if SetVibration was successfull * @return returns true if SetVibration was successfull
*/ */
@ -290,14 +292,14 @@ public:
/** /**
* Adds a callback to the list of events * Adds a callback to the list of events
* @param ConsoleUpdateCallback that will be triggered * @param update_callback A ConsoleUpdateCallback that will be triggered
* @return an unique key corresponding to the callback index in the list * @return an unique key corresponding to the callback index in the list
*/ */
int SetCallback(ControllerUpdateCallback update_callback); int SetCallback(ControllerUpdateCallback update_callback);
/** /**
* Removes a callback from the list stopping any future events to this object * Removes a callback from the list stopping any future events to this object
* @param Key corresponding to the callback index in the list * @param key Key corresponding to the callback index in the list
*/ */
void DeleteCallback(int key); void DeleteCallback(int key);
@ -310,43 +312,43 @@ private:
/** /**
* Updates the button status of the controller * Updates the button status of the controller
* @param callback: A CallbackStatus containing the button status * @param callback A CallbackStatus containing the button status
* @param index: Button ID of the to be updated * @param index Button ID of the to be updated
*/ */
void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
/** /**
* Updates the analog stick status of the controller * Updates the analog stick status of the controller
* @param callback: A CallbackStatus containing the analog stick status * @param callback A CallbackStatus containing the analog stick status
* @param index: stick ID of the to be updated * @param index stick ID of the to be updated
*/ */
void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
/** /**
* Updates the trigger status of the controller * Updates the trigger status of the controller
* @param callback: A CallbackStatus containing the trigger status * @param callback A CallbackStatus containing the trigger status
* @param index: trigger ID of the to be updated * @param index trigger ID of the to be updated
*/ */
void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
/** /**
* Updates the motion status of the controller * Updates the motion status of the controller
* @param callback: A CallbackStatus containing gyro and accelerometer data * @param callback A CallbackStatus containing gyro and accelerometer data
* @param index: motion ID of the to be updated * @param index motion ID of the to be updated
*/ */
void SetMotion(Common::Input::CallbackStatus callback, std::size_t index); void SetMotion(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Updates the battery status of the controller * Updates the battery status of the controller
* @param callback: A CallbackStatus containing the battery status * @param callback A CallbackStatus containing the battery status
* @param index: Button ID of the to be updated * @param index Button ID of the to be updated
*/ */
void SetBattery(Common::Input::CallbackStatus callback, std::size_t index); void SetBattery(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Triggers a callback that something has changed on the controller status * Triggers a callback that something has changed on the controller status
* @param type: Input type of the event to trigger * @param type Input type of the event to trigger
* @param is_service_update: indicates if this event should be sended to only services * @param is_service_update indicates if this event should only be sent to HID services
*/ */
void TriggerOnChange(ControllerTriggerType type, bool is_service_update); void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
@ -357,7 +359,7 @@ private:
f32 motion_sensitivity{0.01f}; f32 motion_sensitivity{0.01f};
bool force_update_motion{false}; bool force_update_motion{false};
// Temporary values to avoid doing changes while the controller is on configuration mode // Temporary values to avoid doing changes while the controller is in configuring mode
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
bool tmp_is_connected{false}; bool tmp_is_connected{false};

View file

@ -75,9 +75,9 @@ class EmulatedDevices {
public: public:
/** /**
* Contains all input data related to external devices that aren't necesarily a controller * Contains all input data related to external devices that aren't necesarily a controller
* like keyboard and mouse * This includes devices such as the keyboard or mouse
*/ */
EmulatedDevices(); explicit EmulatedDevices();
~EmulatedDevices(); ~EmulatedDevices();
YUZU_NON_COPYABLE(EmulatedDevices); YUZU_NON_COPYABLE(EmulatedDevices);
@ -86,14 +86,16 @@ public:
/// Removes all callbacks created from input devices /// Removes all callbacks created from input devices
void UnloadInput(); void UnloadInput();
/// Sets the emulated console into configuring mode. Locking all HID service events from being /**
/// moddified * Sets the emulated devices into configuring mode
* This prevents the modification of the HID state of the emulated devices by input commands
*/
void EnableConfiguration(); void EnableConfiguration();
/// Returns the emulated console to the normal behaivour /// Returns the emulated devices into normal mode, allowing the modification of the HID state
void DisableConfiguration(); void DisableConfiguration();
/// Returns true if the emulated device is on configuring mode /// Returns true if the emulated device is in configuring mode
bool IsConfiguring() const; bool IsConfiguring() const;
/// Reload all input devices /// Reload all input devices
@ -134,14 +136,14 @@ public:
/** /**
* Adds a callback to the list of events * Adds a callback to the list of events
* @param InterfaceUpdateCallback that will be triggered * @param update_callback InterfaceUpdateCallback that will be triggered
* @return an unique key corresponding to the callback index in the list * @return an unique key corresponding to the callback index in the list
*/ */
int SetCallback(InterfaceUpdateCallback update_callback); int SetCallback(InterfaceUpdateCallback update_callback);
/** /**
* Removes a callback from the list stopping any future events to this object * Removes a callback from the list stopping any future events to this object
* @param Key corresponding to the callback index in the list * @param key Key corresponding to the callback index in the list
*/ */
void DeleteCallback(int key); void DeleteCallback(int key);
@ -151,42 +153,42 @@ private:
/** /**
* Updates the touch status of the keyboard device * Updates the touch status of the keyboard device
* @param callback: A CallbackStatus containing the key status * @param callback A CallbackStatus containing the key status
* @param index: key ID to be updated * @param index key ID to be updated
*/ */
void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index); void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Updates the keyboard status of the keyboard device * Updates the keyboard status of the keyboard device
* @param callback: A CallbackStatus containing the modifier key status * @param callback A CallbackStatus containing the modifier key status
* @param index: modifier key ID to be updated * @param index modifier key ID to be updated
*/ */
void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index); void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Updates the mouse button status of the mouse device * Updates the mouse button status of the mouse device
* @param callback: A CallbackStatus containing the button status * @param callback A CallbackStatus containing the button status
* @param index: Button ID to be updated * @param index Button ID to be updated
*/ */
void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index); void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Updates the mouse wheel status of the mouse device * Updates the mouse wheel status of the mouse device
* @param callback: A CallbackStatus containing the wheel status * @param callback A CallbackStatus containing the wheel status
* @param index: wheel ID to be updated * @param index wheel ID to be updated
*/ */
void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index); void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index);
/** /**
* Updates the mouse position status of the mouse device * Updates the mouse position status of the mouse device
* @param callback: A CallbackStatus containing the position status * @param callback A CallbackStatus containing the position status
* @param index: stick ID to be updated * @param index stick ID to be updated
*/ */
void SetMouseStick(Common::Input::CallbackStatus callback); void SetMouseStick(Common::Input::CallbackStatus callback);
/** /**
* Triggers a callback that something has changed on the device status * Triggers a callback that something has changed on the device status
* @param Input type of the event to trigger * @param type Input type of the event to trigger
*/ */
void TriggerOnChange(DeviceTriggerType type); void TriggerOnChange(DeviceTriggerType type);

View file

@ -135,6 +135,32 @@ NpadIdType HIDCore::GetFirstNpadId() const {
return NpadIdType::Player1; return NpadIdType::Player1;
} }
void HIDCore::EnableAllControllerConfiguration() {
player_1->EnableConfiguration();
player_2->EnableConfiguration();
player_3->EnableConfiguration();
player_4->EnableConfiguration();
player_5->EnableConfiguration();
player_6->EnableConfiguration();
player_7->EnableConfiguration();
player_8->EnableConfiguration();
other->EnableConfiguration();
handheld->EnableConfiguration();
}
void HIDCore::DisableAllControllerConfiguration() {
player_1->DisableConfiguration();
player_2->DisableConfiguration();
player_3->DisableConfiguration();
player_4->DisableConfiguration();
player_5->DisableConfiguration();
player_6->DisableConfiguration();
player_7->DisableConfiguration();
player_8->DisableConfiguration();
other->DisableConfiguration();
handheld->DisableConfiguration();
}
void HIDCore::ReloadInputDevices() { void HIDCore::ReloadInputDevices() {
player_1->ReloadFromSettings(); player_1->ReloadFromSettings();
player_2->ReloadFromSettings(); player_2->ReloadFromSettings();

View file

@ -45,6 +45,12 @@ public:
/// Returns the first connected npad id /// Returns the first connected npad id
NpadIdType GetFirstNpadId() const; NpadIdType GetFirstNpadId() const;
/// Sets all emulated controllers into configuring mode.
void EnableAllControllerConfiguration();
/// Sets all emulated controllers into normal mode.
void DisableAllControllerConfiguration();
/// Reloads all input devices from settings /// Reloads all input devices from settings
void ReloadInputDevices(); void ReloadInputDevices();

View file

@ -63,6 +63,8 @@ enum class NpadButton : u64 {
LagonCUp = 1ULL << 32, LagonCUp = 1ULL << 32,
LagonCRight = 1ULL << 33, LagonCRight = 1ULL << 33,
LagonCDown = 1ULL << 34, LagonCDown = 1ULL << 34,
All = 0xFFFFFFFFFFFFFFFFULL,
}; };
DECLARE_ENUM_FLAG_OPERATORS(NpadButton); DECLARE_ENUM_FLAG_OPERATORS(NpadButton);

View file

@ -21,7 +21,7 @@ namespace Core::HID {
/** /**
* Converts raw input data into a valid battery status. * Converts raw input data into a valid battery status.
* *
* @param Supported callbacks: Analog, Battery, Trigger. * @param callback Supported callbacks: Analog, Battery, Trigger.
* @return A valid BatteryStatus object. * @return A valid BatteryStatus object.
*/ */
Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback); Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback);
@ -29,7 +29,7 @@ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackSta
/** /**
* Converts raw input data into a valid button status. Applies invert properties to the output. * Converts raw input data into a valid button status. Applies invert properties to the output.
* *
* @param Supported callbacks: Analog, Button, Trigger. * @param callback Supported callbacks: Analog, Button, Trigger.
* @return A valid TouchStatus object. * @return A valid TouchStatus object.
*/ */
Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback); Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback);
@ -37,7 +37,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu
/** /**
* Converts raw input data into a valid motion status. * Converts raw input data into a valid motion status.
* *
* @param Supported callbacks: Motion. * @param callback Supported callbacks: Motion.
* @return A valid TouchStatus object. * @return A valid TouchStatus object.
*/ */
Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback); Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback);
@ -46,7 +46,7 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu
* Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert
* properties to the output. * properties to the output.
* *
* @param Supported callbacks: Stick. * @param callback Supported callbacks: Stick.
* @return A valid StickStatus object. * @return A valid StickStatus object.
*/ */
Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback); Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback);
@ -54,7 +54,7 @@ Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus&
/** /**
* Converts raw input data into a valid touch status. * Converts raw input data into a valid touch status.
* *
* @param Supported callbacks: Touch. * @param callback Supported callbacks: Touch.
* @return A valid TouchStatus object. * @return A valid TouchStatus object.
*/ */
Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback); Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback);
@ -63,7 +63,7 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
* Converts raw input data into a valid trigger status. Applies offset, deadzone, range and * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and
* invert properties to the output. Button status uses the threshold property if necessary. * invert properties to the output. Button status uses the threshold property if necessary.
* *
* @param Supported callbacks: Analog, Button, Trigger. * @param callback Supported callbacks: Analog, Button, Trigger.
* @return A valid TriggerStatus object. * @return A valid TriggerStatus object.
*/ */
Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback);
@ -72,22 +72,23 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta
* Converts raw input data into a valid analog status. Applies offset, deadzone, range and * Converts raw input data into a valid analog status. Applies offset, deadzone, range and
* invert properties to the output. * invert properties to the output.
* *
* @param Supported callbacks: Analog. * @param callback Supported callbacks: Analog.
* @return A valid AnalogStatus object. * @return A valid AnalogStatus object.
*/ */
Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback);
/** /**
* Converts raw analog data into a valid analog value * Converts raw analog data into a valid analog value
* @param An analog object containing raw data and properties, bool that determines if the value * @param analog An analog object containing raw data and properties
* needs to be clamped between -1.0f and 1.0f. * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f.
*/ */
void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value); void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value);
/** /**
* Converts raw stick data into a valid stick value * Converts raw stick data into a valid stick value
* @param Two analog objects containing raw data and properties, bool that determines if the value * @param analog_x raw analog data and properties for the x-axis
* needs to be clamped into the unit circle. * @param analog_y raw analog data and properties for the y-axis
* @param clamp_value bool that determines if the value needs to be clamped into the unit circle.
*/ */
void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y,
bool clamp_value); bool clamp_value);

View file

@ -20,7 +20,7 @@ InputInterpreter::InputInterpreter(Core::System& system)
InputInterpreter::~InputInterpreter() = default; InputInterpreter::~InputInterpreter() = default;
void InputInterpreter::PollInput() { void InputInterpreter::PollInput() {
const u64 button_state = npad.GetAndResetPressState(); const auto button_state = npad.GetAndResetPressState();
previous_index = current_index; previous_index = current_index;
current_index = (current_index + 1) % button_states.size(); current_index = (current_index + 1) % button_states.size();
@ -32,30 +32,30 @@ void InputInterpreter::ResetButtonStates() {
previous_index = 0; previous_index = 0;
current_index = 0; current_index = 0;
button_states[0] = 0xFFFFFFFFFFFFFFFF; button_states[0] = Core::HID::NpadButton::All;
for (std::size_t i = 1; i < button_states.size(); ++i) { for (std::size_t i = 1; i < button_states.size(); ++i) {
button_states[i] = 0; button_states[i] = Core::HID::NpadButton::None;
} }
} }
bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const {
return (button_states[current_index] & static_cast<u64>(button)) != 0; return True(button_states[current_index] & button);
} }
bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const {
const bool current_press = (button_states[current_index] & static_cast<u64>(button)) != 0; const bool current_press = True(button_states[current_index] & button);
const bool previous_press = (button_states[previous_index] & static_cast<u64>(button)) != 0; const bool previous_press = True(button_states[previous_index] & button);
return current_press && !previous_press; return current_press && !previous_press;
} }
bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const {
u64 held_buttons{button_states[0]}; Core::HID::NpadButton held_buttons{button_states[0]};
for (std::size_t i = 1; i < button_states.size(); ++i) { for (std::size_t i = 1; i < button_states.size(); ++i) {
held_buttons &= button_states[i]; held_buttons &= button_states[i];
} }
return (held_buttons & static_cast<u64>(button)) != 0; return True(held_buttons & button);
} }

View file

@ -105,7 +105,7 @@ private:
Service::HID::Controller_NPad& npad; Service::HID::Controller_NPad& npad;
/// Stores 9 consecutive button states polled from HID. /// Stores 9 consecutive button states polled from HID.
std::array<u64, 9> button_states{}; std::array<Core::HID::NpadButton, 9> button_states{};
std::size_t previous_index{}; std::size_t previous_index{};
std::size_t current_index{}; std::size_t current_index{};

View file

@ -510,7 +510,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
libnx_state.r_stick = pad_state.r_stick; libnx_state.r_stick = pad_state.r_stick;
npad.system_ext_lifo.WriteNextEntry(pad_state); npad.system_ext_lifo.WriteNextEntry(pad_state);
press_state |= static_cast<u32>(pad_state.npad_buttons.raw); press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
&controller.shared_memory_entry, sizeof(NpadInternalState)); &controller.shared_memory_entry, sizeof(NpadInternalState));
@ -635,7 +635,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
// This buffer only is updated on handheld on HW // This buffer only is updated on handheld on HW
npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
} else { } else {
// Hanheld doesn't update this buffer on HW // Handheld doesn't update this buffer on HW
npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
} }
@ -1149,8 +1149,8 @@ void Controller_NPad::ClearAllControllers() {
} }
} }
u32 Controller_NPad::GetAndResetPressState() { Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
return press_state.exchange(0); return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
} }
bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {

View file

@ -179,7 +179,7 @@ public:
// Logical OR for all buttons presses on all controllers // Logical OR for all buttons presses on all controllers
// Specifically for cheat engine and other features. // Specifically for cheat engine and other features.
u32 GetAndResetPressState(); Core::HID::NpadButton GetAndResetPressState();
static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle); static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
@ -503,7 +503,7 @@ private:
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
std::atomic<u32> press_state{}; std::atomic<u64> press_state{};
std::array<NpadControllerData, 10> controller_data{}; std::array<NpadControllerData, 10> controller_data{};
KernelHelpers::ServiceContext& service_context; KernelHelpers::ServiceContext& service_context;

View file

@ -19,7 +19,6 @@
namespace Core::Memory { namespace Core::Memory {
namespace { namespace {
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12}; constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) { std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) {
auto end_index = start_index; auto end_index = start_index;
@ -61,7 +60,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
applet_resource applet_resource
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad) ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)
.GetAndResetPressState(); .GetAndResetPressState();
return press_state & KEYPAD_BITMASK; return static_cast<u64>(press_state & HID::NpadButton::All);
} }
void StandardVmCallbacks::DebugLog(u8 id, u64 value) { void StandardVmCallbacks::DebugLog(u8 id, u64 value) {

View file

@ -388,8 +388,6 @@ void SDLDriver::CloseJoysticks() {
} }
SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engine_) { SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engine_) {
Common::SetCurrentThreadName("yuzu:input:SDL");
if (!Settings::values.enable_raw_input) { if (!Settings::values.enable_raw_input) {
// Disable raw input. When enabled this setting causes SDL to die when a web applet opens // Disable raw input. When enabled this setting causes SDL to die when a web applet opens
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
@ -422,6 +420,7 @@ SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engin
initialized = true; initialized = true;
if (start_thread) { if (start_thread) {
poll_thread = std::thread([this] { poll_thread = std::thread([this] {
Common::SetCurrentThreadName("yuzu:input:SDL");
using namespace std::chrono_literals; using namespace std::chrono_literals;
while (initialized) { while (initialized) {
SDL_PumpEvents(); SDL_PumpEvents();

View file

@ -126,8 +126,6 @@ add_executable(yuzu
configuration/configure_web.ui configuration/configure_web.ui
configuration/input_profiles.cpp configuration/input_profiles.cpp
configuration/input_profiles.h configuration/input_profiles.h
controller_navigation.cpp
controller_navigation.h
debugger/console.cpp debugger/console.cpp
debugger/console.h debugger/console.h
debugger/controller.cpp debugger/controller.cpp
@ -154,6 +152,8 @@ add_executable(yuzu
main.ui main.ui
uisettings.cpp uisettings.cpp
uisettings.h uisettings.h
util/controller_navigation.cpp
util/controller_navigation.h
util/limitable_input_dialog.cpp util/limitable_input_dialog.cpp
util/limitable_input_dialog.h util/limitable_input_dialog.h
util/overlay_dialog.cpp util/overlay_dialog.cpp

View file

@ -139,7 +139,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
DisableUnsupportedPlayers(); DisableUnsupportedPlayers();
for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) { for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
system.HIDCore().GetEmulatedControllerByIndex(player_index)->EnableConfiguration();
SetEmulatedControllers(player_index); SetEmulatedControllers(player_index);
} }
@ -201,23 +200,10 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
&QtControllerSelectorDialog::ApplyConfiguration); &QtControllerSelectorDialog::ApplyConfiguration);
controller_navigation = new ControllerNavigation(system.HIDCore(), this);
connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
[this](Qt::Key key) {
if (!this->isActiveWindow()) {
return;
}
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
QCoreApplication::postEvent(this, event);
});
// Enhancement: Check if the parameters have already been met before disconnecting controllers. // Enhancement: Check if the parameters have already been met before disconnecting controllers.
// If all the parameters are met AND only allows a single player, // If all the parameters are met AND only allows a single player,
// stop the constructor here as we do not need to continue. // stop the constructor here as we do not need to continue.
if (CheckIfParametersMet() && parameters.enable_single_mode) { if (CheckIfParametersMet() && parameters.enable_single_mode) {
for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
system.HIDCore().GetEmulatedControllerByIndex(player_index)->DisableConfiguration();
}
return; return;
} }
@ -232,8 +218,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
} }
QtControllerSelectorDialog::~QtControllerSelectorDialog() { QtControllerSelectorDialog::~QtControllerSelectorDialog() {
controller_navigation->UnloadController(); system.HIDCore().DisableAllControllerConfiguration();
}; }
int QtControllerSelectorDialog::exec() { int QtControllerSelectorDialog::exec() {
if (parameters_met && parameters.enable_single_mode) { if (parameters_met && parameters.enable_single_mode) {
@ -249,12 +235,11 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
system.HIDCore().GetEmulatedControllerByIndex(player_index)->DisableConfiguration();
}
} }
void QtControllerSelectorDialog::LoadConfiguration() { void QtControllerSelectorDialog::LoadConfiguration() {
system.HIDCore().EnableAllControllerConfiguration();
const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);

View file

@ -7,9 +7,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <QDialog> #include <QDialog>
#include "core/core.h"
#include "core/frontend/applets/controller.h" #include "core/frontend/applets/controller.h"
#include "yuzu/controller_navigation.h"
class GMainWindow; class GMainWindow;
class QCheckBox; class QCheckBox;
@ -33,8 +31,9 @@ class System;
} }
namespace Core::HID { namespace Core::HID {
class HIDCore;
enum class NpadStyleIndex : u8; enum class NpadStyleIndex : u8;
} } // namespace Core::HID
class QtControllerSelectorDialog final : public QDialog { class QtControllerSelectorDialog final : public QDialog {
Q_OBJECT Q_OBJECT
@ -149,9 +148,6 @@ private:
// Checkboxes representing the "Connected Controllers". // Checkboxes representing the "Connected Controllers".
std::array<QCheckBox*, NUM_PLAYERS> connected_controller_checkboxes; std::array<QCheckBox*, NUM_PLAYERS> connected_controller_checkboxes;
// QObject for navigating the UI with a controller
ControllerNavigation* controller_navigation = nullptr;
}; };
class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet { class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet {

View file

@ -17,6 +17,7 @@
#include "core/hle/lock.h" #include "core/hle/lock.h"
#include "yuzu/applets/qt_profile_select.h" #include "yuzu/applets/qt_profile_select.h"
#include "yuzu/main.h" #include "yuzu/main.h"
#include "yuzu/util/controller_navigation.h"
namespace { namespace {
QString FormatUserEntryText(const QString& username, Common::UUID uuid) { QString FormatUserEntryText(const QString& username, Common::UUID uuid) {

View file

@ -10,8 +10,8 @@
#include <QTreeView> #include <QTreeView>
#include "core/frontend/applets/profile_select.h" #include "core/frontend/applets/profile_select.h"
#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/acc/profile_manager.h"
#include "yuzu/controller_navigation.h"
class ControllerNavigation;
class GMainWindow; class GMainWindow;
class QDialogButtonBox; class QDialogButtonBox;
class QGraphicsScene; class QGraphicsScene;
@ -21,6 +21,10 @@ class QStandardItem;
class QStandardItemModel; class QStandardItemModel;
class QVBoxLayout; class QVBoxLayout;
namespace Core::HID {
class HIDCore;
} // namespace Core::HID
class QtProfileSelectionDialog final : public QDialog { class QtProfileSelectionDialog final : public QDialog {
Q_OBJECT Q_OBJECT

View file

@ -246,15 +246,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
if (player_index == 0) { if (player_index == 0) {
auto* emulated_controller_p1 = auto* emulated_controller_p1 =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
auto* emulated_controller_hanheld = auto* emulated_controller_handheld =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
emulated_controller_p1->SaveCurrentConfig(); emulated_controller_p1->SaveCurrentConfig();
emulated_controller_p1->EnableConfiguration(); emulated_controller_p1->EnableConfiguration();
emulated_controller_hanheld->SaveCurrentConfig(); emulated_controller_handheld->SaveCurrentConfig();
emulated_controller_hanheld->EnableConfiguration(); emulated_controller_handheld->EnableConfiguration();
if (emulated_controller_hanheld->IsConnected(true)) { if (emulated_controller_handheld->IsConnected(true)) {
emulated_controller_p1->Disconnect(); emulated_controller_p1->Disconnect();
emulated_controller = emulated_controller_hanheld; emulated_controller = emulated_controller_handheld;
} else { } else {
emulated_controller = emulated_controller_p1; emulated_controller = emulated_controller_p1;
} }
@ -590,19 +590,19 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
if (player_index == 0) { if (player_index == 0) {
auto* emulated_controller_p1 = auto* emulated_controller_p1 =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
auto* emulated_controller_hanheld = auto* emulated_controller_handheld =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
bool is_connected = emulated_controller->IsConnected(true); bool is_connected = emulated_controller->IsConnected(true);
emulated_controller_p1->SetNpadStyleIndex(type); emulated_controller_p1->SetNpadStyleIndex(type);
emulated_controller_hanheld->SetNpadStyleIndex(type); emulated_controller_handheld->SetNpadStyleIndex(type);
if (is_connected) { if (is_connected) {
if (type == Core::HID::NpadStyleIndex::Handheld) { if (type == Core::HID::NpadStyleIndex::Handheld) {
emulated_controller_p1->Disconnect(); emulated_controller_p1->Disconnect();
emulated_controller_hanheld->Connect(); emulated_controller_handheld->Connect();
emulated_controller = emulated_controller_hanheld; emulated_controller = emulated_controller_handheld;
} else { } else {
emulated_controller_hanheld->Disconnect(); emulated_controller_handheld->Disconnect();
emulated_controller_p1->Connect(); emulated_controller_p1->Connect();
emulated_controller = emulated_controller_p1; emulated_controller = emulated_controller_p1;
} }
@ -650,10 +650,10 @@ ConfigureInputPlayer::~ConfigureInputPlayer() {
if (player_index == 0) { if (player_index == 0) {
auto* emulated_controller_p1 = auto* emulated_controller_p1 =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
auto* emulated_controller_hanheld = auto* emulated_controller_handheld =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
emulated_controller_p1->DisableConfiguration(); emulated_controller_p1->DisableConfiguration();
emulated_controller_hanheld->DisableConfiguration(); emulated_controller_handheld->DisableConfiguration();
} else { } else {
emulated_controller->DisableConfiguration(); emulated_controller->DisableConfiguration();
} }
@ -663,14 +663,14 @@ void ConfigureInputPlayer::ApplyConfiguration() {
if (player_index == 0) { if (player_index == 0) {
auto* emulated_controller_p1 = auto* emulated_controller_p1 =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
auto* emulated_controller_hanheld = auto* emulated_controller_handheld =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
emulated_controller_p1->DisableConfiguration(); emulated_controller_p1->DisableConfiguration();
emulated_controller_p1->SaveCurrentConfig(); emulated_controller_p1->SaveCurrentConfig();
emulated_controller_p1->EnableConfiguration(); emulated_controller_p1->EnableConfiguration();
emulated_controller_hanheld->DisableConfiguration(); emulated_controller_handheld->DisableConfiguration();
emulated_controller_hanheld->SaveCurrentConfig(); emulated_controller_handheld->SaveCurrentConfig();
emulated_controller_hanheld->EnableConfiguration(); emulated_controller_handheld->EnableConfiguration();
return; return;
} }
emulated_controller->DisableConfiguration(); emulated_controller->DisableConfiguration();

View file

@ -26,6 +26,7 @@
#include "yuzu/game_list_worker.h" #include "yuzu/game_list_worker.h"
#include "yuzu/main.h" #include "yuzu/main.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
#include "yuzu/util/controller_navigation.h"
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent)
: QObject(parent), gamelist{gamelist} {} : QObject(parent), gamelist{gamelist} {}

View file

@ -23,8 +23,8 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "uisettings.h" #include "uisettings.h"
#include "yuzu/compatibility_list.h" #include "yuzu/compatibility_list.h"
#include "yuzu/controller_navigation.h"
class ControllerNavigation;
class GameListWorker; class GameListWorker;
class GameListSearchField; class GameListSearchField;
class GameListDir; class GameListDir;

View file

@ -0,0 +1,177 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#include "common/settings_input.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "yuzu/util/controller_navigation.h"
ControllerNavigation::ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent) {
player1_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
handheld_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdateEvent(type); },
.is_npad_service = false,
};
player1_callback_key = player1_controller->SetCallback(engine_callback);
handheld_callback_key = handheld_controller->SetCallback(engine_callback);
is_controller_set = true;
}
ControllerNavigation::~ControllerNavigation() {
UnloadController();
}
void ControllerNavigation::UnloadController() {
if (is_controller_set) {
player1_controller->DeleteCallback(player1_callback_key);
handheld_controller->DeleteCallback(handheld_callback_key);
is_controller_set = false;
}
}
void ControllerNavigation::TriggerButton(Settings::NativeButton::Values native_button,
Qt::Key key) {
if (button_values[native_button].value && !button_values[native_button].locked) {
emit TriggerKeyboardEvent(key);
}
}
void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) {
std::lock_guard lock{mutex};
if (type == Core::HID::ControllerTriggerType::Button) {
ControllerUpdateButton();
return;
}
if (type == Core::HID::ControllerTriggerType::Stick) {
ControllerUpdateStick();
return;
}
}
void ControllerNavigation::ControllerUpdateButton() {
const auto controller_type = player1_controller->GetNpadStyleIndex();
const auto& player1_buttons = player1_controller->GetButtonsValues();
const auto& handheld_buttons = handheld_controller->GetButtonsValues();
for (std::size_t i = 0; i < player1_buttons.size(); ++i) {
const bool button = player1_buttons[i].value || handheld_buttons[i].value;
// Trigger only once
button_values[i].locked = button == button_values[i].value;
button_values[i].value = button;
}
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::GameCube:
TriggerButton(Settings::NativeButton::A, Qt::Key_Enter);
TriggerButton(Settings::NativeButton::B, Qt::Key_Escape);
TriggerButton(Settings::NativeButton::DDown, Qt::Key_Down);
TriggerButton(Settings::NativeButton::DLeft, Qt::Key_Left);
TriggerButton(Settings::NativeButton::DRight, Qt::Key_Right);
TriggerButton(Settings::NativeButton::DUp, Qt::Key_Up);
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
TriggerButton(Settings::NativeButton::DDown, Qt::Key_Enter);
TriggerButton(Settings::NativeButton::DLeft, Qt::Key_Escape);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
TriggerButton(Settings::NativeButton::X, Qt::Key_Enter);
TriggerButton(Settings::NativeButton::A, Qt::Key_Escape);
break;
default:
break;
}
}
void ControllerNavigation::ControllerUpdateStick() {
const auto controller_type = player1_controller->GetNpadStyleIndex();
const auto& player1_sticks = player1_controller->GetSticksValues();
const auto& handheld_sticks = player1_controller->GetSticksValues();
bool update = false;
for (std::size_t i = 0; i < player1_sticks.size(); ++i) {
const Common::Input::StickStatus stick{
.left = player1_sticks[i].left || handheld_sticks[i].left,
.right = player1_sticks[i].right || handheld_sticks[i].right,
.up = player1_sticks[i].up || handheld_sticks[i].up,
.down = player1_sticks[i].down || handheld_sticks[i].down,
};
// Trigger only once
if (stick.down != stick_values[i].down || stick.left != stick_values[i].left ||
stick.right != stick_values[i].right || stick.up != stick_values[i].up) {
update = true;
}
stick_values[i] = stick;
}
if (!update) {
return;
}
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::GameCube:
if (stick_values[Settings::NativeAnalog::LStick].down) {
emit TriggerKeyboardEvent(Qt::Key_Down);
return;
}
if (stick_values[Settings::NativeAnalog::LStick].left) {
emit TriggerKeyboardEvent(Qt::Key_Left);
return;
}
if (stick_values[Settings::NativeAnalog::LStick].right) {
emit TriggerKeyboardEvent(Qt::Key_Right);
return;
}
if (stick_values[Settings::NativeAnalog::LStick].up) {
emit TriggerKeyboardEvent(Qt::Key_Up);
return;
}
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
if (stick_values[Settings::NativeAnalog::LStick].left) {
emit TriggerKeyboardEvent(Qt::Key_Down);
return;
}
if (stick_values[Settings::NativeAnalog::LStick].up) {
emit TriggerKeyboardEvent(Qt::Key_Left);
return;
}
if (stick_values[Settings::NativeAnalog::LStick].down) {
emit TriggerKeyboardEvent(Qt::Key_Right);
return;
}
if (stick_values[Settings::NativeAnalog::LStick].right) {
emit TriggerKeyboardEvent(Qt::Key_Up);
return;
}
break;
case Core::HID::NpadStyleIndex::JoyconRight:
if (stick_values[Settings::NativeAnalog::RStick].right) {
emit TriggerKeyboardEvent(Qt::Key_Down);
return;
}
if (stick_values[Settings::NativeAnalog::RStick].down) {
emit TriggerKeyboardEvent(Qt::Key_Left);
return;
}
if (stick_values[Settings::NativeAnalog::RStick].up) {
emit TriggerKeyboardEvent(Qt::Key_Right);
return;
}
if (stick_values[Settings::NativeAnalog::RStick].left) {
emit TriggerKeyboardEvent(Qt::Key_Up);
return;
}
break;
default:
break;
}
}

View file

@ -0,0 +1,48 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#pragma once
#include <QKeyEvent>
#include <QObject>
#include "common/input.h"
#include "common/settings.h"
#include "core/hid/emulated_controller.h"
namespace Core::HID {
class HIDCore;
} // namespace Core::HID
class ControllerNavigation : public QObject {
Q_OBJECT
public:
explicit ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent = nullptr);
~ControllerNavigation();
/// Disables events from the emulated controller
void UnloadController();
signals:
void TriggerKeyboardEvent(Qt::Key key);
private:
void TriggerButton(Settings::NativeButton::Values native_button, Qt::Key key);
void ControllerUpdateEvent(Core::HID::ControllerTriggerType type);
void ControllerUpdateButton();
void ControllerUpdateStick();
Core::HID::ButtonValues button_values{};
Core::HID::SticksValues stick_values{};
int player1_callback_key{};
int handheld_callback_key{};
bool is_controller_set{};
mutable std::mutex mutex;
Core::HID::EmulatedController* player1_controller;
Core::HID::EmulatedController* handheld_controller;
};