diff --git a/README.md b/README.md index 3a82000b6..35da8bf0c 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ To download: You will need a device with armv7 (32-bit ARM), AArch64 (64-bit ARM), or x86_64 (64-bit x86). 64-bit is preferred, the requirements are higher for 32-bit, you'll probably want at least a 1.5GHz CPU. Download from Google Play: https://play.google.com/store/apps/details?id=com.github.stenzek.duckstation + APK and Beta Downloads: https://www.duckstation.org/android/ **No support is provided for the Android app**, it is free and your expectations should be in line with that. Please **do not** email me about issues about it, or ask for help, you will be ignored. @@ -206,9 +207,9 @@ If you wish to use a "portable" build, where the user directory is the same as w in the same directory as the DuckStation executable. ## Bindings for Qt frontend -Your keyboard or game controller can be used to simulate a variety of PlayStation controllers. Controller input is supported through DInput, XInput, and SDL backends and can be changed through `Settings -> General Settings`. +Your keyboard or game controller can be used to simulate a variety of PlayStation controllers. Controller input is supported through DInput, XInput, and SDL backends and can be changed through `Settings -> Controllers`. -To bind your input device, go to `Settings -> Controllers`. Each of the buttons/axes for the simulated controller will be listed, alongside the corresponding key/button on your device that it is currently bound to. To rebind, click the box next to the button/axis name, and press the key or button on your input device that you wish to bind to. When binding rumble, simply press any button on the controller you wish to send rumble to. +To bind your input device, go to `Settings -> Controllers`, and select the virtual controller you want to map. Automatic mapping handles the majority of ocntrollers. However, if you need to manually bind a controller, click the box below the button/axis name, and press the key or button on your input device that you wish to bind to. ## SDL Game Controller Database DuckStation releases ship with a database of game controller mappings for the SDL controller backend, courtesy of https://github.com/mdqinc/SDL_GameControllerDB. The included `gamecontrollerdb.txt` file can be found in the `resources` subdirectory of the DuckStation program directory. @@ -216,6 +217,9 @@ DuckStation releases ship with a database of game controller mappings for the SD If you are experiencing issues binding your controller with the SDL controller backend, you may need to add a custom mapping to the database file. Make a copy of `gamecontrollerdb.txt` and place it in your [user directory](#user-directories) (or directly in the program directory, if running in portable mode) and then follow the instructions in the [SDL_GameControllerDB repository](https://github.com/mdqinc/SDL_GameControllerDB) for creating a new mapping. Add this mapping to the new copy of `gamecontrollerdb.txt` and your controller should then be recognized properly. ## Default bindings + +Bindings for controllers and hotkeys can be changed in `Settings -> Controllers`. + Controller 1: - **Left Stick:** W/A/S/D - **Right Stick:** T/F/G/H @@ -229,6 +233,11 @@ Controller 1: Hotkeys: - **Escape:** Open Pause Menu + - **F1:** Load State + - **F2:** Save State + - **F3:** Select Previous Save State + - **F4:** Select Next Save State + - **F10:** Save Screenshot - **F11:** Toggle Fullscreen - **Tab:** Temporarily Disable Speed Limiter - **Space:** Pause/Resume Emulation diff --git a/src/core/game_database.cpp b/src/core/game_database.cpp index 45fd40ebe..eac5a2ea7 100644 --- a/src/core/game_database.cpp +++ b/src/core/game_database.cpp @@ -543,7 +543,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes } else if (settings.gpu_pgxp_enable && settings.gpu_pgxp_vertex_cache) { - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "gamedb_force_pgxp_vertex_cache", ICON_EMOJI_WARNING, TRANSLATE_STR( "GameDatabase", @@ -558,7 +558,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes #ifndef __ANDROID__ APPEND_MESSAGE(TRANSLATE_SV("GameDatabase", "PGXP CPU mode enabled.")); #else - Host::AddIconOSDMessage("gamedb_force_pgxp_cpu", ICON_EMOJI_WARNING, + Host::AddIconOSDWarning("gamedb_force_pgxp_cpu", ICON_EMOJI_WARNING, "This game requires PGXP CPU mode, which increases system requirements.\n" " If the game runs too slow, disable PGXP for this game.", Host::OSD_WARNING_DURATION); @@ -569,7 +569,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes } else if (settings.UsingPGXPCPUMode()) { - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "gamedb_force_pgxp_cpu", ICON_EMOJI_WARNING, TRANSLATE_STR("GameDatabase", "PGXP CPU mode is enabled, but it is not required for this game. This may cause rendering errors."), diff --git a/src/core/host.cpp b/src/core/host.cpp index 844e94ed2..b1d860cbe 100644 --- a/src/core/host.cpp +++ b/src/core/host.cpp @@ -315,8 +315,7 @@ bool Host::CreateGPUDevice(RenderAPI api, Error* error) return false; } - if (!ImGuiManager::Initialize(g_settings.display_osd_scale / 100.0f, g_settings.display_show_osd_messages, - &create_error)) + if (!ImGuiManager::Initialize(g_settings.display_osd_scale / 100.0f, &create_error)) { ERROR_LOG("Failed to initialize ImGuiManager: {}", create_error.GetDescription()); Error::SetStringFmt(error, "Failed to initialize ImGuiManager: {}", create_error.GetDescription()); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 0013bd7ca..e061844a2 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -305,7 +305,7 @@ void Settings::Load(SettingsInterface& si, SettingsInterface& controller_si) display_active_end_offset = static_cast(si.GetIntValue("Display", "ActiveEndOffset", 0)); display_line_start_offset = static_cast(si.GetIntValue("Display", "LineStartOffset", 0)); display_line_end_offset = static_cast(si.GetIntValue("Display", "LineEndOffset", 0)); - display_show_osd_messages = si.GetBoolValue("Display", "ShowOSDMessages", true); + ImGuiManager::SetShowOSDMessages(si.GetBoolValue("Display", "ShowOSDMessages", true)); display_show_fps = si.GetBoolValue("Display", "ShowFPS", false); display_show_speed = si.GetBoolValue("Display", "ShowSpeed", false); display_show_gpu_stats = si.GetBoolValue("Display", "ShowGPUStatistics", false); @@ -575,7 +575,7 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const si.GetIntValue("Display", "CustomAspectRatioDenominator", display_aspect_ratio_custom_denominator); if (!ignore_base) { - si.SetBoolValue("Display", "ShowOSDMessages", display_show_osd_messages); + si.SetBoolValue("Display", "ShowOSDMessages", ImGuiManager::IsShowingOSDMessages()); si.SetBoolValue("Display", "ShowFPS", display_show_fps); si.SetBoolValue("Display", "ShowSpeed", display_show_speed); si.SetBoolValue("Display", "ShowResolution", display_show_resolution); diff --git a/src/core/settings.h b/src/core/settings.h index 992e717cf..1624cba6c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -160,7 +160,6 @@ struct Settings bool display_disable_mailbox_presentation : 1 = true; bool display_force_4_3_for_24bit : 1 = false; bool display_24bit_chroma_smoothing : 1 = false; - bool display_show_osd_messages : 1 = true; bool display_show_fps : 1 = false; bool display_show_speed : 1 = false; bool display_show_gpu_stats : 1 = false; diff --git a/src/core/system.cpp b/src/core/system.cpp index ec8716e5f..4d12107b7 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1236,7 +1236,7 @@ void System::HandleHostGPUDeviceLost() std::memcpy(g_vram, vram_backup.data(), VRAM_SIZE); // First frame after reopening is definitely going to be trash, so skip it. - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "HostGPUDeviceLost", ICON_EMOJI_WARNING, TRANSLATE_STR("System", "Host GPU device encountered an error and has recovered. This may cause broken rendering."), Host::OSD_CRITICAL_ERROR_DURATION); @@ -1301,7 +1301,7 @@ LayeredSettingsInterface System::GetControllerSettingsLayers(std::unique_lockGetBoolValue("ControllerPorts", "UseGameSettingsForController", false)) @@ -1332,7 +1332,6 @@ void System::SetDefaultSettings(SettingsInterface& si) Settings temp; // we don't want to reset some things (e.g. OSD) - temp.display_show_osd_messages = g_settings.display_show_osd_messages; temp.display_show_fps = g_settings.display_show_fps; temp.display_show_speed = g_settings.display_show_speed; temp.display_show_gpu_stats = g_settings.display_show_gpu_stats; @@ -1940,7 +1939,8 @@ void System::DestroySystem() GDBServer::Shutdown(); #endif - Host::ClearOSDMessages(); + // TODO-GPU-THREAD: Needs to be called on GPU thread. + Host::ClearOSDMessages(true); PostProcessing::Shutdown(); @@ -2398,7 +2398,7 @@ bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di { WARNING_LOG("BIOS hash mismatch: System: {} | State: {}", BIOS::ImageInfo::GetHashString(s_bios_hash), BIOS::ImageInfo::GetHashString(bios_hash)); - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "StateBIOSMismatch", ICON_FA_EXCLAMATION_TRIANGLE, TRANSLATE_STR("System", "This save state was created with a different BIOS. This may cause stability issues."), Host::OSD_WARNING_DURATION); @@ -3934,7 +3934,7 @@ bool System::InsertMedia(const char* path) std::unique_ptr image = CDImage::Open(path, g_settings.cdrom_load_image_patches, &error); if (!image) { - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "DiscInserted", ICON_FA_COMPACT_DISC, fmt::format(TRANSLATE_FS("OSDMessage", "Failed to open disc image '{}': {}."), path, error.GetDescription()), Host::OSD_ERROR_DURATION); @@ -4474,8 +4474,6 @@ void System::CheckForSettingsChanges(const Settings& old_settings) { if (g_settings.display_osd_scale != old_settings.display_osd_scale) ImGuiManager::SetGlobalScale(g_settings.display_osd_scale / 100.0f); - if (g_settings.display_show_osd_messages != old_settings.display_show_osd_messages) - ImGuiManager::SetShowOSDMessages(g_settings.display_show_osd_messages); } bool controllers_updated = false; @@ -4601,6 +4599,8 @@ void System::WarnAboutUnsafeSettings() { append(ICON_EMOJI_WARNING, TRANSLATE_SV("System", "All enhancements are currently disabled.")); + if (ImGuiManager::IsShowingOSDMessages()) + { #define APPEND_SUBMESSAGE(msg) \ do \ { \ @@ -4609,49 +4609,50 @@ void System::WarnAboutUnsafeSettings() messages.append('\n'); \ } while (0) - if (g_settings.cpu_overclock_active) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Overclock disabled.")); - if (g_settings.enable_8mb_ram) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "8MB RAM disabled.")); - if (g_settings.enable_cheats) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Cheats disabled.")); - if (g_settings.gpu_resolution_scale != 1) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Resolution scale set to 1x.")); - if (g_settings.gpu_multisamples != 1) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Multisample anti-aliasing disabled.")); - if (g_settings.gpu_true_color) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "True color disabled.")); - if (g_settings.gpu_true_color && g_settings.gpu_debanding) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "True color debanding disabled.")); - if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest || - g_settings.gpu_sprite_texture_filter != GPUTextureFilter::Nearest) - { - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Texture filtering disabled.")); - } - if (g_settings.display_deinterlacing_mode == DisplayDeinterlacingMode::Progressive) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Interlaced rendering enabled.")); - if (g_settings.gpu_force_video_timing != ForceVideoTimingMode::Disabled) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Video timings set to default.")); - if (g_settings.gpu_widescreen_hack) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Widescreen rendering disabled.")); - if (g_settings.display_24bit_chroma_smoothing) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "FMV chroma smoothing disabled.")); - if (g_settings.cdrom_read_speedup != 1) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "CD-ROM read speedup disabled.")); - if (g_settings.cdrom_seek_speedup != 1) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "CD-ROM seek speedup disabled.")); - if (g_settings.cdrom_mute_cd_audio) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Mute CD-ROM audio disabled.")); - if (g_settings.texture_replacements.enable_vram_write_replacements) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "VRAM write texture replacements disabled.")); - if (g_settings.use_old_mdec_routines) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Use old MDEC routines disabled.")); - if (g_settings.pcdrv_enable) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "PCDrv disabled.")); - if (g_settings.bios_patch_fast_boot) - APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Fast boot disabled.")); + if (g_settings.cpu_overclock_active) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Overclock disabled.")); + if (g_settings.enable_8mb_ram) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "8MB RAM disabled.")); + if (g_settings.enable_cheats) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Cheats disabled.")); + if (g_settings.gpu_resolution_scale != 1) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Resolution scale set to 1x.")); + if (g_settings.gpu_multisamples != 1) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Multisample anti-aliasing disabled.")); + if (g_settings.gpu_true_color) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "True color disabled.")); + if (g_settings.gpu_true_color && g_settings.gpu_debanding) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "True color debanding disabled.")); + if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest || + g_settings.gpu_sprite_texture_filter != GPUTextureFilter::Nearest) + { + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Texture filtering disabled.")); + } + if (g_settings.display_deinterlacing_mode == DisplayDeinterlacingMode::Progressive) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Interlaced rendering enabled.")); + if (g_settings.gpu_force_video_timing != ForceVideoTimingMode::Disabled) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Video timings set to default.")); + if (g_settings.gpu_widescreen_hack) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Widescreen rendering disabled.")); + if (g_settings.display_24bit_chroma_smoothing) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "FMV chroma smoothing disabled.")); + if (g_settings.cdrom_read_speedup != 1) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "CD-ROM read speedup disabled.")); + if (g_settings.cdrom_seek_speedup != 1) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "CD-ROM seek speedup disabled.")); + if (g_settings.cdrom_mute_cd_audio) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Mute CD-ROM audio disabled.")); + if (g_settings.texture_replacements.enable_vram_write_replacements) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "VRAM write texture replacements disabled.")); + if (g_settings.use_old_mdec_routines) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Use old MDEC routines disabled.")); + if (g_settings.pcdrv_enable) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "PCDrv disabled.")); + if (g_settings.bios_patch_fast_boot) + APPEND_SUBMESSAGE(TRANSLATE_SV("System", "Fast boot disabled.")); #undef APPEND_SUBMESSAGE + } } if (!g_settings.apply_compatibility_settings) @@ -4666,11 +4667,11 @@ void System::WarnAboutUnsafeSettings() messages.pop_back(); LogUnsafeSettingsToConsole(messages); - Host::AddKeyedOSDMessage("performance_settings_warning", std::string(messages.view()), Host::OSD_WARNING_DURATION); + Host::AddKeyedOSDWarning("performance_settings_warning", std::string(messages.view()), Host::OSD_WARNING_DURATION); } else { - Host::RemoveKeyedOSDMessage("performance_settings_warning"); + Host::RemoveKeyedOSDWarning("performance_settings_warning"); } } @@ -5217,7 +5218,7 @@ bool System::StartMediaCapture(std::string path, bool capture_video, bool captur std::string(), &error)) { - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "MediaCapture", ICON_FA_EXCLAMATION_TRIANGLE, fmt::format(TRANSLATE_FS("System", "Failed to create media capture: {0}"), error.GetDescription()), Host::OSD_ERROR_DURATION); @@ -5256,7 +5257,7 @@ void System::StopMediaCapture() } else { - Host::AddIconOSDMessage( + Host::AddIconOSDWarning( "MediaCapture", ICON_FA_EXCLAMATION_TRIANGLE, fmt::format(TRANSLATE_FS("System", "Stopped {0}: {1}."), GetCaptureTypeForMessage(s_media_capture->IsCapturingVideo(), s_media_capture->IsCapturingAudio()), diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index b9b366d3e..a43b78728 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -383,7 +383,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* dialog->registerWidgetHelp( m_ui.stretchDisplayVertically, tr("Stretch Vertically"), tr("Unchecked"), tr("Prefers stretching the display vertically instead of horizontally, when applying the display aspect ratio.")); - dialog->registerWidgetHelp(m_ui.stretchDisplayVertically, tr("Automatically Resize Window"), tr("Unchecked"), + dialog->registerWidgetHelp(m_ui.automaticallyResizeWindow, tr("Automatically Resize Window"), tr("Unchecked"), tr("Automatically resizes the window to match the internal resolution. For high " "internal resolutions, this will create very large windows.")); #ifdef _WIN32 diff --git a/src/util/imgui_manager.cpp b/src/util/imgui_manager.cpp index f7718e1a8..1a78cbffb 100644 --- a/src/util/imgui_manager.cpp +++ b/src/util/imgui_manager.cpp @@ -56,6 +56,7 @@ struct OSDMessage float duration; float target_y; float last_y; + bool is_warning; }; } // namespace @@ -71,6 +72,9 @@ static bool AddImGuiFonts(bool fullscreen_fonts); static ImFont* AddTextFont(float size, bool full_glyph_range); static ImFont* AddFixedFont(float size); static bool AddIconFonts(float size); +static void AddOSDMessage(std::string key, std::string message, float duration, bool is_warning); +static void RemoveKeyedOSDMessage(std::string key, bool is_warning); +static void ClearOSDMessages(bool clear_warnings); static void AcquirePendingOSDMessages(Common::Timer::Value current_time); static void DrawOSDMessages(Common::Timer::Value current_time); static void CreateSoftwareCursorTextures(); @@ -203,6 +207,11 @@ void ImGuiManager::SetGlobalScale(float global_scale) s_scale_changed = true; } +bool ImGuiManager::IsShowingOSDMessages() +{ + return s_show_osd_messages; +} + void ImGuiManager::SetShowOSDMessages(bool enable) { if (s_show_osd_messages == enable) @@ -210,10 +219,10 @@ void ImGuiManager::SetShowOSDMessages(bool enable) s_show_osd_messages = enable; if (!enable) - Host::ClearOSDMessages(); + Host::ClearOSDMessages(false); } -bool ImGuiManager::Initialize(float global_scale, bool show_osd_messages, Error* error) +bool ImGuiManager::Initialize(float global_scale, Error* error) { if (!LoadFontData()) { @@ -224,7 +233,6 @@ bool ImGuiManager::Initialize(float global_scale, bool show_osd_messages, Error* s_global_prescale = global_scale; s_global_scale = std::max(g_gpu_device->GetWindowScale() * global_scale, 1.0f); s_scale_changed = false; - s_show_osd_messages = show_osd_messages; ImGui::CreateContext(); @@ -743,24 +751,19 @@ bool ImGuiManager::HasFullscreenFonts() return (s_medium_font && s_large_font); } -void Host::AddOSDMessage(std::string message, float duration /*= 2.0f*/) -{ - AddKeyedOSDMessage(std::string(), std::move(message), duration); -} - -void Host::AddKeyedOSDMessage(std::string key, std::string message, float duration /* = 2.0f */) +void ImGuiManager::AddOSDMessage(std::string key, std::string message, float duration, bool is_warning) { if (!key.empty()) INFO_LOG("OSD [{}]: {}", key, message); else INFO_LOG("OSD: {}", message); - if (!ImGuiManager::s_show_osd_messages) + if (!s_show_osd_messages && !is_warning) return; const Common::Timer::Value current_time = Common::Timer::GetCurrentValue(); - ImGuiManager::OSDMessage msg; + OSDMessage msg; msg.key = std::move(key); msg.text = std::move(message); msg.duration = duration; @@ -768,37 +771,60 @@ void Host::AddKeyedOSDMessage(std::string key, std::string message, float durati msg.move_time = current_time; msg.target_y = -1.0f; msg.last_y = -1.0f; + msg.is_warning = is_warning; - std::unique_lock lock(ImGuiManager::s_osd_messages_lock); - ImGuiManager::s_osd_posted_messages.push_back(std::move(msg)); + std::unique_lock lock(s_osd_messages_lock); + s_osd_posted_messages.push_back(std::move(msg)); } -void Host::AddIconOSDMessage(std::string key, const char* icon, std::string message, float duration /* = 2.0f */) +void ImGuiManager::RemoveKeyedOSDMessage(std::string key, bool is_warning) { - return AddKeyedOSDMessage(std::move(key), fmt::format("{} {}", icon, message), duration); -} - -void Host::RemoveKeyedOSDMessage(std::string key) -{ - if (!ImGuiManager::s_show_osd_messages) + if (!s_show_osd_messages && !is_warning) return; ImGuiManager::OSDMessage msg = {}; msg.key = std::move(key); msg.duration = 0.0f; + msg.is_warning = is_warning; - std::unique_lock lock(ImGuiManager::s_osd_messages_lock); - ImGuiManager::s_osd_posted_messages.push_back(std::move(msg)); + std::unique_lock lock(s_osd_messages_lock); + s_osd_posted_messages.push_back(std::move(msg)); } -void Host::ClearOSDMessages() +void ImGuiManager::ClearOSDMessages(bool clear_warnings) { { - std::unique_lock lock(ImGuiManager::s_osd_messages_lock); - ImGuiManager::s_osd_posted_messages.clear(); + std::unique_lock lock(s_osd_messages_lock); + if (clear_warnings) + { + s_osd_posted_messages.clear(); + } + else + { + for (auto iter = s_osd_posted_messages.begin(); iter != s_osd_posted_messages.end();) + { + if (!iter->is_warning) + iter = s_osd_posted_messages.erase(iter); + else + ++iter; + } + } } - ImGuiManager::s_osd_active_messages.clear(); + if (clear_warnings) + { + s_osd_active_messages.clear(); + } + else + { + for (auto iter = s_osd_active_messages.begin(); iter != s_osd_active_messages.end();) + { + if (!iter->is_warning) + s_osd_active_messages.erase(iter); + else + ++iter; + } + } } void ImGuiManager::AcquirePendingOSDMessages(Common::Timer::Value current_time) @@ -940,6 +966,46 @@ void ImGuiManager::RenderOSDMessages() DrawOSDMessages(current_time); } +void Host::AddOSDMessage(std::string message, float duration /*= 2.0f*/) +{ + ImGuiManager::AddOSDMessage(std::string(), std::move(message), duration, false); +} + +void Host::AddKeyedOSDMessage(std::string key, std::string message, float duration /* = 2.0f */) +{ + ImGuiManager::AddOSDMessage(std::move(key), std::move(message), duration, false); +} + +void Host::AddIconOSDMessage(std::string key, const char* icon, std::string message, float duration /* = 2.0f */) +{ + ImGuiManager::AddOSDMessage(std::move(key), fmt::format("{} {}", icon, message), duration, false); +} + +void Host::AddKeyedOSDWarning(std::string key, std::string message, float duration /* = 2.0f */) +{ + ImGuiManager::AddOSDMessage(std::move(key), std::move(message), duration, true); +} + +void Host::AddIconOSDWarning(std::string key, const char* icon, std::string message, float duration /* = 2.0f */) +{ + ImGuiManager::AddOSDMessage(std::move(key), fmt::format("{} {}", icon, message), duration, true); +} + +void Host::RemoveKeyedOSDMessage(std::string key) +{ + ImGuiManager::RemoveKeyedOSDMessage(std::move(key), false); +} + +void Host::RemoveKeyedOSDWarning(std::string key) +{ + ImGuiManager::RemoveKeyedOSDMessage(std::move(key), true); +} + +void Host::ClearOSDMessages(bool clear_warnings) +{ + ImGuiManager::ClearOSDMessages(clear_warnings); +} + float ImGuiManager::GetGlobalScale() { return s_global_scale; diff --git a/src/util/imgui_manager.h b/src/util/imgui_manager.h index 146dbd1b5..5c4be61ec 100644 --- a/src/util/imgui_manager.h +++ b/src/util/imgui_manager.h @@ -33,10 +33,11 @@ std::vector CompactFontRange(std::span range); void SetGlobalScale(float global_scale); /// Changes whether OSD messages are silently dropped. +bool IsShowingOSDMessages(); void SetShowOSDMessages(bool enable); /// Initializes ImGui, creates fonts, etc. -bool Initialize(float global_scale, bool show_osd_messages, Error* error); +bool Initialize(float global_scale, Error* error); /// Frees all ImGui resources. void Shutdown(); @@ -137,6 +138,9 @@ static constexpr float OSD_QUICK_DURATION = 2.5f; void AddOSDMessage(std::string message, float duration = 2.0f); void AddKeyedOSDMessage(std::string key, std::string message, float duration = 2.0f); void AddIconOSDMessage(std::string key, const char* icon, std::string message, float duration = 2.0f); +void AddKeyedOSDWarning(std::string key, std::string message, float duration = 2.0f); +void AddIconOSDWarning(std::string key, const char* icon, std::string message, float duration = 2.0f); void RemoveKeyedOSDMessage(std::string key); -void ClearOSDMessages(); +void RemoveKeyedOSDWarning(std::string key); +void ClearOSDMessages(bool clear_warnings); } // namespace Host