From fe3c7926f77bbe2c8593220fc0d900c727ce391c Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 7 Oct 2020 14:20:35 +0200 Subject: [PATCH] Qt: add custom game icons This shouldn't interfere with emulation as replacing actual files would --- rpcs3/Emu/System.cpp | 16 +++++-- rpcs3/rpcs3qt/game_list_frame.cpp | 19 +++++--- rpcs3/rpcs3qt/game_list_frame.h | 2 +- rpcs3/rpcs3qt/qt_utils.cpp | 75 ++++++++++++++++++------------- 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index d259edad58..70e097f8a7 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -451,9 +451,17 @@ const bool Emulator::SetUsr(const std::string& user) const std::string Emulator::GetBackgroundPicturePath() const { - std::string path = m_sfo_dir + "/PIC1.PNG"; + // Try to find a custom icon first + std::string path = fs::get_config_dir() + "/Icons/game_icons/" + Emu.GetTitleID() + "/PIC1.PNG"; - if (!fs::exists(path)) + if (fs::is_file(path)) + { + return path; + } + + path = m_sfo_dir + "/PIC1.PNG"; + + if (!fs::is_file(path)) { const std::string disc_dir = vfs::get("/dev_bdvd/PS3_GAME"); @@ -467,12 +475,12 @@ const std::string Emulator::GetBackgroundPicturePath() const // Fallback to PIC1.PNG in disc dir path = disc_dir + "/PIC1.PNG"; - if (!fs::exists(path)) + if (!fs::is_file(path)) { // Fallback to ICON0.PNG in update dir path = m_sfo_dir + "/ICON0.PNG"; - if (!fs::exists(path)) + if (!fs::is_file(path)) { // Fallback to ICON0.PNG in disc dir path = disc_dir + "/ICON0.PNG"; diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index 58a495d857..3d97ff2896 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -555,7 +555,6 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after) GameInfo game; game.path = dir; - game.icon_path = sfo_dir + "/ICON0.PNG"; game.serial = std::string(psf::get_string(psf, "TITLE_ID", "")); game.name = std::string(psf::get_string(psf, "TITLE", cat_unknown_localized)); game.app_ver = std::string(psf::get_string(psf, "APP_VER", cat_unknown_localized)); @@ -567,6 +566,12 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after) game.sound_format = psf::get_integer(psf, "SOUND_FORMAT", 0); game.bootable = psf::get_integer(psf, "BOOTABLE", 0); game.attr = psf::get_integer(psf, "ATTRIBUTE", 0); + game.icon_path = fs::get_config_dir() + "/Icons/game_icons/" + game.serial + "/ICON0.PNG"; + + if (!fs::is_file(game.icon_path)) + { + game.icon_path = sfo_dir + "/ICON0.PNG"; + } mutex_cat.lock(); @@ -1900,7 +1905,7 @@ void game_list_frame::PopulateGameList() { int selected_row = -1; - std::string selected_item = CurrentSelectionIconPath(); + std::string selected_item = CurrentSelectionPath(); m_game_list->clearSelection(); m_game_list->clearContents(); @@ -2011,7 +2016,7 @@ void game_list_frame::PopulateGameList() m_game_list->setItem(row, gui::column_playtime, new custom_table_widget_item(localized.GetVerboseTimeByMs(elapsed_ms), Qt::UserRole, elapsed_ms)); m_game_list->setItem(row, gui::column_compat, compat_item); - if (selected_item == game->info.icon_path) + if (selected_item == game->info.path + game->info.icon_path) { selected_row = row; } @@ -2028,7 +2033,7 @@ void game_list_frame::PopulateGameGrid(int maxCols, const QSize& image_size, con int r = 0; int c = 0; - const std::string selected_item = CurrentSelectionIconPath(); + const std::string selected_item = CurrentSelectionPath(); m_game_grid->deleteLater(); @@ -2087,7 +2092,7 @@ void game_list_frame::PopulateGameGrid(int maxCols, const QSize& image_size, con m_game_grid->item(r, c)->setToolTip(tr("%0 [%1]").arg(title).arg(serial)); } - if (selected_item == app->info.icon_path) + if (selected_item == app->info.path + app->info.icon_path) { m_game_grid->setCurrentCell(r, c); } @@ -2128,7 +2133,7 @@ bool game_list_frame::SearchMatchesApp(const QString& name, const QString& seria return true; } -std::string game_list_frame::CurrentSelectionIconPath() +std::string game_list_frame::CurrentSelectionPath() { std::string selection; @@ -2158,7 +2163,7 @@ std::string game_list_frame::CurrentSelectionIconPath() auto game = var.value(); if (game) { - selection = game->info.icon_path; + selection = game->info.path + game->info.icon_path; } } } diff --git a/rpcs3/rpcs3qt/game_list_frame.h b/rpcs3/rpcs3qt/game_list_frame.h index c6f0b8e061..16292ce9e9 100644 --- a/rpcs3/rpcs3qt/game_list_frame.h +++ b/rpcs3/rpcs3qt/game_list_frame.h @@ -121,7 +121,7 @@ private: QString GetLastPlayedBySerial(const QString& serial); std::string GetCacheDirBySerial(const std::string& serial); std::string GetDataDirBySerial(const std::string& serial); - std::string CurrentSelectionIconPath(); + std::string CurrentSelectionPath(); std::string GetStringFromU32(const u32& key, const std::map& map, bool combined = false); game_info GetGameInfoByMode(const QTableWidgetItem* item); diff --git a/rpcs3/rpcs3qt/qt_utils.cpp b/rpcs3/rpcs3qt/qt_utils.cpp index 7df4866c61..2b1bf02df9 100644 --- a/rpcs3/rpcs3qt/qt_utils.cpp +++ b/rpcs3/rpcs3qt/qt_utils.cpp @@ -244,43 +244,58 @@ namespace gui // Loads the app icon from path and embeds it centered into an empty square icon QIcon get_app_icon_from_path(const std::string& path, const std::string& title_id) { - // get Icon for the gs_frame from path. this handles presumably all possible use cases - const QString qpath = qstr(path); - const std::string path_list[] = { path, sstr(qpath.section("/", 0, -2, QString::SectionIncludeTrailingSep)), - sstr(qpath.section("/", 0, -3, QString::SectionIncludeTrailingSep)) }; + // Try to find custom icon first + std::string icon_path = fs::get_config_dir() + "/Icons/game_icons/" + title_id + "/ICON0.PNG"; + bool found_file = fs::is_file(icon_path); - for (const std::string& pth : path_list) + if (!found_file) { - if (!fs::is_dir(pth)) + // Get Icon for the gs_frame from path. this handles presumably all possible use cases + const QString qpath = qstr(path); + const std::string path_list[] = { path, sstr(qpath.section("/", 0, -2, QString::SectionIncludeTrailingSep)), + sstr(qpath.section("/", 0, -3, QString::SectionIncludeTrailingSep)) }; + + for (const std::string& pth : path_list) { - continue; - } + if (!fs::is_dir(pth)) + { + continue; + } - const std::string sfo_dir = Emulator::GetSfoDirFromGamePath(pth, Emu.GetUsr(), title_id); - const std::string ico = sfo_dir + "/ICON0.PNG"; - if (fs::is_file(ico)) - { - // load the image from path. It will most likely be a rectangle - QImage source = QImage(qstr(ico)); - const int edge_max = std::max(source.width(), source.height()); + const std::string sfo_dir = Emulator::GetSfoDirFromGamePath(pth, Emu.GetUsr(), title_id); + icon_path = sfo_dir + "/ICON0.PNG"; + found_file = fs::is_file(icon_path); - // create a new transparent image with square size and same format as source (maybe handle other formats than RGB32 as well?) - QImage::Format format = source.format() == QImage::Format_RGB32 ? QImage::Format_ARGB32 : source.format(); - QImage dest = QImage(edge_max, edge_max, format); - dest.fill(Qt::transparent); - - // get the location to draw the source image centered within the dest image. - const QPoint dest_pos = source.width() > source.height() ? QPoint(0, (source.width() - source.height()) / 2) : QPoint((source.height() - source.width()) / 2, 0); - - // Paint the source into/over the dest - QPainter painter(&dest); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.drawImage(dest_pos, source); - painter.end(); - - return QIcon(QPixmap::fromImage(dest)); + if (found_file) + { + break; + } } } + + if (found_file) + { + // load the image from path. It will most likely be a rectangle + QImage source = QImage(qstr(icon_path)); + const int edge_max = std::max(source.width(), source.height()); + + // create a new transparent image with square size and same format as source (maybe handle other formats than RGB32 as well?) + QImage::Format format = source.format() == QImage::Format_RGB32 ? QImage::Format_ARGB32 : source.format(); + QImage dest = QImage(edge_max, edge_max, format); + dest.fill(Qt::transparent); + + // get the location to draw the source image centered within the dest image. + const QPoint dest_pos = source.width() > source.height() ? QPoint(0, (source.width() - source.height()) / 2) : QPoint((source.height() - source.width()) / 2, 0); + + // Paint the source into/over the dest + QPainter painter(&dest); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.drawImage(dest_pos, source); + painter.end(); + + return QIcon(QPixmap::fromImage(dest)); + } + // if nothing was found reset the icon to default return QApplication::windowIcon(); }