summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/yuzu/bootmanager.cpp9
-rw-r--r--src/yuzu/bootmanager.h6
-rw-r--r--src/yuzu/main.cpp99
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/main.ui90
5 files changed, 152 insertions, 57 deletions
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 822ba1a34..fd0a130a3 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -303,6 +303,7 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
303 connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram, 303 connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
304 Qt::QueuedConnection); 304 Qt::QueuedConnection);
305 connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection); 305 connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
306 connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &GMainWindow::OnTasStateChanged);
306} 307}
307 308
308void GRenderWindow::ExecuteProgram(std::size_t program_index) { 309void GRenderWindow::ExecuteProgram(std::size_t program_index) {
@@ -319,10 +320,18 @@ GRenderWindow::~GRenderWindow() {
319 320
320void GRenderWindow::OnFrameDisplayed() { 321void GRenderWindow::OnFrameDisplayed() {
321 input_subsystem->GetTas()->UpdateThread(); 322 input_subsystem->GetTas()->UpdateThread();
323 const TasInput::TasState new_tas_state = std::get<0>(input_subsystem->GetTas()->GetStatus());
324
322 if (!first_frame) { 325 if (!first_frame) {
326 last_tas_state = new_tas_state;
323 first_frame = true; 327 first_frame = true;
324 emit FirstFrameDisplayed(); 328 emit FirstFrameDisplayed();
325 } 329 }
330
331 if (new_tas_state != last_tas_state) {
332 last_tas_state = new_tas_state;
333 emit TasPlaybackStateChanged();
334 }
326} 335}
327 336
328bool GRenderWindow::IsShown() const { 337bool GRenderWindow::IsShown() const {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 40fd4a9d6..061e3605f 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -41,6 +41,10 @@ enum class LoadCallbackStage;
41class RendererBase; 41class RendererBase;
42} // namespace VideoCore 42} // namespace VideoCore
43 43
44namespace TasInput {
45enum class TasState;
46}
47
44class EmuThread final : public QThread { 48class EmuThread final : public QThread {
45 Q_OBJECT 49 Q_OBJECT
46 50
@@ -203,6 +207,7 @@ signals:
203 void ExecuteProgramSignal(std::size_t program_index); 207 void ExecuteProgramSignal(std::size_t program_index);
204 void ExitSignal(); 208 void ExitSignal();
205 void MouseActivity(); 209 void MouseActivity();
210 void TasPlaybackStateChanged();
206 211
207private: 212private:
208 void TouchBeginEvent(const QTouchEvent* event); 213 void TouchBeginEvent(const QTouchEvent* event);
@@ -236,6 +241,7 @@ private:
236 QWidget* child_widget = nullptr; 241 QWidget* child_widget = nullptr;
237 242
238 bool first_frame = false; 243 bool first_frame = false;
244 TasInput::TasState last_tas_state;
239 245
240 std::array<std::size_t, 16> touch_ids{}; 246 std::array<std::size_t, 16> touch_ids{};
241 247
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index c4c76b094..5058c3e4e 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -965,6 +965,9 @@ void GMainWindow::InitializeHotkeys() {
965 const QString toggle_status_bar = QStringLiteral("Toggle Status Bar"); 965 const QString toggle_status_bar = QStringLiteral("Toggle Status Bar");
966 const QString fullscreen = QStringLiteral("Fullscreen"); 966 const QString fullscreen = QStringLiteral("Fullscreen");
967 const QString capture_screenshot = QStringLiteral("Capture Screenshot"); 967 const QString capture_screenshot = QStringLiteral("Capture Screenshot");
968 const QString tas_start_stop = QStringLiteral("TAS Start/Stop");
969 const QString tas_record = QStringLiteral("TAS Record");
970 const QString tas_reset = QStringLiteral("TAS Reset");
968 971
969 ui->action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file)); 972 ui->action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file));
970 ui->action_Load_File->setShortcutContext( 973 ui->action_Load_File->setShortcutContext(
@@ -1005,6 +1008,18 @@ void GMainWindow::InitializeHotkeys() {
1005 ui->action_Fullscreen->setShortcutContext( 1008 ui->action_Fullscreen->setShortcutContext(
1006 hotkey_registry.GetShortcutContext(main_window, fullscreen)); 1009 hotkey_registry.GetShortcutContext(main_window, fullscreen));
1007 1010
1011 ui->action_TAS_Start->setShortcut(hotkey_registry.GetKeySequence(main_window, tas_start_stop));
1012 ui->action_TAS_Start->setShortcutContext(
1013 hotkey_registry.GetShortcutContext(main_window, tas_start_stop));
1014
1015 ui->action_TAS_Record->setShortcut(hotkey_registry.GetKeySequence(main_window, tas_record));
1016 ui->action_TAS_Record->setShortcutContext(
1017 hotkey_registry.GetShortcutContext(main_window, tas_record));
1018
1019 ui->action_TAS_Reset->setShortcut(hotkey_registry.GetKeySequence(main_window, tas_reset));
1020 ui->action_TAS_Reset->setShortcutContext(
1021 hotkey_registry.GetShortcutContext(main_window, tas_reset));
1022
1008 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this), 1023 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this),
1009 &QShortcut::activated, this, &GMainWindow::OnMenuLoadFile); 1024 &QShortcut::activated, this, &GMainWindow::OnMenuLoadFile);
1010 connect( 1025 connect(
@@ -1095,28 +1110,6 @@ void GMainWindow::InitializeHotkeys() {
1095 render_window->setAttribute(Qt::WA_Hover, true); 1110 render_window->setAttribute(Qt::WA_Hover, true);
1096 } 1111 }
1097 }); 1112 });
1098 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Start/Stop"), this),
1099 &QShortcut::activated, this, [&] {
1100 if (!emulation_running) {
1101 return;
1102 }
1103 input_subsystem->GetTas()->StartStop();
1104 });
1105 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Reset"), this),
1106 &QShortcut::activated, this, [&] { input_subsystem->GetTas()->Reset(); });
1107 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Record"), this),
1108 &QShortcut::activated, this, [&] {
1109 if (!emulation_running) {
1110 return;
1111 }
1112 bool is_recording = input_subsystem->GetTas()->Record();
1113 if (!is_recording) {
1114 const auto res = QMessageBox::question(this, tr("TAS Recording"),
1115 tr("Overwrite file of player 1?"),
1116 QMessageBox::Yes | QMessageBox::No);
1117 input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes);
1118 }
1119 });
1120} 1113}
1121 1114
1122void GMainWindow::SetDefaultUIGeometry() { 1115void GMainWindow::SetDefaultUIGeometry() {
@@ -1236,11 +1229,11 @@ void GMainWindow::ConnectMenuEvents() {
1236 connect(ui->action_Restart, &QAction::triggered, this, 1229 connect(ui->action_Restart, &QAction::triggered, this,
1237 [this] { BootGame(QString(game_path)); }); 1230 [this] { BootGame(QString(game_path)); });
1238 connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); 1231 connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure);
1239 connect(ui->action_Configure_Tas, &QAction::triggered, this, &GMainWindow::OnConfigureTas);
1240 connect(ui->action_Configure_Current_Game, &QAction::triggered, this, 1232 connect(ui->action_Configure_Current_Game, &QAction::triggered, this,
1241 &GMainWindow::OnConfigurePerGame); 1233 &GMainWindow::OnConfigurePerGame);
1242 1234
1243 // View 1235 // View
1236 connect(ui->action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
1244 connect(ui->action_Single_Window_Mode, &QAction::triggered, this, 1237 connect(ui->action_Single_Window_Mode, &QAction::triggered, this,
1245 &GMainWindow::ToggleWindowMode); 1238 &GMainWindow::ToggleWindowMode);
1246 connect(ui->action_Display_Dock_Widget_Headers, &QAction::triggered, this, 1239 connect(ui->action_Display_Dock_Widget_Headers, &QAction::triggered, this,
@@ -1258,17 +1251,20 @@ void GMainWindow::ConnectMenuEvents() {
1258 ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_900); 1251 ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_900);
1259 ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_1080); 1252 ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_1080);
1260 1253
1261 // Fullscreen 1254 // Tools
1262 connect(ui->action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); 1255 connect(ui->action_Rederive, &QAction::triggered, this,
1263 1256 std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning));
1264 // Movie
1265 connect(ui->action_Capture_Screenshot, &QAction::triggered, this, 1257 connect(ui->action_Capture_Screenshot, &QAction::triggered, this,
1266 &GMainWindow::OnCaptureScreenshot); 1258 &GMainWindow::OnCaptureScreenshot);
1267 1259
1260 // TAS
1261 connect(ui->action_TAS_Start, &QAction::triggered, this, &GMainWindow::OnTasStartStop);
1262 connect(ui->action_TAS_Record, &QAction::triggered, this, &GMainWindow::OnTasRecord);
1263 connect(ui->action_TAS_Reset, &QAction::triggered, this, &GMainWindow::OnTasReset);
1264 connect(ui->action_Configure_Tas, &QAction::triggered, this, &GMainWindow::OnConfigureTas);
1265
1268 // Help 1266 // Help
1269 connect(ui->action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder); 1267 connect(ui->action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder);
1270 connect(ui->action_Rederive, &QAction::triggered, this,
1271 std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning));
1272 connect(ui->action_About, &QAction::triggered, this, &GMainWindow::OnAbout); 1268 connect(ui->action_About, &QAction::triggered, this, &GMainWindow::OnAbout);
1273} 1269}
1274 1270
@@ -1582,6 +1578,7 @@ void GMainWindow::ShutdownGame() {
1582 game_list->SetFilterFocus(); 1578 game_list->SetFilterFocus();
1583 tas_label->clear(); 1579 tas_label->clear();
1584 input_subsystem->GetTas()->Stop(); 1580 input_subsystem->GetTas()->Stop();
1581 OnTasStateChanged();
1585 1582
1586 render_window->removeEventFilter(render_window); 1583 render_window->removeEventFilter(render_window);
1587 render_window->setAttribute(Qt::WA_Hover, false); 1584 render_window->setAttribute(Qt::WA_Hover, false);
@@ -2509,6 +2506,7 @@ void GMainWindow::OnStartGame() {
2509 ui->action_Restart->setEnabled(true); 2506 ui->action_Restart->setEnabled(true);
2510 ui->action_Configure_Current_Game->setEnabled(true); 2507 ui->action_Configure_Current_Game->setEnabled(true);
2511 ui->action_Report_Compatibility->setEnabled(true); 2508 ui->action_Report_Compatibility->setEnabled(true);
2509 OnTasStateChanged();
2512 2510
2513 discord_rpc->Update(); 2511 discord_rpc->Update();
2514 ui->action_Load_Amiibo->setEnabled(true); 2512 ui->action_Load_Amiibo->setEnabled(true);
@@ -2821,6 +2819,32 @@ void GMainWindow::OnConfigureTas() {
2821 } 2819 }
2822} 2820}
2823 2821
2822void GMainWindow::OnTasStartStop() {
2823 if (!emulation_running) {
2824 return;
2825 }
2826 input_subsystem->GetTas()->StartStop();
2827 OnTasStateChanged();
2828}
2829
2830void GMainWindow::OnTasRecord() {
2831 if (!emulation_running) {
2832 return;
2833 }
2834 const bool is_recording = input_subsystem->GetTas()->Record();
2835 if (!is_recording) {
2836 const auto res =
2837 QMessageBox::question(this, tr("TAS Recording"), tr("Overwrite file of player 1?"),
2838 QMessageBox::Yes | QMessageBox::No);
2839 input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes);
2840 }
2841 OnTasStateChanged();
2842}
2843
2844void GMainWindow::OnTasReset() {
2845 input_subsystem->GetTas()->Reset();
2846}
2847
2824void GMainWindow::OnConfigurePerGame() { 2848void GMainWindow::OnConfigurePerGame() {
2825 const u64 title_id = system->GetCurrentProcessProgramID(); 2849 const u64 title_id = system->GetCurrentProcessProgramID();
2826 OpenPerGameConfiguration(title_id, game_path.toStdString()); 2850 OpenPerGameConfiguration(title_id, game_path.toStdString());
@@ -3014,6 +3038,23 @@ QString GMainWindow::GetTasStateDescription() const {
3014 } 3038 }
3015} 3039}
3016 3040
3041void GMainWindow::OnTasStateChanged() {
3042 bool is_running = false;
3043 bool is_recording = false;
3044 if (emulation_running) {
3045 const TasInput::TasState tas_status = std::get<0>(input_subsystem->GetTas()->GetStatus());
3046 is_running = tas_status == TasInput::TasState::Running;
3047 is_recording = tas_status == TasInput::TasState::Recording;
3048 }
3049
3050 ui->action_TAS_Start->setText(is_running ? tr("&Stop Running") : tr("&Start"));
3051 ui->action_TAS_Record->setText(is_recording ? tr("Stop R&ecording") : tr("R&ecord"));
3052
3053 ui->action_TAS_Start->setEnabled(emulation_running);
3054 ui->action_TAS_Record->setEnabled(emulation_running);
3055 ui->action_TAS_Reset->setEnabled(emulation_running);
3056}
3057
3017void GMainWindow::UpdateStatusBar() { 3058void GMainWindow::UpdateStatusBar() {
3018 if (emu_thread == nullptr) { 3059 if (emu_thread == nullptr) {
3019 status_bar_update_timer.stop(); 3060 status_bar_update_timer.stop();
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 24633ff2d..556cbbaf7 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -177,6 +177,7 @@ public slots:
177 void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args, 177 void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
178 bool is_local); 178 bool is_local);
179 void OnAppFocusStateChanged(Qt::ApplicationState state); 179 void OnAppFocusStateChanged(Qt::ApplicationState state);
180 void OnTasStateChanged();
180 181
181private: 182private:
182 void RegisterMetaTypes(); 183 void RegisterMetaTypes();
@@ -268,6 +269,9 @@ private slots:
268 void OnMenuRecentFile(); 269 void OnMenuRecentFile();
269 void OnConfigure(); 270 void OnConfigure();
270 void OnConfigureTas(); 271 void OnConfigureTas();
272 void OnTasStartStop();
273 void OnTasRecord();
274 void OnTasReset();
271 void OnConfigurePerGame(); 275 void OnConfigurePerGame();
272 void OnLoadAmiibo(); 276 void OnLoadAmiibo();
273 void OnOpenYuzuFolder(); 277 void OnOpenYuzuFolder();
@@ -313,6 +317,7 @@ private:
313 void OpenURL(const QUrl& url); 317 void OpenURL(const QUrl& url);
314 void LoadTranslation(); 318 void LoadTranslation();
315 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); 319 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
320
316 QString GetTasStateDescription() const; 321 QString GetTasStateDescription() const;
317 322
318 std::unique_ptr<Ui::MainWindow> ui; 323 std::unique_ptr<Ui::MainWindow> ui;
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index a62e39a06..c58aa2866 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -79,39 +79,39 @@
79 <string>&amp;View</string> 79 <string>&amp;View</string>
80 </property> 80 </property>
81 <widget class="QMenu" name="menu_Reset_Window_Size"> 81 <widget class="QMenu" name="menu_Reset_Window_Size">
82 <property name="title"> 82 <property name="title">
83 <string>&amp;Reset Window Size</string> 83 <string>&amp;Reset Window Size</string>
84 </property> 84 </property>
85 </widget>
86 <widget class="QMenu" name="menu_View_Debugging">
87 <property name="title">
88 <string>&amp;Debugging</string>
89 </property>
85 </widget> 90 </widget>
86 <action name="action_Reset_Window_Size_720"> 91 <action name="action_Reset_Window_Size_720">
87 <property name="text"> 92 <property name="text">
88 <string>Reset Window Size to &amp;720p</string> 93 <string>Reset Window Size to &amp;720p</string>
89 </property> 94 </property>
90 <property name="iconText"> 95 <property name="iconText">
91 <string>Reset Window Size to 720p</string> 96 <string>Reset Window Size to 720p</string>
92 </property> 97 </property>
93 </action> 98 </action>
94 <action name="action_Reset_Window_Size_900"> 99 <action name="action_Reset_Window_Size_900">
95 <property name="text"> 100 <property name="text">
96 <string>Reset Window Size to &amp;900p</string> 101 <string>Reset Window Size to &amp;900p</string>
97 </property> 102 </property>
98 <property name="iconText"> 103 <property name="iconText">
99 <string>Reset Window Size to 900p</string> 104 <string>Reset Window Size to 900p</string>
100 </property> 105 </property>
101 </action> 106 </action>
102 <action name="action_Reset_Window_Size_1080"> 107 <action name="action_Reset_Window_Size_1080">
103 <property name="text"> 108 <property name="text">
104 <string>Reset Window Size to &amp;1080p</string> 109 <string>Reset Window Size to &amp;1080p</string>
105 </property>
106 <property name="iconText">
107 <string>Reset Window Size to 1080p</string>
108 </property>
109 </action>
110 <widget class="QMenu" name="menu_View_Debugging">
111 <property name="title">
112 <string>&amp;Debugging</string>
113 </property> 110 </property>
114 </widget> 111 <property name="iconText">
112 <string>Reset Window Size to 1080p</string>
113 </property>
114 </action>
115 <addaction name="action_Fullscreen"/> 115 <addaction name="action_Fullscreen"/>
116 <addaction name="action_Single_Window_Mode"/> 116 <addaction name="action_Single_Window_Mode"/>
117 <addaction name="action_Display_Dock_Widget_Headers"/> 117 <addaction name="action_Display_Dock_Widget_Headers"/>
@@ -125,10 +125,20 @@
125 <property name="title"> 125 <property name="title">
126 <string>&amp;Tools</string> 126 <string>&amp;Tools</string>
127 </property> 127 </property>
128 <widget class="QMenu" name="menuTAS">
129 <property name="title">
130 <string>&amp;TAS</string>
131 </property>
132 <addaction name="action_TAS_Start"/>
133 <addaction name="action_TAS_Record"/>
134 <addaction name="action_TAS_Reset"/>
135 <addaction name="separator"/>
136 <addaction name="action_Configure_Tas"/>
137 </widget>
128 <addaction name="action_Rederive"/> 138 <addaction name="action_Rederive"/>
129 <addaction name="separator"/> 139 <addaction name="separator"/>
130 <addaction name="action_Capture_Screenshot"/> 140 <addaction name="action_Capture_Screenshot"/>
131 <addaction name="action_Configure_Tas"/> 141 <addaction name="menuTAS"/>
132 </widget> 142 </widget>
133 <widget class="QMenu" name="menu_Help"> 143 <widget class="QMenu" name="menu_Help">
134 <property name="title"> 144 <property name="title">
@@ -309,7 +319,7 @@
309 </action> 319 </action>
310 <action name="action_Configure_Tas"> 320 <action name="action_Configure_Tas">
311 <property name="text"> 321 <property name="text">
312 <string>Configure &amp;TAS...</string> 322 <string>&amp;Configure TAS...</string>
313 </property> 323 </property>
314 </action> 324 </action>
315 <action name="action_Configure_Current_Game"> 325 <action name="action_Configure_Current_Game">
@@ -320,6 +330,30 @@
320 <string>Configure C&amp;urrent Game...</string> 330 <string>Configure C&amp;urrent Game...</string>
321 </property> 331 </property>
322 </action> 332 </action>
333 <action name="action_TAS_Start">
334 <property name="enabled">
335 <bool>false</bool>
336 </property>
337 <property name="text">
338 <string>&amp;Start</string>
339 </property>
340 </action>
341 <action name="action_TAS_Reset">
342 <property name="enabled">
343 <bool>false</bool>
344 </property>
345 <property name="text">
346 <string>&amp;Reset</string>
347 </property>
348 </action>
349 <action name="action_TAS_Record">
350 <property name="enabled">
351 <bool>false</bool>
352 </property>
353 <property name="text">
354 <string>R&amp;ecord</string>
355 </property>
356 </action>
323 </widget> 357 </widget>
324 <resources> 358 <resources>
325 <include location="yuzu.qrc"/> 359 <include location="yuzu.qrc"/>