Răsfoiți Sursa

core/hid: Prevent Emulated controller from flapping with multiple inputs devices

german77 4 ani în urmă
părinte
comite
157e0b85fd

+ 4 - 0
src/common/input.h

@@ -11,6 +11,7 @@
 #include <utility>
 #include "common/logging/log.h"
 #include "common/param_package.h"
+#include "common/uuid.h"
 
 namespace Common::Input {
 
@@ -81,6 +82,7 @@ struct AnalogStatus {
 };
 
 struct ButtonStatus {
+    Common::UUID uuid{};
     bool value{};
     bool inverted{};
     bool toggle{};
@@ -90,6 +92,7 @@ struct ButtonStatus {
 using BatteryStatus = BatteryLevel;
 
 struct StickStatus {
+    Common::UUID uuid{};
     AnalogStatus x{};
     AnalogStatus y{};
     bool left{};
@@ -99,6 +102,7 @@ struct StickStatus {
 };
 
 struct TriggerStatus {
+    Common::UUID uuid{};
     AnalogStatus analog{};
     ButtonStatus pressed{};
 };

+ 58 - 10
src/core/hid/emulated_controller.cpp

@@ -183,8 +183,11 @@ void EmulatedController::ReloadInput() {
         if (!button_devices[index]) {
             continue;
         }
+        const auto uuid = Common::UUID{button_params[index].Get("guid", "")};
         Common::Input::InputCallback button_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }};
+            [this, index, uuid](Common::Input::CallbackStatus callback) {
+                SetButton(callback, index, uuid);
+            }};
         button_devices[index]->SetCallback(button_callback);
         button_devices[index]->ForceUpdate();
     }
@@ -193,8 +196,11 @@ void EmulatedController::ReloadInput() {
         if (!stick_devices[index]) {
             continue;
         }
+        const auto uuid = Common::UUID{stick_params[index].Get("guid", "")};
         Common::Input::InputCallback stick_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }};
+            [this, index, uuid](Common::Input::CallbackStatus callback) {
+                SetStick(callback, index, uuid);
+            }};
         stick_devices[index]->SetCallback(stick_callback);
         stick_devices[index]->ForceUpdate();
     }
@@ -203,8 +209,11 @@ void EmulatedController::ReloadInput() {
         if (!trigger_devices[index]) {
             continue;
         }
+        const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")};
         Common::Input::InputCallback trigger_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }};
+            [this, index, uuid](Common::Input::CallbackStatus callback) {
+                SetTrigger(callback, index, uuid);
+            }};
         trigger_devices[index]->SetCallback(trigger_callback);
         trigger_devices[index]->ForceUpdate();
     }
@@ -229,13 +238,18 @@ void EmulatedController::ReloadInput() {
         motion_devices[index]->ForceUpdate();
     }
 
+    // Use a common UUID for TAS
+    const auto tas_uuid = Common::UUID{0x0, 0x7A5};
+
     // Register TAS devices. No need to force update
     for (std::size_t index = 0; index < tas_button_devices.size(); ++index) {
         if (!tas_button_devices[index]) {
             continue;
         }
         Common::Input::InputCallback button_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }};
+            [this, index, tas_uuid](Common::Input::CallbackStatus callback) {
+                SetButton(callback, index, tas_uuid);
+            }};
         tas_button_devices[index]->SetCallback(button_callback);
     }
 
@@ -244,7 +258,9 @@ void EmulatedController::ReloadInput() {
             continue;
         }
         Common::Input::InputCallback stick_callback{
-            [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }};
+            [this, index, tas_uuid](Common::Input::CallbackStatus callback) {
+                SetStick(callback, index, tas_uuid);
+            }};
         tas_stick_devices[index]->SetCallback(stick_callback);
     }
 }
@@ -423,7 +439,8 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage
     ReloadInput();
 }
 
-void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index,
+                                   Common::UUID uuid) {
     if (index >= controller.button_values.size()) {
         return;
     }
@@ -432,7 +449,16 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::
         bool value_changed = false;
         const auto new_status = TransformToButton(callback);
         auto& current_status = controller.button_values[index];
+
+        // Only read button values that have the same uuid or are pressed once
+        if (current_status.uuid != uuid) {
+            if (!new_status.value) {
+                return;
+            }
+        }
+
         current_status.toggle = new_status.toggle;
+        current_status.uuid = uuid;
 
         // Update button status with current
         if (!current_status.toggle) {
@@ -553,12 +579,23 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::
     TriggerOnChange(ControllerTriggerType::Button, true);
 }
 
-void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index,
+                                  Common::UUID uuid) {
     if (index >= controller.stick_values.size()) {
         return;
     }
     std::lock_guard lock{mutex};
-    controller.stick_values[index] = TransformToStick(callback);
+    const auto stick_value = TransformToStick(callback);
+
+    // Only read stick values that have the same uuid or are over the threshold to avoid flapping
+    if (controller.stick_values[index].uuid != uuid) {
+        if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) {
+            return;
+        }
+    }
+
+    controller.stick_values[index] = stick_value;
+    controller.stick_values[index].uuid = uuid;
 
     if (is_configuring) {
         controller.analog_stick_state.left = {};
@@ -592,12 +629,23 @@ void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::s
     TriggerOnChange(ControllerTriggerType::Stick, true);
 }
 
-void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) {
+void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index,
+                                    Common::UUID uuid) {
     if (index >= controller.trigger_values.size()) {
         return;
     }
     std::lock_guard lock{mutex};
-    controller.trigger_values[index] = TransformToTrigger(callback);
+    const auto trigger_value = TransformToTrigger(callback);
+
+    // Only read trigger values that have the same uuid or are pressed once
+    if (controller.stick_values[index].uuid != uuid) {
+        if (!trigger_value.pressed.value) {
+            return;
+        }
+    }
+
+    controller.trigger_values[index] = trigger_value;
+    controller.trigger_values[index].uuid = uuid;
 
     if (is_configuring) {
         controller.gc_trigger_state.left = 0;

+ 3 - 3
src/core/hid/emulated_controller.h

@@ -313,21 +313,21 @@ private:
      * @param callback: A CallbackStatus containing the button status
      * @param index: Button ID of the to be updated
      */
-    void SetButton(Common::Input::CallbackStatus callback, std::size_t index);
+    void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
 
     /**
      * 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
      */
-    void SetStick(Common::Input::CallbackStatus callback, std::size_t index);
+    void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
 
     /**
      * Updates the trigger status of the controller
      * @param callback: A CallbackStatus containing the trigger status
      * @param index: trigger ID of the to be updated
      */
-    void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index);
+    void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
 
     /**
      * Updates the motion status of the controller

+ 9 - 15
src/input_common/drivers/tas_input.cpp

@@ -71,21 +71,21 @@ Tas::~Tas() {
 void Tas::LoadTasFiles() {
     script_length = 0;
     for (size_t i = 0; i < commands.size(); i++) {
-        LoadTasFile(i);
+        LoadTasFile(i, 0);
         if (commands[i].size() > script_length) {
             script_length = commands[i].size();
         }
     }
 }
 
-void Tas::LoadTasFile(size_t player_index) {
+void Tas::LoadTasFile(size_t player_index, size_t file_index) {
     if (!commands[player_index].empty()) {
         commands[player_index].clear();
     }
-    std::string file =
-        Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
-                                           fmt::format("script0-{}.txt", player_index + 1),
-                                       Common::FS::FileType::BinaryFile);
+    std::string file = Common::FS::ReadStringFromFile(
+        Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
+            fmt::format("script{}-{}.txt", file_index, player_index + 1),
+        Common::FS::FileType::BinaryFile);
     std::stringstream command_line(file);
     std::string line;
     int frame_no = 0;
@@ -144,15 +144,8 @@ void Tas::WriteTasFile(std::u8string file_name) {
 void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) {
     last_input = {
         .buttons = buttons,
-        .l_axis = FlipAxisY(left_axis),
-        .r_axis = FlipAxisY(right_axis),
-    };
-}
-
-TasAnalog Tas::FlipAxisY(TasAnalog old) {
-    return {
-        .x = old.x,
-        .y = -old.y,
+        .l_axis = left_axis,
+        .r_axis = right_axis,
     };
 }
 
@@ -219,6 +212,7 @@ void Tas::UpdateThread() {
         }
     } else {
         is_running = Settings::values.tas_loop.GetValue();
+        LoadTasFiles();
         current_command = 0;
         ClearInput();
     }

+ 3 - 8
src/input_common/drivers/tas_input.h

@@ -138,21 +138,16 @@ private:
     void LoadTasFiles();
 
     /** Loads TAS file from the specified player
-     * @param player_index: player number where data is going to be stored
+     * @param player_index: player number to save the script
+     * @param file_index: script number of the file
      */
-    void LoadTasFile(size_t player_index);
+    void LoadTasFile(size_t player_index, size_t file_index);
 
     /** Writes a TAS file from the recorded commands
      * @param file_name: name of the file to be written
      */
     void WriteTasFile(std::u8string file_name);
 
-    /** Inverts the Y axis polarity
-     * @param old: value of the axis
-     * @return new value of the axis
-     */
-    TasAnalog FlipAxisY(TasAnalog old);
-
     /**
      * Parses a string containing the axis values. X and Y have a range from -32767 to 32767
      * @param line: string containing axis values with the following format "x;y"