Initial support for title switching + better Wii U menu compatibility (#907)

This commit is contained in:
Exzap 2023-07-21 13:54:07 +02:00 committed by GitHub
parent bfbeeae6f6
commit 2200cc0ddf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 2549 additions and 746 deletions

View file

@ -73,8 +73,6 @@
extern WindowInfo g_window_info;
extern std::shared_mutex g_mutex;
wxDEFINE_EVENT(wxEVT_SET_WINDOW_TITLE, wxCommandEvent);
enum
{
// ui elements
@ -161,8 +159,10 @@ enum
MAINFRAME_ID_TIMER1 = 21800,
};
wxDEFINE_EVENT(wxEVT_SET_WINDOW_TITLE, wxCommandEvent);
wxDEFINE_EVENT(wxEVT_REQUEST_GAMELIST_REFRESH, wxCommandEvent);
wxDEFINE_EVENT(wxEVT_LAUNCH_GAME, wxLaunchGameEvent);
wxDEFINE_EVENT(wxEVT_REQUEST_RECREATE_CANVAS, wxCommandEvent);
wxBEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_TIMER(MAINFRAME_ID_TIMER1, MainWindow::OnTimer)
@ -237,6 +237,8 @@ EVT_COMMAND(wxID_ANY, wxEVT_GAMELIST_END_UPDATE, MainWindow::OnGameListEndUpdate
EVT_COMMAND(wxID_ANY, wxEVT_ACCOUNTLIST_REFRESH, MainWindow::OnAccountListRefresh)
EVT_COMMAND(wxID_ANY, wxEVT_SET_WINDOW_TITLE, MainWindow::OnSetWindowTitle)
EVT_COMMAND(wxID_ANY, wxEVT_REQUEST_RECREATE_CANVAS, MainWindow::OnRequestRecreateCanvas)
wxEND_EVENT_TABLE()
class wxGameDropTarget : public wxFileDropTarget
@ -290,6 +292,7 @@ MainWindow::MainWindow()
{
gui_initHandleContextFromWxWidgetsWindow(g_window_info.window_main, this);
g_mainFrame = this;
CafeSystem::SetImplementation(this);
RecreateMenu();
SetClientSize(1280, 720);
@ -330,62 +333,45 @@ MainWindow::MainWindow()
}
}
if (!quick_launch)
{
{
m_main_panel = new wxPanel(this);
auto* sizer = new wxBoxSizer(wxVERTICAL);
// game list
m_game_list = new wxGameList(m_main_panel, MAINFRAME_GAMELIST_ID);
m_game_list->Bind(wxEVT_OPEN_SETTINGS, [this](auto&) {OpenSettings(); });
m_game_list->SetDropTarget(new wxGameDropTarget(this));
sizer->Add(m_game_list, 1, wxEXPAND);
SetSizer(main_sizer);
if (!quick_launch)
{
CreateGameListAndStatusBar();
}
else
{
// launching game via -g or -t option. Don't set up or load game list
m_game_list = nullptr;
m_info_bar = nullptr;
}
SetSizer(main_sizer);
// info, warning bar
m_info_bar = new wxInfoBar(m_main_panel);
m_info_bar->SetShowHideEffects(wxSHOW_EFFECT_BLEND, wxSHOW_EFFECT_BLEND);
m_info_bar->SetEffectDuration(500);
sizer->Add(m_info_bar, 0, wxALL | wxEXPAND, 5);
m_last_mouse_move_time = std::chrono::steady_clock::now();
m_main_panel->SetSizer(sizer);
main_sizer->Add(m_main_panel, 1, wxEXPAND, 0, nullptr);
}
}
else
{
// launching game via -g or -t option. Don't set up or load game list
m_game_list = nullptr;
m_info_bar = nullptr;
}
SetSizer(main_sizer);
m_timer = new wxTimer(this, MAINFRAME_ID_TIMER1);
m_timer->Start(500);
m_last_mouse_move_time = std::chrono::steady_clock::now();
LoadSettings();
m_timer = new wxTimer(this, MAINFRAME_ID_TIMER1);
m_timer->Start(500);
auto& config = GetConfig();
#ifdef ENABLE_DISCORD_RPC
if (config.use_discord_presence)
m_discord = std::make_unique<DiscordPresence>();
#endif
LoadSettings();
Bind(wxEVT_OPEN_GRAPHIC_PACK, &MainWindow::OnGraphicWindowOpen, this);
Bind(wxEVT_LAUNCH_GAME, &MainWindow::OnLaunchFromFile, this);
auto& config = GetConfig();
#ifdef ENABLE_DISCORD_RPC
if (config.use_discord_presence)
m_discord = std::make_unique<DiscordPresence>();
#endif
Bind(wxEVT_OPEN_GRAPHIC_PACK, &MainWindow::OnGraphicWindowOpen, this);
Bind(wxEVT_LAUNCH_GAME, &MainWindow::OnLaunchFromFile, this);
if (LaunchSettings::GDBStubEnabled())
{
g_gdbstub = std::make_unique<GDBServer>(config.gdb_port);
}
if (LaunchSettings::GDBStubEnabled())
{
g_gdbstub = std::make_unique<GDBServer>(config.gdb_port);
}
}
MainWindow::~MainWindow()
{
if (m_padView)
{
//delete m_padView;
m_padView->Destroy();
m_padView = nullptr;
}
@ -396,13 +382,47 @@ MainWindow::~MainWindow()
g_mainFrame = nullptr;
}
void MainWindow::CreateGameListAndStatusBar()
{
if(m_main_panel)
return; // already displayed
m_main_panel = new wxPanel(this);
auto* sizer = new wxBoxSizer(wxVERTICAL);
// game list
m_game_list = new wxGameList(m_main_panel, MAINFRAME_GAMELIST_ID);
m_game_list->Bind(wxEVT_OPEN_SETTINGS, [this](auto&) {OpenSettings(); });
m_game_list->SetDropTarget(new wxGameDropTarget(this));
sizer->Add(m_game_list, 1, wxEXPAND);
// info, warning bar
m_info_bar = new wxInfoBar(m_main_panel);
m_info_bar->SetShowHideEffects(wxSHOW_EFFECT_BLEND, wxSHOW_EFFECT_BLEND);
m_info_bar->SetEffectDuration(500);
sizer->Add(m_info_bar, 0, wxALL | wxEXPAND, 5);
m_main_panel->SetSizer(sizer);
auto* main_sizer = this->GetSizer();
main_sizer->Add(m_main_panel, 1, wxEXPAND, 0, nullptr);
}
void MainWindow::DestroyGameListAndStatusBar()
{
if(!m_main_panel)
return;
m_main_panel->Destroy();
m_main_panel = nullptr;
m_game_list = nullptr;
m_info_bar = nullptr;
}
wxString MainWindow::GetInitialWindowTitle()
{
return BUILD_VERSION_WITH_NAME_STRING;
}
void MainWindow::ShowGettingStartedDialog()
{
{
GettingStartedDialog dia(this);
dia.ShowModal();
if (dia.HasGamePathChanged() || dia.HasMLCChanged())
@ -435,7 +455,7 @@ void MainWindow::OnClose(wxCloseEvent& event)
event.Skip();
CafeSystem::ShutdownTitle();
CafeSystem::Shutdown();
DestroyCanvas();
}
@ -558,36 +578,13 @@ bool MainWindow::FileLoad(std::wstring fileName, wxLaunchGameEvent::INITIATED_BY
wxWindowUpdateLocker lock(this);
auto* main_sizer = GetSizer();
// remove old gamelist panel
if (m_main_panel)
{
m_main_panel->Hide();
main_sizer->Detach(m_main_panel);
}
// create render canvas rendering
m_game_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER | wxWANTS_CHARS);
auto* sizer = new wxBoxSizer(wxVERTICAL);
// shouldn't be needed, but who knows
m_game_panel->Bind(wxEVT_KEY_UP, &MainWindow::OnKeyUp, this);
m_game_panel->Bind(wxEVT_CHAR, &MainWindow::OnChar, this);
m_game_panel->SetSizer(sizer);
main_sizer->Add(m_game_panel, 1, wxEXPAND, 0, nullptr);
DestroyGameListAndStatusBar();
m_game_launched = true;
m_loadMenuItem->Enable(false);
m_installUpdateMenuItem->Enable(false);
m_memorySearcherMenuItem->Enable(true);
if (m_game_list)
{
delete m_game_list;
m_game_list = nullptr;
}
m_launched_game_name = CafeSystem::GetForegroundTitleName();
#ifdef ENABLE_DISCORD_RPC
if (m_discord)
@ -675,10 +672,12 @@ void MainWindow::OnFileMenu(wxCommandEvent& event)
}
else if (menuId == MAINFRAME_MENU_ID_FILE_END_EMULATION)
{
CafeSystem::ShutdownTitle();
CafeSystem::ShutdownTitle();
DestroyCanvas();
m_game_launched = false;
RecreateMenu();
CreateGameListAndStatusBar();
DoLayout();
}
}
@ -1547,7 +1546,19 @@ void MainWindow::AsyncSetTitle(std::string_view windowTitle)
void MainWindow::CreateCanvas()
{
if (ActiveSettings::GetGraphicsAPI() == kVulkan)
// create panel for canvas
m_game_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER | wxWANTS_CHARS);
auto* sizer = new wxBoxSizer(wxVERTICAL);
// shouldn't be needed, but who knows
m_game_panel->Bind(wxEVT_KEY_UP, &MainWindow::OnKeyUp, this);
m_game_panel->Bind(wxEVT_CHAR, &MainWindow::OnChar, this);
m_game_panel->SetSizer(sizer);
this->GetSizer()->Add(m_game_panel, 1, wxEXPAND, 0, nullptr);
// create canvas
if (ActiveSettings::GetGraphicsAPI() == kVulkan)
m_render_canvas = new VulkanCanvas(m_game_panel, wxSize(1280, 720), true);
else
m_render_canvas = GLCanvas_Create(m_game_panel, wxSize(1280, 720), true);
@ -1580,14 +1591,18 @@ void MainWindow::DestroyCanvas()
{
if (m_padView)
{
m_padView->Destroy();
m_padView = nullptr;
m_padView->DestroyCanvas();
}
if (m_render_canvas)
{
m_render_canvas->Destroy();
m_render_canvas = nullptr;
}
if(m_game_panel)
{
m_game_panel->Destroy();
m_game_panel = nullptr;
}
}
void MainWindow::OnSizeEvent(wxSizeEvent& event)
@ -2048,9 +2063,9 @@ void MainWindow::RecreateMenu()
auto& config = GetConfig();
m_menuBar = new wxMenuBar;
m_menuBar = new wxMenuBar();
// file submenu
m_fileMenu = new wxMenu;
m_fileMenu = new wxMenu();
if (!m_game_launched)
{
@ -2084,7 +2099,7 @@ void MainWindow::RecreateMenu()
{
// add 'Stop emulation' menu entry to file menu
#ifdef CEMU_DEBUG_ASSERT
m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_END_EMULATION, _("End emulation"));
m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_END_EMULATION, _("Stop emulation"));
#endif
}
@ -2094,7 +2109,7 @@ void MainWindow::RecreateMenu()
m_exitMenuItem = m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_EXIT, _("&Exit"));
m_menuBar->Append(m_fileMenu, _("&File"));
// options->account submenu
m_optionsAccountMenu = new wxMenu;
m_optionsAccountMenu = new wxMenu();
const auto account_id = ActiveSettings::GetPersistentId();
int index = 0;
for(const auto& account : Account::GetAccounts())
@ -2106,23 +2121,9 @@ void MainWindow::RecreateMenu()
++index;
}
//optionsAccountMenu->AppendSeparator(); TODO
//optionsAccountMenu->AppendCheckItem(MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_1 + index, _("Online enabled"))->Check(config.account.online_enabled);
// options->region submenu
//wxMenu* optionsRegionMenu = new wxMenu;
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_AUTO, _("&Auto"), wxEmptyString)->Check(config.console_region == ConsoleRegion::Auto);
////optionsRegionMenu->AppendSeparator();
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_USA, _("&USA"), wxEmptyString)->Check(config.console_region == ConsoleRegion::USA);
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_EUR, _("&Europe"), wxEmptyString)->Check(config.console_region == ConsoleRegion::EUR);
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_JPN, _("&Japan"), wxEmptyString)->Check(config.console_region == ConsoleRegion::JPN);
//// optionsRegionMenu->Append(MAINFRAME_MENU_ID_OPTIONS_REGION_AUS, wxT("&Australia"), wxEmptyString, wxITEM_RADIO)->Check(config_get()->region==3); -> Was merged into Europe?
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_CHN, _("&China"), wxEmptyString)->Check(config.console_region == ConsoleRegion::CHN);
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_KOR, _("&Korea"), wxEmptyString)->Check(config.console_region == ConsoleRegion::KOR);
//optionsRegionMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_REGION_TWN, _("&Taiwan"), wxEmptyString)->Check(config.console_region == ConsoleRegion::TWN);
// options->console language submenu
wxMenu* optionsConsoleLanguageMenu = new wxMenu;
wxMenu* optionsConsoleLanguageMenu = new wxMenu();
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_ENGLISH, _("&English"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::EN);
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_JAPANESE, _("&Japanese"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::JA);
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_FRENCH, _("&French"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::FR);
@ -2137,12 +2138,11 @@ void MainWindow::RecreateMenu()
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_TAIWANESE, _("&Taiwanese"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::TW);
// options submenu
wxMenu* optionsMenu = new wxMenu;
wxMenu* optionsMenu = new wxMenu();
m_fullscreenMenuItem = optionsMenu->AppendCheckItem(MAINFRAME_MENU_ID_OPTIONS_FULLSCREEN, _("&Fullscreen"), wxEmptyString);
m_fullscreenMenuItem->Check(ActiveSettings::FullscreenEnabled());
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_GRAPHIC_PACKS2, _("&Graphic packs"));
//optionsMenu->AppendSubMenu(optionsVCAMenu, _("&GPU buffer cache accuracy"));
m_padViewMenuItem = optionsMenu->AppendCheckItem(MAINFRAME_MENU_ID_OPTIONS_SECOND_WINDOW_PADVIEW, _("&Separate GamePad view"), wxEmptyString);
m_padViewMenuItem->Check(GetConfig().pad_open);
optionsMenu->AppendSeparator();
@ -2151,12 +2151,11 @@ void MainWindow::RecreateMenu()
optionsMenu->AppendSeparator();
optionsMenu->AppendSubMenu(m_optionsAccountMenu, _("&Active account"));
//optionsMenu->AppendSubMenu(optionsRegionMenu, _("&Console region"));
optionsMenu->AppendSubMenu(optionsConsoleLanguageMenu, _("&Console language"));
m_menuBar->Append(optionsMenu, _("&Options"));
// tools submenu
wxMenu* toolsMenu = new wxMenu;
wxMenu* toolsMenu = new wxMenu();
m_memorySearcherMenuItem = toolsMenu->Append(MAINFRAME_MENU_ID_TOOLS_MEMORY_SEARCHER, _("&Memory searcher"));
m_memorySearcherMenuItem->Enable(false);
toolsMenu->Append(MAINFRAME_MENU_ID_TOOLS_TITLE_MANAGER, _("&Title Manager"));
@ -2164,7 +2163,7 @@ void MainWindow::RecreateMenu()
m_menuBar->Append(toolsMenu, _("&Tools"));
// cpu timer speed menu
wxMenu* timerSpeedMenu = new wxMenu;
wxMenu* timerSpeedMenu = new wxMenu();
timerSpeedMenu->AppendRadioItem(MAINFRAME_MENU_ID_TIMER_SPEED_1X, _("&1x speed"), wxEmptyString)->Check(ActiveSettings::GetTimerShiftFactor() == 3);
timerSpeedMenu->AppendRadioItem(MAINFRAME_MENU_ID_TIMER_SPEED_2X, _("&2x speed"), wxEmptyString)->Check(ActiveSettings::GetTimerShiftFactor() == 2);
timerSpeedMenu->AppendRadioItem(MAINFRAME_MENU_ID_TIMER_SPEED_4X, _("&4x speed"), wxEmptyString)->Check(ActiveSettings::GetTimerShiftFactor() == 1);
@ -2174,12 +2173,12 @@ void MainWindow::RecreateMenu()
timerSpeedMenu->AppendRadioItem(MAINFRAME_MENU_ID_TIMER_SPEED_0125X, _("&0.125x speed"), wxEmptyString)->Check(ActiveSettings::GetTimerShiftFactor() == 6);
// cpu submenu
wxMenu* cpuMenu = new wxMenu;
wxMenu* cpuMenu = new wxMenu();
cpuMenu->AppendSubMenu(timerSpeedMenu, _("&Timer speed"));
m_menuBar->Append(cpuMenu, _("&CPU"));
// nfc submenu
wxMenu* nfcMenu = new wxMenu;
wxMenu* nfcMenu = new wxMenu();
m_nfcMenu = nfcMenu;
nfcMenu->Append(MAINFRAME_MENU_ID_NFC_TOUCH_NFC_FILE, _("&Scan NFC tag from file"))->Enable(false);
m_menuBar->Append(nfcMenu, _("&NFC"));
@ -2216,7 +2215,7 @@ void MainWindow::RecreateMenu()
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_SHADERS, _("&Shaders"), wxEmptyString)->Check(ActiveSettings::DumpShadersEnabled());
debugDumpMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_DUMP_CURL_REQUESTS, _("&nlibcurl HTTP/HTTPS requests"), wxEmptyString);
// debug submenu
wxMenu* debugMenu = new wxMenu;
wxMenu* debugMenu = new wxMenu();
m_debugMenu = debugMenu;
debugMenu->AppendSubMenu(debugLoggingMenu, _("&Logging"));
debugMenu->AppendSubMenu(debugDumpMenu, _("&Dump"));
@ -2251,7 +2250,7 @@ void MainWindow::RecreateMenu()
m_menuBar->Append(debugMenu, _("&Debug"));
// help menu
wxMenu* helpMenu = new wxMenu;
wxMenu* helpMenu = new wxMenu();
//helpMenu->Append(MAINFRAME_MENU_ID_HELP_WEB, wxT("&Visit website"));
//helpMenu->AppendSeparator();
m_check_update_menu = helpMenu->Append(MAINFRAME_MENU_ID_HELP_UPDATE, _("&Check for updates"));
@ -2271,8 +2270,8 @@ void MainWindow::RecreateMenu()
m_memorySearcherMenuItem->Enable(true);
m_nfcMenu->Enable(MAINFRAME_MENU_ID_NFC_TOUCH_NFC_FILE, true);
// disable OpenGL logging (currently cant be toggled after OpenGL backend is initialized)
// these options cant be toggled after the renderer backend is initialized:
m_loggingSubmenu->Enable(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::OpenGLLogging), false);
m_loggingSubmenu->Enable(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::VulkanValidation), false);
@ -2343,31 +2342,9 @@ void MainWindow::RestoreSettingsAfterGameExited()
void MainWindow::UpdateSettingsAfterGameLaunch()
{
m_update_available = {};
//m_game_launched = true;
RecreateMenu();
}
std::string MainWindow::GetRegionString(uint32 region) const
{
switch (region)
{
case 0x1:
return "JPN";
case 0x2:
return "USA";
case 0x4:
return "EUR";
case 0x10:
return "CHN";
case 0x20:
return "KOR";
case 0x40:
return "TWN";
default:
return std::to_string(region);
}
}
void MainWindow::OnGraphicWindowClose(wxCloseEvent& event)
{
m_graphic_pack_window->Destroy();
@ -2378,7 +2355,6 @@ void MainWindow::OnGraphicWindowOpen(wxTitleIdEvent& event)
{
if (m_graphic_pack_window)
return;
m_graphic_pack_window = new GraphicPacksWindow2(this, event.GetTitleId());
m_graphic_pack_window->Bind(wxEVT_CLOSE_WINDOW, &MainWindow::OnGraphicWindowClose, this);
m_graphic_pack_window->Show(true);
@ -2395,3 +2371,20 @@ void MainWindow::RequestLaunchGame(fs::path filePath, wxLaunchGameEvent::INITIAT
wxLaunchGameEvent evt(filePath, initiatedBy);
wxPostEvent(g_mainFrame, evt);
}
void MainWindow::OnRequestRecreateCanvas(wxCommandEvent& event)
{
CounterSemaphore* sem = (CounterSemaphore*)event.GetClientData();
DestroyCanvas();
CreateCanvas();
sem->increment();
}
void MainWindow::CafeRecreateCanvas()
{
CounterSemaphore sem;
auto* evt = new wxCommandEvent(wxEVT_REQUEST_RECREATE_CANVAS);
evt->SetClientData((void*)&sem);
wxQueueEvent(g_mainFrame, evt);
sem.decrementWithWait();
}