Added TAS controls to the menu under Tools
This commit is contained in:
parent
d20f91da11
commit
f90d980837
|
@ -303,6 +303,7 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||||
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
|
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
|
connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
|
||||||
|
connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &GMainWindow::OnTasStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
|
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
|
||||||
|
@ -319,10 +320,18 @@ GRenderWindow::~GRenderWindow() {
|
||||||
|
|
||||||
void GRenderWindow::OnFrameDisplayed() {
|
void GRenderWindow::OnFrameDisplayed() {
|
||||||
input_subsystem->GetTas()->UpdateThread();
|
input_subsystem->GetTas()->UpdateThread();
|
||||||
|
TasInput::TasState new_tas_state = std::get<0>(input_subsystem->GetTas()->GetStatus());
|
||||||
|
|
||||||
if (!first_frame) {
|
if (!first_frame) {
|
||||||
|
last_tas_state = new_tas_state;
|
||||||
first_frame = true;
|
first_frame = true;
|
||||||
emit FirstFrameDisplayed();
|
emit FirstFrameDisplayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_tas_state != last_tas_state) {
|
||||||
|
last_tas_state = new_tas_state;
|
||||||
|
emit TasPlaybackStateChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GRenderWindow::IsShown() const {
|
bool GRenderWindow::IsShown() const {
|
||||||
|
|
|
@ -41,6 +41,10 @@ enum class LoadCallbackStage;
|
||||||
class RendererBase;
|
class RendererBase;
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
||||||
|
namespace TasInput {
|
||||||
|
enum class TasState;
|
||||||
|
}
|
||||||
|
|
||||||
class EmuThread final : public QThread {
|
class EmuThread final : public QThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -203,6 +207,7 @@ signals:
|
||||||
void ExecuteProgramSignal(std::size_t program_index);
|
void ExecuteProgramSignal(std::size_t program_index);
|
||||||
void ExitSignal();
|
void ExitSignal();
|
||||||
void MouseActivity();
|
void MouseActivity();
|
||||||
|
void TasPlaybackStateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void TouchBeginEvent(const QTouchEvent* event);
|
void TouchBeginEvent(const QTouchEvent* event);
|
||||||
|
@ -236,6 +241,7 @@ private:
|
||||||
QWidget* child_widget = nullptr;
|
QWidget* child_widget = nullptr;
|
||||||
|
|
||||||
bool first_frame = false;
|
bool first_frame = false;
|
||||||
|
TasInput::TasState last_tas_state;
|
||||||
|
|
||||||
std::array<std::size_t, 16> touch_ids{};
|
std::array<std::size_t, 16> touch_ids{};
|
||||||
|
|
||||||
|
|
|
@ -965,6 +965,9 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
const QString toggle_status_bar = QStringLiteral("Toggle Status Bar");
|
const QString toggle_status_bar = QStringLiteral("Toggle Status Bar");
|
||||||
const QString fullscreen = QStringLiteral("Fullscreen");
|
const QString fullscreen = QStringLiteral("Fullscreen");
|
||||||
const QString capture_screenshot = QStringLiteral("Capture Screenshot");
|
const QString capture_screenshot = QStringLiteral("Capture Screenshot");
|
||||||
|
const QString tas_start_stop = QStringLiteral("TAS Start/Stop");
|
||||||
|
const QString tas_record = QStringLiteral("TAS Record");
|
||||||
|
const QString tas_reset = QStringLiteral("TAS Reset");
|
||||||
|
|
||||||
ui->action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file));
|
ui->action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file));
|
||||||
ui->action_Load_File->setShortcutContext(
|
ui->action_Load_File->setShortcutContext(
|
||||||
|
@ -1005,6 +1008,18 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
ui->action_Fullscreen->setShortcutContext(
|
ui->action_Fullscreen->setShortcutContext(
|
||||||
hotkey_registry.GetShortcutContext(main_window, fullscreen));
|
hotkey_registry.GetShortcutContext(main_window, fullscreen));
|
||||||
|
|
||||||
|
ui->action_TAS_Start->setShortcut(hotkey_registry.GetKeySequence(main_window, tas_start_stop));
|
||||||
|
ui->action_TAS_Start->setShortcutContext(
|
||||||
|
hotkey_registry.GetShortcutContext(main_window, tas_start_stop));
|
||||||
|
|
||||||
|
ui->action_TAS_Record->setShortcut(hotkey_registry.GetKeySequence(main_window, tas_record));
|
||||||
|
ui->action_TAS_Record->setShortcutContext(
|
||||||
|
hotkey_registry.GetShortcutContext(main_window, tas_record));
|
||||||
|
|
||||||
|
ui->action_TAS_Reset->setShortcut(hotkey_registry.GetKeySequence(main_window, tas_reset));
|
||||||
|
ui->action_TAS_Reset->setShortcutContext(
|
||||||
|
hotkey_registry.GetShortcutContext(main_window, tas_reset));
|
||||||
|
|
||||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this),
|
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this),
|
||||||
&QShortcut::activated, this, &GMainWindow::OnMenuLoadFile);
|
&QShortcut::activated, this, &GMainWindow::OnMenuLoadFile);
|
||||||
connect(
|
connect(
|
||||||
|
@ -1095,28 +1110,6 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
render_window->setAttribute(Qt::WA_Hover, true);
|
render_window->setAttribute(Qt::WA_Hover, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Start/Stop"), this),
|
|
||||||
&QShortcut::activated, this, [&] {
|
|
||||||
if (!emulation_running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
input_subsystem->GetTas()->StartStop();
|
|
||||||
});
|
|
||||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Reset"), this),
|
|
||||||
&QShortcut::activated, this, [&] { input_subsystem->GetTas()->Reset(); });
|
|
||||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Record"), this),
|
|
||||||
&QShortcut::activated, this, [&] {
|
|
||||||
if (!emulation_running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool is_recording = input_subsystem->GetTas()->Record();
|
|
||||||
if (!is_recording) {
|
|
||||||
const auto res = QMessageBox::question(this, tr("TAS Recording"),
|
|
||||||
tr("Overwrite file of player 1?"),
|
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
|
||||||
input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::SetDefaultUIGeometry() {
|
void GMainWindow::SetDefaultUIGeometry() {
|
||||||
|
@ -1236,11 +1229,11 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
connect(ui->action_Restart, &QAction::triggered, this,
|
connect(ui->action_Restart, &QAction::triggered, this,
|
||||||
[this] { BootGame(QString(game_path)); });
|
[this] { BootGame(QString(game_path)); });
|
||||||
connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure);
|
connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure);
|
||||||
connect(ui->action_Configure_Tas, &QAction::triggered, this, &GMainWindow::OnConfigureTas);
|
|
||||||
connect(ui->action_Configure_Current_Game, &QAction::triggered, this,
|
connect(ui->action_Configure_Current_Game, &QAction::triggered, this,
|
||||||
&GMainWindow::OnConfigurePerGame);
|
&GMainWindow::OnConfigurePerGame);
|
||||||
|
|
||||||
// View
|
// View
|
||||||
|
connect(ui->action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
|
||||||
connect(ui->action_Single_Window_Mode, &QAction::triggered, this,
|
connect(ui->action_Single_Window_Mode, &QAction::triggered, this,
|
||||||
&GMainWindow::ToggleWindowMode);
|
&GMainWindow::ToggleWindowMode);
|
||||||
connect(ui->action_Display_Dock_Widget_Headers, &QAction::triggered, this,
|
connect(ui->action_Display_Dock_Widget_Headers, &QAction::triggered, this,
|
||||||
|
@ -1258,17 +1251,20 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_900);
|
ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_900);
|
||||||
ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_1080);
|
ui->menu_Reset_Window_Size->addAction(ui->action_Reset_Window_Size_1080);
|
||||||
|
|
||||||
// Fullscreen
|
// Tools
|
||||||
connect(ui->action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
|
connect(ui->action_Rederive, &QAction::triggered, this,
|
||||||
|
std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning));
|
||||||
// Movie
|
|
||||||
connect(ui->action_Capture_Screenshot, &QAction::triggered, this,
|
connect(ui->action_Capture_Screenshot, &QAction::triggered, this,
|
||||||
&GMainWindow::OnCaptureScreenshot);
|
&GMainWindow::OnCaptureScreenshot);
|
||||||
|
|
||||||
|
// TAS
|
||||||
|
connect(ui->action_TAS_Start, &QAction::triggered, this, &GMainWindow::OnTasStartStop);
|
||||||
|
connect(ui->action_TAS_Record, &QAction::triggered, this, &GMainWindow::OnTasRecord);
|
||||||
|
connect(ui->action_TAS_Reset, &QAction::triggered, this, &GMainWindow::OnTasReset);
|
||||||
|
connect(ui->action_Configure_Tas, &QAction::triggered, this, &GMainWindow::OnConfigureTas);
|
||||||
|
|
||||||
// Help
|
// Help
|
||||||
connect(ui->action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder);
|
connect(ui->action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder);
|
||||||
connect(ui->action_Rederive, &QAction::triggered, this,
|
|
||||||
std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning));
|
|
||||||
connect(ui->action_About, &QAction::triggered, this, &GMainWindow::OnAbout);
|
connect(ui->action_About, &QAction::triggered, this, &GMainWindow::OnAbout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1582,6 +1578,7 @@ void GMainWindow::ShutdownGame() {
|
||||||
game_list->SetFilterFocus();
|
game_list->SetFilterFocus();
|
||||||
tas_label->clear();
|
tas_label->clear();
|
||||||
input_subsystem->GetTas()->Stop();
|
input_subsystem->GetTas()->Stop();
|
||||||
|
OnTasStateChanged();
|
||||||
|
|
||||||
render_window->removeEventFilter(render_window);
|
render_window->removeEventFilter(render_window);
|
||||||
render_window->setAttribute(Qt::WA_Hover, false);
|
render_window->setAttribute(Qt::WA_Hover, false);
|
||||||
|
@ -2509,6 +2506,7 @@ void GMainWindow::OnStartGame() {
|
||||||
ui->action_Restart->setEnabled(true);
|
ui->action_Restart->setEnabled(true);
|
||||||
ui->action_Configure_Current_Game->setEnabled(true);
|
ui->action_Configure_Current_Game->setEnabled(true);
|
||||||
ui->action_Report_Compatibility->setEnabled(true);
|
ui->action_Report_Compatibility->setEnabled(true);
|
||||||
|
OnTasStateChanged();
|
||||||
|
|
||||||
discord_rpc->Update();
|
discord_rpc->Update();
|
||||||
ui->action_Load_Amiibo->setEnabled(true);
|
ui->action_Load_Amiibo->setEnabled(true);
|
||||||
|
@ -2821,6 +2819,33 @@ void GMainWindow::OnConfigureTas() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnTasStartStop() {
|
||||||
|
if (!emulation_running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input_subsystem->GetTas()->StartStop();
|
||||||
|
OnTasStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnTasRecord() {
|
||||||
|
if (!emulation_running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool is_recording = input_subsystem->GetTas()->Record();
|
||||||
|
if (!is_recording) {
|
||||||
|
const auto res =
|
||||||
|
QMessageBox::question(this, tr("TAS Recording"), tr("Overwrite file of player 1?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes);
|
||||||
|
}
|
||||||
|
OnTasStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnTasReset() {
|
||||||
|
input_subsystem->GetTas()->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GMainWindow::OnConfigurePerGame() {
|
void GMainWindow::OnConfigurePerGame() {
|
||||||
const u64 title_id = system->GetCurrentProcessProgramID();
|
const u64 title_id = system->GetCurrentProcessProgramID();
|
||||||
OpenPerGameConfiguration(title_id, game_path.toStdString());
|
OpenPerGameConfiguration(title_id, game_path.toStdString());
|
||||||
|
@ -3014,6 +3039,23 @@ QString GMainWindow::GetTasStateDescription() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnTasStateChanged() {
|
||||||
|
bool is_running = false;
|
||||||
|
bool is_recording = false;
|
||||||
|
if (emulation_running) {
|
||||||
|
TasInput::TasState tas_status = std::get<0>(input_subsystem->GetTas()->GetStatus());
|
||||||
|
is_running = tas_status == TasInput::TasState::Running;
|
||||||
|
is_recording = tas_status == TasInput::TasState::Recording;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->action_TAS_Start->setText(is_running ? tr("&Stop Running") : tr("&Start"));
|
||||||
|
ui->action_TAS_Record->setText(is_recording ? tr("Stop R&ecording") : tr("R&ecord"));
|
||||||
|
|
||||||
|
ui->action_TAS_Start->setEnabled(emulation_running);
|
||||||
|
ui->action_TAS_Record->setEnabled(emulation_running);
|
||||||
|
ui->action_TAS_Reset->setEnabled(emulation_running);
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::UpdateStatusBar() {
|
void GMainWindow::UpdateStatusBar() {
|
||||||
if (emu_thread == nullptr) {
|
if (emu_thread == nullptr) {
|
||||||
status_bar_update_timer.stop();
|
status_bar_update_timer.stop();
|
||||||
|
|
|
@ -177,6 +177,7 @@ public slots:
|
||||||
void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
|
void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
|
||||||
bool is_local);
|
bool is_local);
|
||||||
void OnAppFocusStateChanged(Qt::ApplicationState state);
|
void OnAppFocusStateChanged(Qt::ApplicationState state);
|
||||||
|
void OnTasStateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RegisterMetaTypes();
|
void RegisterMetaTypes();
|
||||||
|
@ -268,6 +269,9 @@ private slots:
|
||||||
void OnMenuRecentFile();
|
void OnMenuRecentFile();
|
||||||
void OnConfigure();
|
void OnConfigure();
|
||||||
void OnConfigureTas();
|
void OnConfigureTas();
|
||||||
|
void OnTasStartStop();
|
||||||
|
void OnTasRecord();
|
||||||
|
void OnTasReset();
|
||||||
void OnConfigurePerGame();
|
void OnConfigurePerGame();
|
||||||
void OnLoadAmiibo();
|
void OnLoadAmiibo();
|
||||||
void OnOpenYuzuFolder();
|
void OnOpenYuzuFolder();
|
||||||
|
@ -313,6 +317,7 @@ private:
|
||||||
void OpenURL(const QUrl& url);
|
void OpenURL(const QUrl& url);
|
||||||
void LoadTranslation();
|
void LoadTranslation();
|
||||||
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
||||||
|
|
||||||
QString GetTasStateDescription() const;
|
QString GetTasStateDescription() const;
|
||||||
|
|
||||||
std::unique_ptr<Ui::MainWindow> ui;
|
std::unique_ptr<Ui::MainWindow> ui;
|
||||||
|
|
|
@ -83,6 +83,11 @@
|
||||||
<string>&Reset Window Size</string>
|
<string>&Reset Window Size</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menu_View_Debugging">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Debugging</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<action name="action_Reset_Window_Size_720">
|
<action name="action_Reset_Window_Size_720">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Reset Window Size to &720p</string>
|
<string>Reset Window Size to &720p</string>
|
||||||
|
@ -107,11 +112,6 @@
|
||||||
<string>Reset Window Size to 1080p</string>
|
<string>Reset Window Size to 1080p</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<widget class="QMenu" name="menu_View_Debugging">
|
|
||||||
<property name="title">
|
|
||||||
<string>&Debugging</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<addaction name="action_Fullscreen"/>
|
<addaction name="action_Fullscreen"/>
|
||||||
<addaction name="action_Single_Window_Mode"/>
|
<addaction name="action_Single_Window_Mode"/>
|
||||||
<addaction name="action_Display_Dock_Widget_Headers"/>
|
<addaction name="action_Display_Dock_Widget_Headers"/>
|
||||||
|
@ -125,10 +125,20 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>&Tools</string>
|
<string>&Tools</string>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QMenu" name="menuTAS">
|
||||||
|
<property name="title">
|
||||||
|
<string>&TAS</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="action_TAS_Start"/>
|
||||||
|
<addaction name="action_TAS_Record"/>
|
||||||
|
<addaction name="action_TAS_Reset"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="action_Configure_Tas"/>
|
||||||
|
</widget>
|
||||||
<addaction name="action_Rederive"/>
|
<addaction name="action_Rederive"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Capture_Screenshot"/>
|
<addaction name="action_Capture_Screenshot"/>
|
||||||
<addaction name="action_Configure_Tas"/>
|
<addaction name="menuTAS"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_Help">
|
<widget class="QMenu" name="menu_Help">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -309,7 +319,7 @@
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Configure_Tas">
|
<action name="action_Configure_Tas">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Configure &TAS...</string>
|
<string>&Configure TAS...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Configure_Current_Game">
|
<action name="action_Configure_Current_Game">
|
||||||
|
@ -320,6 +330,30 @@
|
||||||
<string>Configure C&urrent Game...</string>
|
<string>Configure C&urrent Game...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_TAS_Start">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Start</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_TAS_Reset">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Reset</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_TAS_Record">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>R&ecord</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="yuzu.qrc"/>
|
<include location="yuzu.qrc"/>
|
||||||
|
|
Reference in New Issue