diff options
| -rw-r--r-- | src/common/fs/path_util.h | 2 | ||||
| -rw-r--r-- | src/input_common/main.h | 20 | ||||
| -rw-r--r-- | src/input_common/tas/tas_input.cpp | 63 | ||||
| -rw-r--r-- | src/input_common/tas/tas_input.h | 9 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player_widget.cpp | 34 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_tas.ui | 3 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 2 |
8 files changed, 99 insertions, 39 deletions
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h index 52e4670e2..0a9e3a145 100644 --- a/src/common/fs/path_util.h +++ b/src/common/fs/path_util.h | |||
| @@ -23,7 +23,7 @@ enum class YuzuPath { | |||
| 23 | ScreenshotsDir, // Where yuzu screenshots are stored. | 23 | ScreenshotsDir, // Where yuzu screenshots are stored. |
| 24 | SDMCDir, // Where the emulated SDMC is stored. | 24 | SDMCDir, // Where the emulated SDMC is stored. |
| 25 | ShaderDir, // Where shaders are stored. | 25 | ShaderDir, // Where shaders are stored. |
| 26 | TASDir, // Where the current script file is stored. | 26 | TASDir, // Where TAS scripts are stored. |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | /** | 29 | /** |
diff --git a/src/input_common/main.h b/src/input_common/main.h index 1d06fc5f5..6390d3f09 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h | |||
| @@ -155,28 +155,28 @@ public: | |||
| 155 | /// Retrieves the underlying udp touch handler. | 155 | /// Retrieves the underlying udp touch handler. |
| 156 | [[nodiscard]] const UDPTouchFactory* GetUDPTouch() const; | 156 | [[nodiscard]] const UDPTouchFactory* GetUDPTouch() const; |
| 157 | 157 | ||
| 158 | /// Retrieves the underlying GameCube button handler. | 158 | /// Retrieves the underlying mouse button handler. |
| 159 | [[nodiscard]] MouseButtonFactory* GetMouseButtons(); | 159 | [[nodiscard]] MouseButtonFactory* GetMouseButtons(); |
| 160 | 160 | ||
| 161 | /// Retrieves the underlying GameCube button handler. | 161 | /// Retrieves the underlying mouse button handler. |
| 162 | [[nodiscard]] const MouseButtonFactory* GetMouseButtons() const; | 162 | [[nodiscard]] const MouseButtonFactory* GetMouseButtons() const; |
| 163 | 163 | ||
| 164 | /// Retrieves the underlying udp touch handler. | 164 | /// Retrieves the underlying mouse analog handler. |
| 165 | [[nodiscard]] MouseAnalogFactory* GetMouseAnalogs(); | 165 | [[nodiscard]] MouseAnalogFactory* GetMouseAnalogs(); |
| 166 | 166 | ||
| 167 | /// Retrieves the underlying udp touch handler. | 167 | /// Retrieves the underlying mouse analog handler. |
| 168 | [[nodiscard]] const MouseAnalogFactory* GetMouseAnalogs() const; | 168 | [[nodiscard]] const MouseAnalogFactory* GetMouseAnalogs() const; |
| 169 | 169 | ||
| 170 | /// Retrieves the underlying udp motion handler. | 170 | /// Retrieves the underlying mouse motion handler. |
| 171 | [[nodiscard]] MouseMotionFactory* GetMouseMotions(); | 171 | [[nodiscard]] MouseMotionFactory* GetMouseMotions(); |
| 172 | 172 | ||
| 173 | /// Retrieves the underlying udp motion handler. | 173 | /// Retrieves the underlying mouse motion handler. |
| 174 | [[nodiscard]] const MouseMotionFactory* GetMouseMotions() const; | 174 | [[nodiscard]] const MouseMotionFactory* GetMouseMotions() const; |
| 175 | 175 | ||
| 176 | /// Retrieves the underlying udp touch handler. | 176 | /// Retrieves the underlying mouse touch handler. |
| 177 | [[nodiscard]] MouseTouchFactory* GetMouseTouch(); | 177 | [[nodiscard]] MouseTouchFactory* GetMouseTouch(); |
| 178 | 178 | ||
| 179 | /// Retrieves the underlying udp touch handler. | 179 | /// Retrieves the underlying mouse touch handler. |
| 180 | [[nodiscard]] const MouseTouchFactory* GetMouseTouch() const; | 180 | [[nodiscard]] const MouseTouchFactory* GetMouseTouch() const; |
| 181 | 181 | ||
| 182 | /// Retrieves the underlying tas button handler. | 182 | /// Retrieves the underlying tas button handler. |
| @@ -185,10 +185,10 @@ public: | |||
| 185 | /// Retrieves the underlying tas button handler. | 185 | /// Retrieves the underlying tas button handler. |
| 186 | [[nodiscard]] const TasButtonFactory* GetTasButtons() const; | 186 | [[nodiscard]] const TasButtonFactory* GetTasButtons() const; |
| 187 | 187 | ||
| 188 | /// Retrieves the underlying tas touch handler. | 188 | /// Retrieves the underlying tas analogs handler. |
| 189 | [[nodiscard]] TasAnalogFactory* GetTasAnalogs(); | 189 | [[nodiscard]] TasAnalogFactory* GetTasAnalogs(); |
| 190 | 190 | ||
| 191 | /// Retrieves the underlying tas touch handler. | 191 | /// Retrieves the underlying tas analogs handler. |
| 192 | [[nodiscard]] const TasAnalogFactory* GetTasAnalogs() const; | 192 | [[nodiscard]] const TasAnalogFactory* GetTasAnalogs() const; |
| 193 | 193 | ||
| 194 | /// Reloads the input devices | 194 | /// Reloads the input devices |
diff --git a/src/input_common/tas/tas_input.cpp b/src/input_common/tas/tas_input.cpp index eb3327520..aceb13adc 100644 --- a/src/input_common/tas/tas_input.cpp +++ b/src/input_common/tas/tas_input.cpp | |||
| @@ -61,8 +61,8 @@ void Tas::LoadTasFile(size_t player_index) { | |||
| 61 | commands[player_index].clear(); | 61 | commands[player_index].clear(); |
| 62 | } | 62 | } |
| 63 | std::string file = | 63 | std::string file = |
| 64 | Common::FS::ReadStringFromFile(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir) + | 64 | Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / |
| 65 | "script0-" + std::to_string(player_index + 1) + ".txt", | 65 | fmt::format("script0-{}.txt", player_index + 1), |
| 66 | Common::FS::FileType::BinaryFile); | 66 | Common::FS::FileType::BinaryFile); |
| 67 | std::stringstream command_line(file); | 67 | std::stringstream command_line(file); |
| 68 | std::string line; | 68 | std::string line; |
| @@ -102,7 +102,7 @@ void Tas::LoadTasFile(size_t player_index) { | |||
| 102 | LOG_INFO(Input, "TAS file loaded! {} frames", frame_no); | 102 | LOG_INFO(Input, "TAS file loaded! {} frames", frame_no); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void Tas::WriteTasFile(std::string file_name) { | 105 | void Tas::WriteTasFile(std::u8string file_name) { |
| 106 | std::string output_text; | 106 | std::string output_text; |
| 107 | for (size_t frame = 0; frame < record_commands.size(); frame++) { | 107 | for (size_t frame = 0; frame < record_commands.size(); frame++) { |
| 108 | if (!output_text.empty()) { | 108 | if (!output_text.empty()) { |
| @@ -112,8 +112,8 @@ void Tas::WriteTasFile(std::string file_name) { | |||
| 112 | output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " + | 112 | output_text += std::to_string(frame) + " " + WriteCommandButtons(line.buttons) + " " + |
| 113 | WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis); | 113 | WriteCommandAxis(line.l_axis) + " " + WriteCommandAxis(line.r_axis); |
| 114 | } | 114 | } |
| 115 | const size_t bytes_written = Common::FS::WriteStringToFile( | 115 | const auto bytes_written = Common::FS::WriteStringToFile( |
| 116 | Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir) + file_name, | 116 | Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name, |
| 117 | Common::FS::FileType::TextFile, output_text); | 117 | Common::FS::FileType::TextFile, output_text); |
| 118 | if (bytes_written == output_text.size()) { | 118 | if (bytes_written == output_text.size()) { |
| 119 | LOG_INFO(Input, "TAS file written to file!"); | 119 | LOG_INFO(Input, "TAS file written to file!"); |
| @@ -217,6 +217,9 @@ void Tas::UpdateThread() { | |||
| 217 | is_running = Settings::values.tas_loop; | 217 | is_running = Settings::values.tas_loop; |
| 218 | current_command = 0; | 218 | current_command = 0; |
| 219 | tas_data.fill({}); | 219 | tas_data.fill({}); |
| 220 | if (!is_running) { | ||
| 221 | SwapToStoredController(); | ||
| 222 | } | ||
| 220 | } | 223 | } |
| 221 | } else { | 224 | } else { |
| 222 | tas_data.fill({}); | 225 | tas_data.fill({}); |
| @@ -290,6 +293,52 @@ std::string Tas::WriteCommandButtons(u32 data) const { | |||
| 290 | 293 | ||
| 291 | void Tas::StartStop() { | 294 | void Tas::StartStop() { |
| 292 | is_running = !is_running; | 295 | is_running = !is_running; |
| 296 | if (is_running) { | ||
| 297 | SwapToTasController(); | ||
| 298 | } else { | ||
| 299 | SwapToStoredController(); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | void Tas::SwapToTasController() { | ||
| 304 | if (!Settings::values.tas_swap_controllers) { | ||
| 305 | return; | ||
| 306 | } | ||
| 307 | auto& players = Settings::values.players.GetValue(); | ||
| 308 | for (std::size_t index = 0; index < players.size(); index++) { | ||
| 309 | auto& player = players[index]; | ||
| 310 | player_mappings[index] = player; | ||
| 311 | |||
| 312 | // Only swap active controllers | ||
| 313 | if (!player.connected) { | ||
| 314 | continue; | ||
| 315 | } | ||
| 316 | |||
| 317 | auto tas_param = Common::ParamPackage{{"pad", static_cast<u8>(index)}}; | ||
| 318 | auto button_mapping = GetButtonMappingForDevice(tas_param); | ||
| 319 | auto analog_mapping = GetAnalogMappingForDevice(tas_param); | ||
| 320 | auto& buttons = player.buttons; | ||
| 321 | auto& analogs = player.analogs; | ||
| 322 | |||
| 323 | for (std::size_t i = 0; i < buttons.size(); ++i) { | ||
| 324 | buttons[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)].Serialize(); | ||
| 325 | } | ||
| 326 | for (std::size_t i = 0; i < analogs.size(); ++i) { | ||
| 327 | analogs[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)].Serialize(); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | Settings::values.is_device_reload_pending.store(true); | ||
| 331 | } | ||
| 332 | |||
| 333 | void Tas::SwapToStoredController() { | ||
| 334 | if (!Settings::values.tas_swap_controllers) { | ||
| 335 | return; | ||
| 336 | } | ||
| 337 | auto& players = Settings::values.players.GetValue(); | ||
| 338 | for (std::size_t index = 0; index < players.size(); index++) { | ||
| 339 | players[index] = player_mappings[index]; | ||
| 340 | } | ||
| 341 | Settings::values.is_device_reload_pending.store(true); | ||
| 293 | } | 342 | } |
| 294 | 343 | ||
| 295 | void Tas::Reset() { | 344 | void Tas::Reset() { |
| @@ -308,9 +357,9 @@ void Tas::SaveRecording(bool overwrite_file) { | |||
| 308 | if (record_commands.empty()) { | 357 | if (record_commands.empty()) { |
| 309 | return; | 358 | return; |
| 310 | } | 359 | } |
| 311 | WriteTasFile("record.txt"); | 360 | WriteTasFile(u8"record.txt"); |
| 312 | if (overwrite_file) { | 361 | if (overwrite_file) { |
| 313 | WriteTasFile("script0-1.txt"); | 362 | WriteTasFile(u8"script0-1.txt"); |
| 314 | } | 363 | } |
| 315 | needs_reset = true; | 364 | needs_reset = true; |
| 316 | record_commands.clear(); | 365 | record_commands.clear(); |
diff --git a/src/input_common/tas/tas_input.h b/src/input_common/tas/tas_input.h index e0462e858..e1f351251 100644 --- a/src/input_common/tas/tas_input.h +++ b/src/input_common/tas/tas_input.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/settings_input.h" | ||
| 10 | #include "core/frontend/input.h" | 11 | #include "core/frontend/input.h" |
| 11 | #include "input_common/main.h" | 12 | #include "input_common/main.h" |
| 12 | 13 | ||
| @@ -91,7 +92,7 @@ private: | |||
| 91 | }; | 92 | }; |
| 92 | void LoadTasFiles(); | 93 | void LoadTasFiles(); |
| 93 | void LoadTasFile(size_t player_index); | 94 | void LoadTasFile(size_t player_index); |
| 94 | void WriteTasFile(std::string file_name); | 95 | void WriteTasFile(std::u8string file_name); |
| 95 | TasAnalog ReadCommandAxis(const std::string& line) const; | 96 | TasAnalog ReadCommandAxis(const std::string& line) const; |
| 96 | u32 ReadCommandButtons(const std::string& line) const; | 97 | u32 ReadCommandButtons(const std::string& line) const; |
| 97 | std::string WriteCommandButtons(u32 data) const; | 98 | std::string WriteCommandButtons(u32 data) const; |
| @@ -105,6 +106,9 @@ private: | |||
| 105 | std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const; | 106 | std::string DebugInputs(const std::array<TasData, PLAYER_NUMBER>& arr) const; |
| 106 | std::string ButtonsToString(u32 button) const; | 107 | std::string ButtonsToString(u32 button) const; |
| 107 | 108 | ||
| 109 | void SwapToTasController(); | ||
| 110 | void SwapToStoredController(); | ||
| 111 | |||
| 108 | size_t script_length{0}; | 112 | size_t script_length{0}; |
| 109 | std::array<TasData, PLAYER_NUMBER> tas_data; | 113 | std::array<TasData, PLAYER_NUMBER> tas_data; |
| 110 | bool is_recording{false}; | 114 | bool is_recording{false}; |
| @@ -114,5 +118,8 @@ private: | |||
| 114 | std::vector<TASCommand> record_commands{}; | 118 | std::vector<TASCommand> record_commands{}; |
| 115 | size_t current_command{0}; | 119 | size_t current_command{0}; |
| 116 | TASCommand last_input{}; // only used for recording | 120 | TASCommand last_input{}; // only used for recording |
| 121 | |||
| 122 | // Old settings for swapping controllers | ||
| 123 | std::array<Settings::PlayerInput, 10> player_mappings; | ||
| 117 | }; | 124 | }; |
| 118 | } // namespace TasInput | 125 | } // namespace TasInput |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 99e318a8f..a0dfa06df 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -1205,6 +1205,11 @@ void Config::SaveControlValues() { | |||
| 1205 | WriteBasicSetting(Settings::values.emulate_analog_keyboard); | 1205 | WriteBasicSetting(Settings::values.emulate_analog_keyboard); |
| 1206 | WriteBasicSetting(Settings::values.mouse_panning_sensitivity); | 1206 | WriteBasicSetting(Settings::values.mouse_panning_sensitivity); |
| 1207 | 1207 | ||
| 1208 | WriteSetting(QStringLiteral("enable_tas"), Settings::values.tas_enable, false); | ||
| 1209 | WriteSetting(QStringLiteral("loop_tas"), Settings::values.tas_loop, false); | ||
| 1210 | WriteSetting(QStringLiteral("swap_tas_controllers"), Settings::values.tas_swap_controllers, | ||
| 1211 | true); | ||
| 1212 | WriteSetting(QStringLiteral("tas_pause_on_load"), Settings::values.pause_tas_on_load, true); | ||
| 1208 | qt_config->endGroup(); | 1213 | qt_config->endGroup(); |
| 1209 | } | 1214 | } |
| 1210 | 1215 | ||
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index b905fc73d..ba3720c03 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp | |||
| @@ -175,10 +175,7 @@ void PlayerControlPreview::ResetInputs() { | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | void PlayerControlPreview::UpdateInput() { | 177 | void PlayerControlPreview::UpdateInput() { |
| 178 | if (controller_callback.update != nullptr) { | 178 | if (!is_enabled && !mapping_active && !Settings::values.tas_enable) { |
| 179 | controller_callback.update(std::move(true)); | ||
| 180 | } | ||
| 181 | if (!is_enabled && !mapping_active) { | ||
| 182 | return; | 179 | return; |
| 183 | } | 180 | } |
| 184 | bool input_changed = false; | 181 | bool input_changed = false; |
| @@ -223,20 +220,25 @@ void PlayerControlPreview::UpdateInput() { | |||
| 223 | } | 220 | } |
| 224 | } | 221 | } |
| 225 | 222 | ||
| 226 | ControllerInput input{}; | ||
| 227 | if (input_changed) { | 223 | if (input_changed) { |
| 228 | update(); | 224 | update(); |
| 229 | input.changed = true; | 225 | ControllerInput input{ |
| 230 | } | 226 | .axis_values = |
| 231 | input.axis_values[Settings::NativeAnalog::LStick] = { | 227 | {std::pair<float, float>{axis_values[Settings::NativeAnalog::LStick].value.x(), |
| 232 | axis_values[Settings::NativeAnalog::LStick].value.x(), | 228 | axis_values[Settings::NativeAnalog::LStick].value.y()}, |
| 233 | axis_values[Settings::NativeAnalog::LStick].value.y()}; | 229 | std::pair<float, float>{axis_values[Settings::NativeAnalog::RStick].value.x(), |
| 234 | input.axis_values[Settings::NativeAnalog::RStick] = { | 230 | axis_values[Settings::NativeAnalog::RStick].value.y()}}, |
| 235 | axis_values[Settings::NativeAnalog::RStick].value.x(), | 231 | .button_values = button_values, |
| 236 | axis_values[Settings::NativeAnalog::RStick].value.y()}; | 232 | .changed = true, |
| 237 | input.button_values = button_values; | 233 | }; |
| 238 | if (controller_callback.input != nullptr) { | 234 | |
| 239 | controller_callback.input(std::move(input)); | 235 | if (controller_callback.input != nullptr) { |
| 236 | controller_callback.input(std::move(input)); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | if (controller_callback.update != nullptr) { | ||
| 241 | controller_callback.update(std::move(true)); | ||
| 240 | } | 242 | } |
| 241 | 243 | ||
| 242 | if (mapping_active) { | 244 | if (mapping_active) { |
diff --git a/src/yuzu/configuration/configure_tas.ui b/src/yuzu/configuration/configure_tas.ui index 906e073ff..445904d8f 100644 --- a/src/yuzu/configuration/configure_tas.ui +++ b/src/yuzu/configuration/configure_tas.ui | |||
| @@ -31,9 +31,6 @@ | |||
| 31 | </item> | 31 | </item> |
| 32 | <item row="1" column="0" colspan="4"> | 32 | <item row="1" column="0" colspan="4"> |
| 33 | <widget class="QCheckBox" name="tas_control_swap"> | 33 | <widget class="QCheckBox" name="tas_control_swap"> |
| 34 | <property name="enabled"> | ||
| 35 | <bool>false</bool> | ||
| 36 | </property> | ||
| 37 | <property name="text"> | 34 | <property name="text"> |
| 38 | <string>Automatic controller profile swapping</string> | 35 | <string>Automatic controller profile swapping</string> |
| 39 | </property> | 36 | </property> |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 560de89af..7d12fcca7 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2921,7 +2921,7 @@ QString GMainWindow::GetTasStateDescription() const { | |||
| 2921 | case TasInput::TasState::Stopped: | 2921 | case TasInput::TasState::Stopped: |
| 2922 | return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames); | 2922 | return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames); |
| 2923 | default: | 2923 | default: |
| 2924 | return tr("INVALID TAS STATE"); | 2924 | return tr("TAS State: Invalid"); |
| 2925 | } | 2925 | } |
| 2926 | } | 2926 | } |
| 2927 | 2927 | ||