mirror of
https://github.com/stenzek/duckstation.git
synced 2025-07-21 17:40:16 +00:00
FullscreenUI: Add native cover download
This commit is contained in:
parent
a9862461f3
commit
3453c897d1
@ -33,6 +33,7 @@
|
|||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
|
#include "common/progress_callback.h"
|
||||||
#include "common/small_string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
@ -330,6 +331,7 @@ static void DrawAchievementsSettingsHeader(SettingsInterface* bsi, std::unique_l
|
|||||||
static void DrawAchievementsLoginWindow();
|
static void DrawAchievementsLoginWindow();
|
||||||
static void DrawAdvancedSettingsPage();
|
static void DrawAdvancedSettingsPage();
|
||||||
static void DrawPatchesOrCheatsSettingsPage(bool cheats);
|
static void DrawPatchesOrCheatsSettingsPage(bool cheats);
|
||||||
|
static void DrawCoverDownloaderWindow();
|
||||||
|
|
||||||
static bool ShouldShowAdvancedSettings();
|
static bool ShouldShowAdvancedSettings();
|
||||||
static bool IsEditingGameSettings(SettingsInterface* bsi);
|
static bool IsEditingGameSettings(SettingsInterface* bsi);
|
||||||
@ -497,6 +499,7 @@ static constexpr std::array s_theme_values = {"", "Dark", "Light
|
|||||||
static constexpr std::string_view RESUME_STATE_SELECTOR_DIALOG_NAME = "##resume_state_selector";
|
static constexpr std::string_view RESUME_STATE_SELECTOR_DIALOG_NAME = "##resume_state_selector";
|
||||||
static constexpr std::string_view ABOUT_DIALOG_NAME = "##about_duckstation";
|
static constexpr std::string_view ABOUT_DIALOG_NAME = "##about_duckstation";
|
||||||
static constexpr std::string_view ACHIEVEMENTS_LOGIN_DIALOG_NAME = "##achievements_login";
|
static constexpr std::string_view ACHIEVEMENTS_LOGIN_DIALOG_NAME = "##achievements_login";
|
||||||
|
static constexpr std::string_view COVER_DOWNLOADER_DIALOG_NAME = "##cover_downloader";
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// State
|
// State
|
||||||
@ -1329,6 +1332,8 @@ void FullscreenUI::Render()
|
|||||||
DrawAboutWindow();
|
DrawAboutWindow();
|
||||||
else if (IsFixedPopupDialogOpen(RESUME_STATE_SELECTOR_DIALOG_NAME))
|
else if (IsFixedPopupDialogOpen(RESUME_STATE_SELECTOR_DIALOG_NAME))
|
||||||
DrawResumeStateSelector();
|
DrawResumeStateSelector();
|
||||||
|
else if (IsFixedPopupDialogOpen(COVER_DOWNLOADER_DIALOG_NAME))
|
||||||
|
DrawCoverDownloaderWindow();
|
||||||
|
|
||||||
s_state.input_binding_dialog.Draw();
|
s_state.input_binding_dialog.Draw();
|
||||||
|
|
||||||
@ -8758,7 +8763,7 @@ void FullscreenUI::DrawGameListSettingsPage()
|
|||||||
if (MenuButton(FSUI_ICONVSTR(ICON_FA_DOWNLOAD, "Download Covers"),
|
if (MenuButton(FSUI_ICONVSTR(ICON_FA_DOWNLOAD, "Download Covers"),
|
||||||
FSUI_VSTR("Downloads covers from a user-specified URL template.")))
|
FSUI_VSTR("Downloads covers from a user-specified URL template.")))
|
||||||
{
|
{
|
||||||
Host::OnCoverDownloaderOpenRequested();
|
OpenFixedPopupDialog(COVER_DOWNLOADER_DIALOG_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8779,6 +8784,94 @@ void FullscreenUI::DrawGameListSettingsPage()
|
|||||||
EndMenuButtons();
|
EndMenuButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FullscreenUI::DrawCoverDownloaderWindow()
|
||||||
|
{
|
||||||
|
static char template_urls[512];
|
||||||
|
static bool use_serial_names;
|
||||||
|
|
||||||
|
if (!BeginFixedPopupDialog(LayoutScale(LAYOUT_LARGE_POPUP_PADDING), LayoutScale(LAYOUT_LARGE_POPUP_ROUNDING),
|
||||||
|
LayoutScale(1000.0f, 0.0f)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f));
|
||||||
|
ImGui::PushFont(UIStyle.Font, UIStyle.MediumLargeFontSize, UIStyle.NormalFontWeight);
|
||||||
|
|
||||||
|
ImGui::TextWrapped(
|
||||||
|
"%s",
|
||||||
|
FSUI_CSTR("DuckStation can automatically download covers for games which do not currently have a cover set. We "
|
||||||
|
"do not host any cover images, the user must provide their own source for images."));
|
||||||
|
ImGui::NewLine();
|
||||||
|
ImGui::TextWrapped("%s",
|
||||||
|
FSUI_CSTR("In the form below, specify the URLs to download covers from, with one template URL "
|
||||||
|
"per line. The following variables are available:"));
|
||||||
|
ImGui::NewLine();
|
||||||
|
ImGui::TextWrapped("%s", FSUI_CSTR("${title}: Title of the game.\n${filetitle}: Name component of the game's "
|
||||||
|
"filename.\n${serial}: Serial of the game."));
|
||||||
|
ImGui::NewLine();
|
||||||
|
ImGui::TextWrapped("%s", FSUI_CSTR("Example: https://www.example-not-a-real-domain.com/covers/${serial}.jpg"));
|
||||||
|
ImGui::NewLine();
|
||||||
|
|
||||||
|
ImGui::InputTextMultiline("##templates", template_urls, sizeof(template_urls),
|
||||||
|
ImVec2(ImGui::GetCurrentWindow()->WorkRect.GetWidth(), LayoutScale(175.0f)));
|
||||||
|
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + LayoutScale(5.0f));
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(2.0f, 2.0f));
|
||||||
|
ImGui::Checkbox(FSUI_CSTR("Save as Serial File Names"), &use_serial_names);
|
||||||
|
ImGui::PopStyleVar(1);
|
||||||
|
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + LayoutScale(10.0f));
|
||||||
|
|
||||||
|
const bool download_enabled = (std::strlen(template_urls) > 0);
|
||||||
|
|
||||||
|
BeginHorizontalMenuButtons(2, 200.0f);
|
||||||
|
|
||||||
|
if (HorizontalMenuButton(FSUI_ICONSTR(ICON_FA_DOWNLOAD, "Start Download"), download_enabled))
|
||||||
|
{
|
||||||
|
// TODO: Remove release once using move_only_function
|
||||||
|
std::unique_ptr<ProgressCallback> progress =
|
||||||
|
ImGuiFullscreen::OpenModalProgressDialog(FSUI_STR("Cover Downloader"), 1000.0f);
|
||||||
|
System::QueueAsyncTask([progress = progress.release(), urls = StringUtil::SplitNewString(template_urls, '\n'),
|
||||||
|
use_serial_names = use_serial_names]() {
|
||||||
|
GameList::DownloadCovers(
|
||||||
|
urls, use_serial_names, progress, [](const GameList::Entry* entry, std::string save_path) {
|
||||||
|
// cache the cover path on our side once it's saved
|
||||||
|
Host::RunOnCPUThread([path = entry->path, save_path = std::move(save_path)]() mutable {
|
||||||
|
GPUThread::RunOnThread([path = std::move(path), save_path = std::move(save_path)]() mutable {
|
||||||
|
s_state.cover_image_map[std::move(path)] = std::move(save_path);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// close the parent window if we weren't cancelled
|
||||||
|
if (!progress->IsCancelled())
|
||||||
|
{
|
||||||
|
Host::RunOnCPUThread([]() {
|
||||||
|
GPUThread::RunOnThread([]() {
|
||||||
|
if (IsFixedPopupDialogOpen(COVER_DOWNLOADER_DIALOG_NAME))
|
||||||
|
CloseFixedPopupDialog();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete progress;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HorizontalMenuButton(FSUI_ICONSTR(ICON_FA_XMARK, "Close")))
|
||||||
|
CloseFixedPopupDialog();
|
||||||
|
|
||||||
|
EndHorizontalMenuButtons();
|
||||||
|
|
||||||
|
ImGui::PopFont();
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
|
||||||
|
EndFixedPopupDialog();
|
||||||
|
}
|
||||||
|
|
||||||
void FullscreenUI::SwitchToGameList()
|
void FullscreenUI::SwitchToGameList()
|
||||||
{
|
{
|
||||||
s_state.game_list_view =
|
s_state.game_list_view =
|
||||||
@ -9263,6 +9356,7 @@ void FullscreenUI::CloseLoadingScreen()
|
|||||||
#if 0
|
#if 0
|
||||||
// TRANSLATION-STRING-AREA-BEGIN
|
// TRANSLATION-STRING-AREA-BEGIN
|
||||||
TRANSLATE_NOOP("FullscreenUI", " (%u MB on disk)");
|
TRANSLATE_NOOP("FullscreenUI", " (%u MB on disk)");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "${title}: Title of the game.\n${filetitle}: Name component of the game's filename.\n${serial}: Serial of the game.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "%.1f ms");
|
TRANSLATE_NOOP("FullscreenUI", "%.1f ms");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "%.2f Seconds");
|
TRANSLATE_NOOP("FullscreenUI", "%.2f Seconds");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "%d Frames");
|
TRANSLATE_NOOP("FullscreenUI", "%d Frames");
|
||||||
@ -9448,6 +9542,7 @@ TRANSLATE_NOOP("FullscreenUI", "Copies the global controller configuration to th
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Copy Global Settings");
|
TRANSLATE_NOOP("FullscreenUI", "Copy Global Settings");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Copy Settings");
|
TRANSLATE_NOOP("FullscreenUI", "Copy Settings");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Could not find any CD/DVD-ROM devices. Please ensure you have a drive connected and sufficient permissions to access it.");
|
TRANSLATE_NOOP("FullscreenUI", "Could not find any CD/DVD-ROM devices. Please ensure you have a drive connected and sufficient permissions to access it.");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Cover Downloader");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Cover Settings");
|
TRANSLATE_NOOP("FullscreenUI", "Cover Settings");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Cover set.");
|
TRANSLATE_NOOP("FullscreenUI", "Cover set.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Covers Directory");
|
TRANSLATE_NOOP("FullscreenUI", "Covers Directory");
|
||||||
@ -9518,6 +9613,7 @@ TRANSLATE_NOOP("FullscreenUI", "Downsampling");
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Downsampling Display Scale");
|
TRANSLATE_NOOP("FullscreenUI", "Downsampling Display Scale");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Draws a border around the currently-selected item for readability.");
|
TRANSLATE_NOOP("FullscreenUI", "Draws a border around the currently-selected item for readability.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Duck icon by icons8 (https://icons8.com/icon/74847/platforms.undefined.short-title)");
|
TRANSLATE_NOOP("FullscreenUI", "Duck icon by icons8 (https://icons8.com/icon/74847/platforms.undefined.short-title)");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "DuckStation can automatically download covers for games which do not currently have a cover set. We do not host any cover images, the user must provide their own source for images.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "DuckStation is a free simulator/emulator of the Sony PlayStation(TM) console, focusing on playability, speed, and long-term maintainability.");
|
TRANSLATE_NOOP("FullscreenUI", "DuckStation is a free simulator/emulator of the Sony PlayStation(TM) console, focusing on playability, speed, and long-term maintainability.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Dump Replaced Textures");
|
TRANSLATE_NOOP("FullscreenUI", "Dump Replaced Textures");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Dumps textures that have replacements already loaded.");
|
TRANSLATE_NOOP("FullscreenUI", "Dumps textures that have replacements already loaded.");
|
||||||
@ -9567,6 +9663,7 @@ TRANSLATE_NOOP("FullscreenUI", "Ensures every frame generated is displayed for o
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Enter Value");
|
TRANSLATE_NOOP("FullscreenUI", "Enter Value");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Enter the name of the controller preset you wish to create.");
|
TRANSLATE_NOOP("FullscreenUI", "Enter the name of the controller preset you wish to create.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Error");
|
TRANSLATE_NOOP("FullscreenUI", "Error");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Example: https://www.example-not-a-real-domain.com/covers/${serial}.jpg");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Execution Mode");
|
TRANSLATE_NOOP("FullscreenUI", "Execution Mode");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Exit");
|
TRANSLATE_NOOP("FullscreenUI", "Exit");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Exit And Save State");
|
TRANSLATE_NOOP("FullscreenUI", "Exit And Save State");
|
||||||
@ -9640,6 +9737,7 @@ TRANSLATE_NOOP("FullscreenUI", "If enabled, the display will be blended with the
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "If enabled, the transparency of the overlay image will be applied.");
|
TRANSLATE_NOOP("FullscreenUI", "If enabled, the transparency of the overlay image will be applied.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "If not enabled, the current post processing chain will be ignored.");
|
TRANSLATE_NOOP("FullscreenUI", "If not enabled, the current post processing chain will be ignored.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Image Path");
|
TRANSLATE_NOOP("FullscreenUI", "Image Path");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "In the form below, specify the URLs to download covers from, with one template URL per line. The following variables are available:");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Includes the elapsed time since the application start in file logs.");
|
TRANSLATE_NOOP("FullscreenUI", "Includes the elapsed time since the application start in file logs.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Includes the elapsed time since the application start in window and console logs.");
|
TRANSLATE_NOOP("FullscreenUI", "Includes the elapsed time since the application start in window and console logs.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Increases the field of view from 4:3 to the chosen display aspect ratio in 3D games.");
|
TRANSLATE_NOOP("FullscreenUI", "Increases the field of view from 4:3 to the chosen display aspect ratio in 3D games.");
|
||||||
@ -9837,6 +9935,7 @@ TRANSLATE_NOOP("FullscreenUI", "Save Screenshot");
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Save State");
|
TRANSLATE_NOOP("FullscreenUI", "Save State");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Save State Compression");
|
TRANSLATE_NOOP("FullscreenUI", "Save State Compression");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Save State On Shutdown");
|
TRANSLATE_NOOP("FullscreenUI", "Save State On Shutdown");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Save as Serial File Names");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Saved {:%c}");
|
TRANSLATE_NOOP("FullscreenUI", "Saved {:%c}");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Saves state periodically so you can rewind any mistakes while playing.");
|
TRANSLATE_NOOP("FullscreenUI", "Saves state periodically so you can rewind any mistakes while playing.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Scaled Interlacing");
|
TRANSLATE_NOOP("FullscreenUI", "Scaled Interlacing");
|
||||||
@ -9944,6 +10043,7 @@ TRANSLATE_NOOP("FullscreenUI", "Sprite Texture Filtering");
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Stage {}: {}");
|
TRANSLATE_NOOP("FullscreenUI", "Stage {}: {}");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Start BIOS");
|
TRANSLATE_NOOP("FullscreenUI", "Start BIOS");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Start Disc");
|
TRANSLATE_NOOP("FullscreenUI", "Start Disc");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Start Download");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Start File");
|
TRANSLATE_NOOP("FullscreenUI", "Start File");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Start Fullscreen");
|
TRANSLATE_NOOP("FullscreenUI", "Start Fullscreen");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Start Game");
|
TRANSLATE_NOOP("FullscreenUI", "Start Game");
|
||||||
|
@ -155,9 +155,6 @@ void RequestExitApplication(bool allow_confirm);
|
|||||||
/// Requests Big Picture mode to be shut down, returning to the desktop interface.
|
/// Requests Big Picture mode to be shut down, returning to the desktop interface.
|
||||||
void RequestExitBigPicture();
|
void RequestExitBigPicture();
|
||||||
|
|
||||||
/// Requests the cover downloader be opened.
|
|
||||||
void OnCoverDownloaderOpenRequested();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace Host
|
} // namespace Host
|
||||||
|
@ -1738,7 +1738,7 @@ bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, boo
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress->FormatStatusText("Downloading cover for {}...", entry->title);
|
progress->SetStatusText(entry->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we could actually do a few in parallel here...
|
// we could actually do a few in parallel here...
|
||||||
|
@ -1139,11 +1139,6 @@ void Host::OnRAIntegrationMenuChanged()
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Host::OnCoverDownloaderOpenRequested()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::SetMouseMode(bool relative, bool hide_cursor)
|
void Host::SetMouseMode(bool relative, bool hide_cursor)
|
||||||
{
|
{
|
||||||
// noop
|
// noop
|
||||||
|
@ -1681,11 +1681,6 @@ void Host::OnAchievementsAllProgressRefreshed()
|
|||||||
emit g_emu_thread->achievementsAllProgressRefreshed();
|
emit g_emu_thread->achievementsAllProgressRefreshed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnCoverDownloaderOpenRequested()
|
|
||||||
{
|
|
||||||
emit g_emu_thread->onCoverDownloaderOpenRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Host::ShouldPreferHostFileSelector()
|
bool Host::ShouldPreferHostFileSelector()
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -609,11 +609,6 @@ void Host::OnRAIntegrationMenuChanged()
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Host::OnCoverDownloaderOpenRequested()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Host::GetDefaultFullscreenUITheme()
|
const char* Host::GetDefaultFullscreenUITheme()
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user