From eb5da8e55775149021cf6c685d235b14225a1dfb Mon Sep 17 00:00:00 2001 From: Gliniak Date: Fri, 10 Mar 2023 13:50:22 +0100 Subject: [PATCH] [UI] Changed default UI font to Tahoma. If it's not available use embedded font - Additionally allow user to provide own font size - Forced font scaling in notification window to be reasonable size --- src/xenia/ui/imgui_drawer.cc | 137 ++++++++++++++++++++--------- src/xenia/ui/imgui_drawer.h | 9 +- src/xenia/ui/imgui_notification.cc | 20 +++-- src/xenia/ui/imgui_notification.h | 2 + 4 files changed, 116 insertions(+), 52 deletions(-) diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 5e4ff4f8d..f1b0ce9d4 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -32,8 +32,9 @@ DEFINE_path( custom_font_path, "", - "Allows user to load custom font and use it instead of default one.", - "General"); + "Allows user to load custom font and use it instead of default one.", "UI"); + +DEFINE_uint32(font_size, 12, "Allows user to set custom font size.", "UI"); namespace xe { namespace ui { @@ -251,56 +252,79 @@ void ImGuiDrawer::SetupNotificationTextures() { } } -void ImGuiDrawer::InitializeFonts() { - auto& io = ImGui::GetIO(); +static const ImWchar font_glyph_ranges[] = { + 0x0020, 0x00FF, // Basic Latin + Latin Supplement + 0x0370, 0x03FF, // Greek + 0x0400, 0x044F, // Cyrillic + 0x2000, 0x206F, // General Punctuation + 0, +}; - const float default_font_size = 12.0f; - // TODO(gibbed): disable imgui.ini saving for now, - // imgui assumes paths are char* so we can't throw a good path at it on - // Windows. - io.IniFilename = nullptr; - - // Setup the font glyphs. - ImFontConfig font_config; - font_config.OversampleH = font_config.OversampleV = 2; - font_config.PixelSnapH = true; - - // https://jrgraphix.net/r/Unicode/ - static const ImWchar font_glyph_ranges[] = { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x0370, 0x03FF, // Greek - 0x0400, 0x044F, // Cyrillic - 0x2000, 0x206F, // General Punctuation - 0, - }; - - if (!cvars::custom_font_path.empty() && - std::filesystem::exists(cvars::custom_font_path)) { - const std::string font_path = xe::path_to_utf8(cvars::custom_font_path); - ImFont* font = io.Fonts->AddFontFromFileTTF( - font_path.c_str(), default_font_size, &font_config, font_glyph_ranges); - - io.Fonts->Build(); - // Something went wrong while loading custom font. Probably corrupted. - if (!font->IsLoaded()) { - XELOGE("Failed to load custom font: {}", font_path); - io.Fonts->Clear(); - } +bool ImGuiDrawer::LoadCustomFont(ImGuiIO& io, ImFontConfig& font_config, + float font_size) { + if (cvars::custom_font_path.empty()) { + return false; } - if (io.Fonts->Fonts.empty()) { - io.Fonts->AddFontFromMemoryCompressedBase85TTF( - kProggyTinyCompressedDataBase85, default_font_size, &font_config, - io.Fonts->GetGlyphRangesDefault()); + if (!std::filesystem::exists(cvars::custom_font_path)) { + return false; } + const std::string font_path = xe::path_to_utf8(cvars::custom_font_path); + ImFont* font = io.Fonts->AddFontFromFileTTF(font_path.c_str(), font_size, + &font_config, font_glyph_ranges); + + io.Fonts->Build(); + + if (!font->IsLoaded()) { + XELOGE("Failed to load custom font: {}", font_path); + io.Fonts->Clear(); + return false; + } + return true; +} + +bool ImGuiDrawer::LoadWindowsFont(ImGuiIO& io, ImFontConfig& font_config, + float font_size) { +#if XE_PLATFORM_WIN32 + PWSTR fonts_dir; + HRESULT result = SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &fonts_dir); + if (FAILED(result)) { + CoTaskMemFree(static_cast(fonts_dir)); + XELOGW("Unable to find Windows fonts directory"); + return false; + } + + std::filesystem::path font_path = std::wstring(fonts_dir); + font_path.append("tahoma.ttf"); + if (!std::filesystem::exists(font_path)) { + return false; + } + + ImFont* font = + io.Fonts->AddFontFromFileTTF(xe::path_to_utf8(font_path).c_str(), + font_size, &font_config, font_glyph_ranges); + + io.Fonts->Build(); + // Something went wrong while loading custom font. Probably corrupted. + if (!font->IsLoaded()) { + XELOGE("Failed to load custom font: {}", xe::path_to_utf8(font_path)); + io.Fonts->Clear(); + } + CoTaskMemFree(static_cast(fonts_dir)); + return true; +#endif + return false; +} + +bool ImGuiDrawer::LoadJapaneseFont(ImGuiIO& io, float font_size) { // TODO(benvanik): jp font on other platforms? #if XE_PLATFORM_WIN32 PWSTR fonts_dir; HRESULT result = SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &fonts_dir); if (FAILED(result)) { XELOGW("Unable to find Windows fonts directory"); - return; + return false; } std::filesystem::path jp_font_path = std::wstring(fonts_dir); @@ -312,13 +336,42 @@ void ImGuiDrawer::InitializeFonts() { jp_font_config.PixelSnapH = true; jp_font_config.FontNo = 0; io.Fonts->AddFontFromFileTTF(xe::path_to_utf8(jp_font_path).c_str(), - default_font_size, &jp_font_config, + font_size, &jp_font_config, io.Fonts->GetGlyphRangesJapanese()); } else { XELOGW("Unable to load Japanese font; JP characters will be boxes"); } CoTaskMemFree(static_cast(fonts_dir)); + return true; #endif + return false; +}; + +void ImGuiDrawer::InitializeFonts() { + auto& io = ImGui::GetIO(); + + const float font_size = std::max((float)cvars::font_size, 8.f); + // TODO(gibbed): disable imgui.ini saving for now, + // imgui assumes paths are char* so we can't throw a good path at it on + // Windows. + io.IniFilename = nullptr; + + ImFontConfig font_config; + font_config.OversampleH = font_config.OversampleV = 2; + font_config.PixelSnapH = true; + + bool is_font_loaded = LoadCustomFont(io, font_config, font_size); + if (!is_font_loaded) { + is_font_loaded = LoadWindowsFont(io, font_config, font_size); + } + + if (io.Fonts->Fonts.empty()) { + io.Fonts->AddFontFromMemoryCompressedBase85TTF( + kProggyTinyCompressedDataBase85, font_size, &font_config, + io.Fonts->GetGlyphRangesDefault()); + } + + LoadJapaneseFont(io, font_size); } void ImGuiDrawer::SetupFontTexture() { diff --git a/src/xenia/ui/imgui_drawer.h b/src/xenia/ui/imgui_drawer.h index f1f7c6ca0..3cabf91cf 100644 --- a/src/xenia/ui/imgui_drawer.h +++ b/src/xenia/ui/imgui_drawer.h @@ -15,6 +15,7 @@ #include #include +#include "third_party/imgui/imgui.h" #include "xenia/ui/immediate_drawer.h" #include "xenia/ui/presenter.h" #include "xenia/ui/window.h" @@ -55,7 +56,7 @@ class ImGuiDrawer : public WindowInputListener, public UIDrawer { } void Draw(UIDrawContext& ui_draw_context) override; - + void ClearDialogs(); ImmediateTexture* GetNotificationIcon(uint8_t user_index) { @@ -79,6 +80,9 @@ class ImGuiDrawer : public WindowInputListener, public UIDrawer { private: void Initialize(); void InitializeFonts(); + bool LoadCustomFont(ImGuiIO& io, ImFontConfig& font_config, float font_size); + bool LoadWindowsFont(ImGuiIO& io, ImFontConfig& font_config, float font_size); + bool LoadJapaneseFont(ImGuiIO& io, float font_size); void SetupNotificationTextures(); void SetupFontTexture(); @@ -103,7 +107,8 @@ class ImGuiDrawer : public WindowInputListener, public UIDrawer { // All currently-attached dialogs that get drawn. std::vector dialogs_; - // All queued notifications. Notification at index 0 is currently presented one. + // All queued notifications. Notification at index 0 is currently presented + // one. std::vector notifications_; // Using an index, not an iterator, because after the erasure, the adjustment // must be done for the vector element indices that would be in the iterator diff --git a/src/xenia/ui/imgui_notification.cc b/src/xenia/ui/imgui_notification.cc index 07dc10676..d22ac032a 100644 --- a/src/xenia/ui/imgui_notification.cc +++ b/src/xenia/ui/imgui_notification.cc @@ -186,14 +186,16 @@ void AchievementNotificationWindow::OnDraw(ImGuiIO& io) { : GetDescription().c_str(); const ImVec2 screen_size = io.DisplaySize; - const float scale = std::fminf(screen_size.x / default_drawing_resolution.x, - screen_size.y / default_drawing_resolution.y); + const float window_scale = + std::fminf(screen_size.x / default_drawing_resolution.x, + screen_size.y / default_drawing_resolution.y); + const float font_scale = default_font_size / io.Fonts->Fonts[0]->FontSize; const ImVec2 text_size = io.Fonts->Fonts[0]->CalcTextSizeA( - io.Fonts->Fonts[0]->FontSize * default_notification_text_scale * scale, + default_font_size * default_notification_text_scale * window_scale, FLT_MAX, -1.0f, longest_notification_text_line.c_str()); const ImVec2 final_notification_size = - CalculateNotificationSize(text_size, scale); + CalculateNotificationSize(text_size, window_scale); const ImVec2 notification_position = CalculateNotificationScreenPosition( screen_size, final_notification_size, GetPositionId()); @@ -211,7 +213,8 @@ void AchievementNotificationWindow::OnDraw(ImGuiIO& io) { ImGui::SetNextWindowPos(notification_position); // Set new window style before drawing window - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 30.f * scale); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, + default_notification_rounding * window_scale); ImGui::PushStyleColor(ImGuiCol_WindowBg, default_notification_background_color); ImGui::PushStyleColor(ImGuiCol_Separator, @@ -220,15 +223,16 @@ void AchievementNotificationWindow::OnDraw(ImGuiIO& io) { ImGui::Begin("Notification Window", NULL, NOTIFY_TOAST_FLAGS); { - ImGui::SetWindowFontScale(default_notification_text_scale * scale); + ImGui::SetWindowFontScale(default_notification_text_scale * font_scale * + window_scale); // Set offset to image to prevent it from being right on border. ImGui::SetCursorPos(ImVec2(final_notification_size.x * 0.005f, final_notification_size.y * 0.05f)); // Elements of window ImGui::Image(reinterpret_cast( GetDrawer()->GetNotificationIcon(GetUserIndex())), - ImVec2(default_notification_icon_size.x * scale, - default_notification_icon_size.y * scale)); + ImVec2(default_notification_icon_size.x * window_scale, + default_notification_icon_size.y * window_scale)); ImGui::SameLine(); if (notification_draw_progress_ > 0.5f) { diff --git a/src/xenia/ui/imgui_notification.h b/src/xenia/ui/imgui_notification.h index 55304dbc1..c8e900646 100644 --- a/src/xenia/ui/imgui_notification.h +++ b/src/xenia/ui/imgui_notification.h @@ -26,6 +26,8 @@ constexpr ImVec2 default_drawing_resolution = ImVec2(1280.f, 720.f); constexpr ImVec2 default_notification_icon_size = ImVec2(58.0f, 58.0f); constexpr ImVec2 default_notification_margin_size = ImVec2(50.f, 5.f); constexpr float default_notification_text_scale = 2.3f; +constexpr float default_notification_rounding = 30.f; +constexpr float default_font_size = 12.f; constexpr ImVec4 white_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);