Browse Source

input_common/tas: Document the main class

german77 5 years ago
parent
commit
33a1d790e8

+ 4 - 7
src/common/settings.h

@@ -512,17 +512,14 @@ struct Values {
                                             "motion_device"};
     BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
 
-    BasicSetting<bool> pause_tas_on_load { false, "pause_tas_on_load" };
-    BasicSetting<bool> tas_enable{ false, "tas_enable" };
-    BasicSetting<bool> tas_loop{ false, "tas_loop" };
-    BasicSetting<bool> tas_swap_controllers{ false, "tas_swap_controllers" };
-    BasicSetting<bool> is_cpu_boosted{ false,  "is_cpu_boosted" };
-" };
+    BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
+    BasicSetting<bool> tas_enable{false, "tas_enable"};
+    BasicSetting<bool> tas_loop{false, "tas_loop"};
+    BasicSetting<bool> tas_swap_controllers{true, "tas_swap_controllers"};
 
     BasicSetting<bool> mouse_panning{false, "mouse_panning"};
     BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
     BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
-
     std::string mouse_device;
     MouseButtonsRaw mouse_buttons;
 

+ 2 - 1
src/input_common/tas/tas_input.cpp

@@ -14,6 +14,7 @@
 
 namespace TasInput {
 
+// Supported keywords and buttons from a TAS file
 constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_button = {
     std::pair{"KEY_A", TasButton::BUTTON_A},
     {"KEY_B", TasButton::BUTTON_B},
@@ -214,7 +215,7 @@ void Tas::UpdateThread() {
                 }
             }
         } else {
-            is_running = Settings::values.tas_loop;
+            is_running = Settings::values.tas_loop.GetValue();
             current_command = 0;
             tas_data.fill({});
             if (!is_running) {

+ 108 - 0
src/input_common/tas/tas_input.h

@@ -11,6 +11,38 @@
 #include "core/frontend/input.h"
 #include "input_common/main.h"
 
+/*
+To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
+Emulation -> Configure TAS. The file itself has normal text format and has to be called
+script0-1.txt for controller 1, script0-2.txt for controller 2 and so forth (with max. 8 players).
+
+A script file has the same format as TAS-nx uses, so final files will look like this:
+
+1 KEY_B 0;0 0;0
+6 KEY_ZL 0;0 0;0
+41 KEY_ZL;KEY_Y 0;0 0;0
+43 KEY_X;KEY_A 32767;0 0;0
+44 KEY_A 32767;0 0;0
+45 KEY_A 32767;0 0;0
+46 KEY_A 32767;0 0;0
+47 KEY_A 32767;0 0;0
+
+After placing the file at the correct location, it can be read into Yuzu with the (default) hotkey
+CTRL+F6 (refresh). In the bottom left corner, it will display the amount of frames the script file
+has. Playback can be started or stopped using CTRL+F5.
+
+However, for playback to actually work, the correct input device has to be selected: In the Controls
+menu, select TAS from the device list for the controller that the script should be played on.
+
+Recording a new script file is really simple: Just make sure that the proper device (not TAS) is
+connected on P1, and press CTRL+F7 to start recording. When done, just press the same keystroke
+again (CTRL+F7). The new script will be saved at the location previously selected, as the filename
+record.txt.
+
+For debugging purposes, the common controller debugger can be used (View -> Debugging -> Controller
+P1).
+*/
+
 namespace TasInput {
 
 constexpr size_t PLAYER_NUMBER = 8;
@@ -64,12 +96,26 @@ public:
     Tas();
     ~Tas();
 
+    // Changes the input status that will be stored in each frame
     void RecordInput(u32 buttons, const std::array<std::pair<float, float>, 2>& axes);
+
+    // Main loop that records or executes input
     void UpdateThread();
 
+    //  Sets the flag to start or stop the TAS command excecution and swaps controllers profiles
     void StartStop();
+
+    // Sets the flag to reload the file and start from the begining in the next update
     void Reset();
+
+    /**
+     * Sets the flag to enable or disable recording of inputs
+     * @return Returns true if the current recording status is enabled
+     */
     bool Record();
+
+    // Saves contents of record_commands on a file if overwrite is enabled player 1 will be
+    // overwritten with the recorded commands
     void SaveRecording(bool overwrite_file);
 
     /**
@@ -80,7 +126,11 @@ public:
      * Total length of script file currently loaded or amount of frames (so far) for Recording
      */
     std::tuple<TasState, size_t, size_t> GetStatus() const;
+
+    // Retuns an array of the default button mappings
     InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
+
+    // Retuns an array of the default analog mappings
     InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
     [[nodiscard]] const TasData& GetTasState(std::size_t pad) const;
 
@@ -90,23 +140,81 @@ private:
         TasAnalog l_axis{};
         TasAnalog r_axis{};
     };
+
+    // Loads TAS files from all players
     void LoadTasFiles();
+
+    // Loads TAS file from the specified player
     void LoadTasFile(size_t player_index);
+
+    // Writes a TAS file from the recorded commands
     void WriteTasFile(std::u8string file_name);
+
+    /**
+     * Parses a string containing the axis values with the following format "x;y"
+     * X and Y have a range from -32767 to 32767
+     * @return Returns a TAS analog object with axis values with range from -1.0 to 1.0
+     */
     TasAnalog ReadCommandAxis(const std::string& line) const;
+
+    /**
+     * Parses a string containing the button values with the following format "a;b;c;d..."
+     * Each button is represented by it's text format specified in text_to_tas_button array
+     * @return Returns a u32 with each bit representing the status of a button
+     */
     u32 ReadCommandButtons(const std::string& line) const;
+
+    /**
+     * Converts an u32 containing the button status into the text equivalent
+     * @return Returns a string with the name of the buttons to be written to the file
+     */
     std::string WriteCommandButtons(u32 data) const;
+
+    /**
+     * Converts an TAS analog object containing the axis status into the text equivalent
+     * @return Returns a string with the value of the axis to be written to the file
+     */
     std::string WriteCommandAxis(TasAnalog data) const;
 
+    // Inverts the Y axis polarity
     std::pair<float, float> FlipAxisY(std::pair<float, float> old);
 
+    /**
+     * Converts an u32 containing the button status into the text equivalent
+     * @return Returns a string with the name of the buttons to be printed on console
+     */
     std::string DebugButtons(u32 buttons) const;
+
+    /**
+     * Converts an TAS analog object containing the axis status into the text equivalent
+     * @return Returns a string with the value of the axis to be printed on console
+     */
     std::string DebugJoystick(float x, float y) const;
+
+    /**
+     * Converts the given TAS status into the text equivalent
+     * @return Returns a string with the value of the TAS status to be printed on console
+     */
     std::string DebugInput(const TasData& data) const;
+
+    /**
+     * Converts the given TAS status of multiple players into the text equivalent
+     * @return Returns a string with the value of the status of all TAS players to be printed on
+     * console
+     */
     std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const;
+
+    /**
+     * Converts an u32 containing the button status into the text equivalent
+     * @return Returns a string with the name of the buttons
+     */
     std::string ButtonsToString(u32 button) const;
 
+    // Stores current controller configuration and sets a TAS controller for every active controller
+    // to the current config
     void SwapToTasController();
+
+    // Sets the stored controller configuration to the current config
     void SwapToStoredController();
 
     size_t script_length{0};

+ 2 - 2
src/input_common/tas/tas_poller.h

@@ -11,7 +11,7 @@
 namespace InputCommon {
 
 /**
- * A button device factory representing a mouse. It receives mouse events and forward them
+ * A button device factory representing a tas bot. It receives tas events and forward them
  * to all button devices it created.
  */
 class TasButtonFactory final : public Input::Factory<Input::ButtonDevice> {
@@ -29,7 +29,7 @@ private:
     std::shared_ptr<TasInput::Tas> tas_input;
 };
 
-/// An analog device factory that creates analog devices from mouse
+/// An analog device factory that creates analog devices from tas
 class TasAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
 public:
     explicit TasAnalogFactory(std::shared_ptr<TasInput::Tas> tas_input_);

+ 18 - 21
src/yuzu/configuration/config.cpp

@@ -567,8 +567,10 @@ void Config::ReadControlValues() {
     Settings::values.mouse_panning = false;
     ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
 
-    ReadBasicSetting(Settings::values.tas_enable = false);
-    ReadBasicSetting(Settings::values.tas_reset = false);
+    ReadBasicSetting(Settings::values.tas_enable);
+    ReadBasicSetting(Settings::values.tas_loop);
+    ReadBasicSetting(Settings::values.tas_swap_controllers);
+    ReadBasicSetting(Settings::values.pause_tas_on_load);
 
     ReadGlobalSetting(Settings::values.use_docked_mode);
 
@@ -667,20 +669,16 @@ void Config::ReadDataStorageValues() {
                     QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)))
             .toString()
             .toStdString());
-    FS::SetYuzuPath(
-        FS::YuzuPath::TASFile,
-        qt_config
-        ->value(QStringLiteral("tas_path"),
-            QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASFile)))
-        .toString()
-        .toStdString());
-
-    ReadBasicSetting(Settings::values.pauseTasOnLoad);
+    FS::SetYuzuPath(FS::YuzuPath::TASDir,
+                    qt_config
+                        ->value(QStringLiteral("tas_directory"),
+                                QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)))
+                        .toString()
+                        .toStdString());
 
     ReadBasicSetting(Settings::values.gamecard_inserted);
     ReadBasicSetting(Settings::values.gamecard_current_game);
     ReadBasicSetting(Settings::values.gamecard_path);
-  
 
     qt_config->endGroup();
 }
@@ -1205,11 +1203,11 @@ void Config::SaveControlValues() {
     WriteBasicSetting(Settings::values.emulate_analog_keyboard);
     WriteBasicSetting(Settings::values.mouse_panning_sensitivity);
 
-    WriteSetting(QStringLiteral("enable_tas"), Settings::values.tas_enable, false);
-    WriteSetting(QStringLiteral("loop_tas"), Settings::values.tas_loop, false);
-    WriteSetting(QStringLiteral("swap_tas_controllers"), Settings::values.tas_swap_controllers,
-                 true);
-    WriteSetting(QStringLiteral("tas_pause_on_load"), Settings::values.pause_tas_on_load, true);
+    WriteBasicSetting(Settings::values.tas_enable);
+    WriteBasicSetting(Settings::values.tas_loop);
+    WriteBasicSetting(Settings::values.tas_swap_controllers);
+    WriteBasicSetting(Settings::values.pause_tas_on_load);
+
     qt_config->endGroup();
 }
 
@@ -1237,10 +1235,9 @@ void Config::SaveDataStorageValues() {
     WriteSetting(QStringLiteral("dump_directory"),
                  QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)),
                  QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
-    WriteSetting(QStringLiteral("tas_path"),
-        QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASFile)),
-        QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASFile)));
-    WriteSetting(QStringLiteral("tas_pause_on_load"), Settings::values.pauseTasOnLoad, true);
+    WriteSetting(QStringLiteral("tas_directory"),
+                 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)),
+                 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
 
     WriteBasicSetting(Settings::values.gamecard_inserted);
     WriteBasicSetting(Settings::values.gamecard_current_game);

+ 0 - 1
src/yuzu/configuration/configure_filesystem.cpp

@@ -52,7 +52,6 @@ void ConfigureFilesystem::setConfiguration() {
 
     ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted.GetValue());
     ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game.GetValue());
-    ui->tas_pause_on_load->setChecked(Settings::values.pauseTasOnLoad);
     ui->dump_exefs->setChecked(Settings::values.dump_exefs.GetValue());
     ui->dump_nso->setChecked(Settings::values.dump_nso.GetValue());
 

+ 11 - 11
src/yuzu/configuration/configure_input_player_widget.cpp

@@ -222,23 +222,23 @@ void PlayerControlPreview::UpdateInput() {
 
     if (input_changed) {
         update();
-        ControllerInput input{
-            .axis_values =
-                {std::pair<float, float>{axis_values[Settings::NativeAnalog::LStick].value.x(),
-                                         axis_values[Settings::NativeAnalog::LStick].value.y()},
-                 std::pair<float, float>{axis_values[Settings::NativeAnalog::RStick].value.x(),
-                                         axis_values[Settings::NativeAnalog::RStick].value.y()}},
-            .button_values = button_values,
-            .changed = true,
-        };
-
         if (controller_callback.input != nullptr) {
+            ControllerInput input{
+                .axis_values = {std::pair<float, float>{
+                                    axis_values[Settings::NativeAnalog::LStick].value.x(),
+                                    axis_values[Settings::NativeAnalog::LStick].value.y()},
+                                std::pair<float, float>{
+                                    axis_values[Settings::NativeAnalog::RStick].value.x(),
+                                    axis_values[Settings::NativeAnalog::RStick].value.y()}},
+                .button_values = button_values,
+                .changed = true,
+            };
             controller_callback.input(std::move(input));
         }
     }
 
     if (controller_callback.update != nullptr) {
-        controller_callback.update(std::move(true));
+        controller_callback.update(true);
     }
 
     if (mapping_active) {

+ 8 - 8
src/yuzu/configuration/configure_tas.cpp

@@ -30,18 +30,18 @@ ConfigureTasDialog::~ConfigureTasDialog() = default;
 void ConfigureTasDialog::LoadConfiguration() {
     ui->tas_path_edit->setText(
         QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir)));
-    ui->tas_enable->setChecked(Settings::values.tas_enable);
-    ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers);
-    ui->tas_loop_script->setChecked(Settings::values.tas_loop);
-    ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load);
+    ui->tas_enable->setChecked(Settings::values.tas_enable.GetValue());
+    ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers.GetValue());
+    ui->tas_loop_script->setChecked(Settings::values.tas_loop.GetValue());
+    ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load.GetValue());
 }
 
 void ConfigureTasDialog::ApplyConfiguration() {
     Common::FS::SetYuzuPath(Common::FS::YuzuPath::TASDir, ui->tas_path_edit->text().toStdString());
-    Settings::values.tas_enable = ui->tas_enable->isChecked();
-    Settings::values.tas_swap_controllers = ui->tas_control_swap->isChecked();
-    Settings::values.tas_loop = ui->tas_loop_script->isChecked();
-    Settings::values.pause_tas_on_load = ui->tas_pause_on_load->isChecked();
+    Settings::values.tas_enable.SetValue(ui->tas_enable->isChecked());
+    Settings::values.tas_swap_controllers.SetValue(ui->tas_control_swap->isChecked());
+    Settings::values.tas_loop.SetValue(ui->tas_loop_script->isChecked());
+    Settings::values.pause_tas_on_load.SetValue(ui->tas_pause_on_load->isChecked());
 }
 
 void ConfigureTasDialog::SetDirectory(DirectoryTarget target, QLineEdit* edit) {