diff --git a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp index 9ef181354a..4fb77fdb65 100644 --- a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp @@ -23,6 +23,8 @@ #include "DolphinWX/Cheats/GeckoCodeDiag.h" #include "DolphinWX/WxUtils.h" +wxDEFINE_EVENT(DOLPHIN_EVT_GECKOCODE_TOGGLED, wxCommandEvent); + namespace Gecko { static const wxString wxstr_name(wxTRANSLATE("Name: ")), wxstr_notes(wxTRANSLATE("Notes: ")), @@ -108,7 +110,13 @@ void CodeConfigPanel::ToggleCode(wxCommandEvent& evt) { const int sel = evt.GetInt(); // this right? if (sel > -1) + { m_gcodes[sel].enabled = m_listbox_gcodes->IsChecked(sel); + + wxCommandEvent toggle_event(DOLPHIN_EVT_GECKOCODE_TOGGLED, GetId()); + toggle_event.SetClientData(&m_gcodes[sel]); + GetEventHandler()->ProcessEvent(toggle_event); + } } void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) diff --git a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.h b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.h index 317f84f205..724dc76939 100644 --- a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.h +++ b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.h @@ -17,6 +17,9 @@ class wxListBox; class wxStaticText; class wxTextCtrl; +// GetClientData() -> GeckoCode* [immutable] +wxDECLARE_EVENT(DOLPHIN_EVT_GECKOCODE_TOGGLED, wxCommandEvent); + namespace Gecko { class CodeConfigPanel : public wxPanel diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index cbcee5e374..01285c3a37 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -109,6 +109,7 @@ public: void PopulateSavedPerspectives(); static void ConnectWiimote(int wm_idx, bool connect); void UpdateTitle(const std::string& str); + void OpenGeneralConfiguration(int tab = -1); const CGameListCtrl* GetGameListCtrl() const; wxMenuBar* GetMenuBar() const override; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 4dc8789796..2fdf38a02f 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -600,6 +600,20 @@ void CFrame::InitBitmaps() RecreateToolbar(); } +void CFrame::OpenGeneralConfiguration(int tab) +{ + CConfigMain config_main(this); + if (tab > -1) + config_main.SetSelectedTab(tab); + + HotkeyManagerEmu::Enable(false); + if (config_main.ShowModal() == wxID_OK) + m_GameListCtrl->Update(); + HotkeyManagerEmu::Enable(true); + + UpdateGUI(); +} + // Menu items // Start the game or change the disc. @@ -1300,12 +1314,7 @@ void CFrame::OnReset(wxCommandEvent& WXUNUSED(event)) void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED(event)) { - CConfigMain ConfigMain(this); - HotkeyManagerEmu::Enable(false); - if (ConfigMain.ShowModal() == wxID_OK) - m_GameListCtrl->Update(); - HotkeyManagerEmu::Enable(true); - UpdateGUI(); + OpenGeneralConfiguration(); } void CFrame::OnConfigGFX(wxCommandEvent& WXUNUSED(event)) @@ -1318,12 +1327,7 @@ void CFrame::OnConfigGFX(wxCommandEvent& WXUNUSED(event)) void CFrame::OnConfigAudio(wxCommandEvent& WXUNUSED(event)) { - CConfigMain ConfigMain(this); - ConfigMain.SetSelectedTab(CConfigMain::ID_AUDIOPAGE); - HotkeyManagerEmu::Enable(false); - if (ConfigMain.ShowModal() == wxID_OK) - m_GameListCtrl->Update(); - HotkeyManagerEmu::Enable(true); + OpenGeneralConfiguration(CConfigMain::ID_AUDIOPAGE); } void CFrame::OnConfigControllers(wxCommandEvent& WXUNUSED(event)) diff --git a/Source/Core/DolphinWX/ISOProperties.cpp b/Source/Core/DolphinWX/ISOProperties.cpp index e8b30dddfe..339ff592bf 100644 --- a/Source/Core/DolphinWX/ISOProperties.cpp +++ b/Source/Core/DolphinWX/ISOProperties.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ #include "Common/SysConf.h" #include "Core/Boot/Boot.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" #include "Core/GeckoCodeConfig.h" #include "Core/PatchEngine.h" #include "DiscIO/Blob.h" @@ -65,12 +67,126 @@ #include "DiscIO/VolumeCreator.h" #include "DolphinWX/Cheats/ActionReplayCodesPanel.h" #include "DolphinWX/Cheats/GeckoCodeDiag.h" +#include "DolphinWX/Frame.h" #include "DolphinWX/Globals.h" #include "DolphinWX/ISOFile.h" #include "DolphinWX/ISOProperties.h" +#include "DolphinWX/Main.h" #include "DolphinWX/PatchAddEdit.h" #include "DolphinWX/WxUtils.h" +// A warning message displayed on the ARCodes and GeckoCodes pages when cheats are +// disabled globally to explain why turning cheats on does not work. +// Also displays a different warning when the game is currently running to explain +// that toggling codes has no effect while the game is already running. +class CheatWarningMessage final : public wxPanel +{ +public: + CheatWarningMessage(wxWindow* parent, std::string game_id) + : wxPanel(parent), m_game_id(std::move(game_id)) + { + SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS); + CreateGUI(); + wxTheApp->Bind(wxEVT_IDLE, &CheatWarningMessage::OnAppIdle, this); + Hide(); + } + + void UpdateState() + { + // If cheats are disabled then show the notification about that. + // If cheats are enabled and the game is currently running then display that warning. + State new_state = State::Hidden; + if (!SConfig::GetInstance().bEnableCheats) + new_state = State::DisabledCheats; + else if (Core::IsRunning() && SConfig::GetInstance().GetUniqueID() == m_game_id) + new_state = State::GameRunning; + ApplyState(new_state); + } + +private: + enum class State + { + Inactive, + Hidden, + DisabledCheats, + GameRunning + }; + + void CreateGUI() + { + wxStaticBitmap* icon = + new wxStaticBitmap(this, wxID_ANY, wxArtProvider::GetMessageBoxIcon(wxICON_WARNING)); + m_message = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, + wxST_NO_AUTORESIZE); + m_btn_configure = new wxButton(this, wxID_ANY, _("Configure Dolphin")); + + m_btn_configure->Bind(wxEVT_BUTTON, &CheatWarningMessage::OnConfigureClicked, this); + + wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(icon, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 15); + sizer->Add(m_message, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 15); + sizer->Add(m_btn_configure, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10); + sizer->AddSpacer(10); + + SetSizer(sizer); + } + + void OnConfigureClicked(wxCommandEvent&) + { + main_frame->OpenGeneralConfiguration(); + UpdateState(); + } + + void OnAppIdle(wxIdleEvent& ev) + { + ev.Skip(); + // Only respond to setting changes if we've been triggered once already. + if (m_state != State::Inactive) + UpdateState(); + } + + void ApplyState(State new_state) + { + // The purpose of this function is to prevent unnecessary UI updates which cause flickering. + if (new_state == m_state || (m_state == State::Inactive && new_state == State::Hidden)) + return; + + bool visible = true; + switch (new_state) + { + case State::Inactive: + case State::Hidden: + visible = false; + break; + + case State::DisabledCheats: + m_btn_configure->Show(); + m_message->SetLabelText(_("Dolphin's cheat system is currently disabled.")); + break; + + case State::GameRunning: + m_btn_configure->Hide(); + m_message->SetLabelText( + _("Changing cheats will only take effect when the game is restarted.")); + break; + } + m_state = new_state; + Show(visible); + GetParent()->Layout(); + if (visible) + { + m_message->Wrap(m_message->GetSize().GetWidth()); + m_message->InvalidateBestSize(); + GetParent()->Layout(); + } + } + + std::string m_game_id; + wxStaticText* m_message = nullptr; + wxButton* m_btn_configure = nullptr; + State m_state = State::Inactive; +}; + BEGIN_EVENT_TABLE(CISOProperties, wxDialog) EVT_CLOSE(CISOProperties::OnClose) EVT_BUTTON(wxID_OK, CISOProperties::OnCloseClick) @@ -313,8 +429,8 @@ void CISOProperties::CreateGUIControls() m_Notebook->AddPage(m_PatchPage, _("Patches")); wxPanel* const m_CheatPage = new wxPanel(m_Notebook, ID_ARCODE_PAGE); m_Notebook->AddPage(m_CheatPage, _("AR Codes")); - m_geckocode_panel = new Gecko::CodeConfigPanel(m_Notebook); - m_Notebook->AddPage(m_geckocode_panel, _("Gecko Codes")); + wxPanel* const gecko_cheat_page = new wxPanel(m_Notebook); + m_Notebook->AddPage(gecko_cheat_page, _("Gecko Codes")); wxPanel* const m_Information = new wxPanel(m_Notebook, ID_INFORMATION); m_Notebook->AddPage(m_Information, _("Info")); @@ -472,12 +588,27 @@ void CISOProperties::CreateGUIControls() // Action Replay Cheats m_ar_code_panel = new ActionReplayCodesPanel(m_CheatPage, ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS); + m_cheats_disabled_ar = new CheatWarningMessage(m_CheatPage, game_id); + + m_ar_code_panel->Bind(DOLPHIN_EVT_ARCODE_TOGGLED, &CISOProperties::OnCheatCodeToggled, this); wxBoxSizer* const sCheatPage = new wxBoxSizer(wxVERTICAL); - // TODO: Cheat disabled warning. + sCheatPage->Add(m_cheats_disabled_ar, 0, wxEXPAND | wxTOP, 5); sCheatPage->Add(m_ar_code_panel, 1, wxEXPAND | wxALL, 5); m_CheatPage->SetSizer(sCheatPage); + // Gecko Cheats + m_geckocode_panel = new Gecko::CodeConfigPanel(gecko_cheat_page); + m_cheats_disabled_gecko = new CheatWarningMessage(gecko_cheat_page, game_id); + + m_geckocode_panel->Bind(DOLPHIN_EVT_GECKOCODE_TOGGLED, &CISOProperties::OnCheatCodeToggled, this); + + wxBoxSizer* gecko_layout = new wxBoxSizer(wxVERTICAL); + gecko_layout->Add(m_cheats_disabled_gecko, 0, wxEXPAND | wxTOP, 5); + gecko_layout->Add(m_geckocode_panel, 1, wxEXPAND); + gecko_cheat_page->SetSizer(gecko_layout); + + // Info Page wxStaticText* const m_InternalNameText = new wxStaticText(m_Information, wxID_ANY, _("Internal Name:")); m_InternalName = new wxTextCtrl(m_Information, ID_NAME, wxEmptyString, wxDefaultPosition, @@ -1285,6 +1416,12 @@ void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED(event)) GenerateLocalIniModified(); } +void CISOProperties::OnCheatCodeToggled(wxCommandEvent&) +{ + m_cheats_disabled_ar->UpdateState(); + m_cheats_disabled_gecko->UpdateState(); +} + void CISOProperties::OnComputeMD5Sum(wxCommandEvent& WXUNUSED(event)) { wxProgressDialog progressDialog(_("Computing MD5 checksum"), _("Working..."), 100, this, diff --git a/Source/Core/DolphinWX/ISOProperties.h b/Source/Core/DolphinWX/ISOProperties.h index 125ff29967..c3e70e62dd 100644 --- a/Source/Core/DolphinWX/ISOProperties.h +++ b/Source/Core/DolphinWX/ISOProperties.h @@ -19,7 +19,6 @@ #include "DolphinWX/ISOFile.h" #include "DolphinWX/PatchAddEdit.h" -class GameListItem; class wxButton; class wxCheckBox; class wxCheckListBox; @@ -39,6 +38,8 @@ namespace Gecko class CodeConfigPanel; } class ActionReplayCodesPanel; +class CheatWarningMessage; +class GameListItem; class WiiPartition final : public wxTreeItemData { @@ -123,6 +124,9 @@ private: ActionReplayCodesPanel* m_ar_code_panel; Gecko::CodeConfigPanel* m_geckocode_panel; + CheatWarningMessage* m_cheats_disabled_ar; + CheatWarningMessage* m_cheats_disabled_gecko; + enum { ID_TREECTRL = 1000, @@ -203,6 +207,7 @@ private: void CheckPartitionIntegrity(wxCommandEvent& event); void OnEmustateChanged(wxCommandEvent& event); void OnChangeBannerLang(wxCommandEvent& event); + void OnCheatCodeToggled(wxCommandEvent& event); const GameListItem OpenGameListItem;