From ad96b1ec7572da3c2990984eb4dca09db5e3099e Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 13 Dec 2023 01:12:55 +1000 Subject: [PATCH] FullscreenUI: Improve menu button borders --- src/core/fullscreen_ui.cpp | 4 +- src/util/imgui_fullscreen.cpp | 74 +++++++++++++++++++++++++++++++---- src/util/imgui_fullscreen.h | 3 ++ 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 22ddbf7bc..7f3e8ba39 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -5409,7 +5409,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading) const float t = std::min(static_cast(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1)), 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - ImGui::RenderFrame(bb.Min, bb.Max, col, true, 0.0f); + ImGuiFullscreen::DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); ImGui::PopStyleColor(); } @@ -6031,7 +6031,7 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size) const float t = static_cast(std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0)); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - ImGui::RenderFrame(bb.Min, bb.Max, col, true, 0.0f); + ImGuiFullscreen::DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); ImGui::PopStyleColor(); } diff --git a/src/util/imgui_fullscreen.cpp b/src/util/imgui_fullscreen.cpp index e21af5f4f..b39511889 100644 --- a/src/util/imgui_fullscreen.cpp +++ b/src/util/imgui_fullscreen.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #define IMGUI_DEFINE_MATH_OPERATORS #include "imgui_fullscreen.h" -#include "IconsFontAwesome5.h" +#include "gpu_device.h" +#include "imgui_animated.h" + #include "common/assert.h" #include "common/easing.h" #include "common/file_system.h" @@ -15,9 +17,12 @@ #include "common/string_util.h" #include "common/threading.h" #include "common/timer.h" + #include "core/host.h" + #include "fmt/core.h" -#include "gpu_device.h" + +#include "IconsFontAwesome5.h" #include "imgui_internal.h" #include "imgui_stdlib.h" @@ -34,6 +39,8 @@ Log_SetChannel(ImGuiFullscreen); namespace ImGuiFullscreen { using MessageDialogCallbackVariant = std::variant; +static constexpr float MENU_BACKGROUND_ANIMATION_TIME = 0.25f; + static std::optional LoadTextureImage(const char* path); static std::shared_ptr UploadTexture(const char* path, const Common::RGBA8Image& image); static void TextureLoaderThread(); @@ -113,6 +120,11 @@ static std::string s_message_dialog_message; static std::array s_message_dialog_buttons; static MessageDialogCallbackVariant s_message_dialog_callback; +static ImAnimatedVec2 s_menu_button_frame_min_animated; +static ImAnimatedVec2 s_menu_button_frame_max_animated; +static bool s_had_hovered_menu_item = false; +static bool s_has_hovered_menu_item = false; + namespace { struct FileSelectorItem { @@ -203,6 +215,7 @@ bool ImGuiFullscreen::Initialize(const char* placeholder_image_path) s_texture_load_thread_quit.store(false, std::memory_order_release); s_texture_load_thread = std::thread(TextureLoaderThread); + ResetMenuButtonFrame(); return true; } @@ -478,6 +491,8 @@ void ImGuiFullscreen::EndLayout() DrawToast(); PopResetLayout(); + + s_had_hovered_menu_item = std::exchange(s_has_hovered_menu_item, false); } void ImGuiFullscreen::PushResetLayout() @@ -775,7 +790,7 @@ bool ImGuiFullscreen::MenuButtonFrame(const char* str_id, bool enabled, float he const float t = static_cast(std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0)); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - ImGui::RenderFrame(bb->Min, bb->Max, col, true, 0.0f); + DrawMenuButtonFrame(bb->Min, bb->Max, col, true, 0.0f); ImGui::PopStyleColor(); } @@ -793,6 +808,43 @@ bool ImGuiFullscreen::MenuButtonFrame(const char* str_id, bool enabled, float he return pressed; } +void ImGuiFullscreen::DrawMenuButtonFrame(const ImVec2& p_min, const ImVec2& p_max, ImU32 fill_col, + bool border /* = true */, float rounding /* = 0.0f */) +{ + ImVec2 frame_min = p_min; + ImVec2 frame_max = p_max; + + if (ImGui::GetIO().NavVisible) + { + if (!s_had_hovered_menu_item) + { + s_menu_button_frame_min_animated.Reset(frame_min); + s_menu_button_frame_max_animated.Reset(frame_max); + s_has_hovered_menu_item = true; + } + else + { + if (frame_min.x != s_menu_button_frame_min_animated.GetEndValue().x || + frame_min.y != s_menu_button_frame_min_animated.GetEndValue().y) + { + s_menu_button_frame_min_animated.Start(s_menu_button_frame_min_animated.GetCurrentValue(), frame_min, + MENU_BACKGROUND_ANIMATION_TIME); + } + if (frame_max.x != s_menu_button_frame_max_animated.GetEndValue().x || + frame_max.y != s_menu_button_frame_max_animated.GetEndValue().x) + { + s_menu_button_frame_max_animated.Start(s_menu_button_frame_max_animated.GetCurrentValue(), frame_max, + MENU_BACKGROUND_ANIMATION_TIME); + } + frame_min = s_menu_button_frame_min_animated.UpdateAndGetValue(); + frame_max = s_menu_button_frame_max_animated.UpdateAndGetValue(); + s_has_hovered_menu_item = true; + } + } + + ImGui::RenderFrame(frame_min, frame_max, fill_col, border, rounding); +} + bool ImGuiFullscreen::MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImVec2* min, ImVec2* max, ImGuiButtonFlags flags /*= 0*/, float hover_alpha /*= 0*/) @@ -804,6 +856,12 @@ bool ImGuiFullscreen::MenuButtonFrame(const char* str_id, bool enabled, float he return result; } +void ImGuiFullscreen::ResetMenuButtonFrame() +{ + s_had_hovered_menu_item = false; + s_has_hovered_menu_item = false; +} + void ImGuiFullscreen::MenuHeading(const char* title, bool draw_line /*= true*/) { const float line_thickness = draw_line ? LayoutScale(1.0f) : 0.0f; @@ -876,7 +934,7 @@ bool ImGuiFullscreen::ActiveButton(const char* title, bool is_active, bool enabl { ImVec2 pos, size; GetMenuButtonFrameBounds(height, &pos, &size); - ImGui::RenderFrame(pos, pos + size, ImGui::GetColorU32(UIPrimaryColor), false); + DrawMenuButtonFrame(pos, pos + size, ImGui::GetColorU32(UIPrimaryColor), false); } ImRect bb; @@ -1066,7 +1124,7 @@ bool ImGuiFullscreen::FloatingButton(const char* text, float x, float y, float w const float t = std::min(static_cast(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1)), 1.0f); const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - ImGui::RenderFrame(bb.Min, bb.Max, col, true, 0.0f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); ImGui::PopStyleColor(); } } @@ -1585,7 +1643,7 @@ bool ImGuiFullscreen::NavButton(const char* title, bool is_active, bool enabled if (hovered) { const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); - ImGui::RenderFrame(bb.Min, bb.Max, col, true, 0.0f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); } } else @@ -1662,7 +1720,7 @@ bool ImGuiFullscreen::NavTab(const char* title, bool is_active, bool enabled /* hovered ? ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f) : ImGui::GetColorU32(is_active ? background : ImVec4(background.x, background.y, background.z, 0.5f)); - ImGui::RenderFrame(bb.Min, bb.Max, col, true, 0.0f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); if (is_active) { diff --git a/src/util/imgui_fullscreen.h b/src/util/imgui_fullscreen.h index 0a6843cb1..b7863ca5a 100644 --- a/src/util/imgui_fullscreen.h +++ b/src/util/imgui_fullscreen.h @@ -177,6 +177,9 @@ void EndMenuButtons(); void GetMenuButtonFrameBounds(float height, ImVec2* pos, ImVec2* size); bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImVec2* min, ImVec2* max, ImGuiButtonFlags flags = 0, float hover_alpha = 1.0f); +void DrawMenuButtonFrame(const ImVec2& p_min, const ImVec2& p_max, ImU32 fill_col, bool border = true, + float rounding = 0.0f); +void ResetMenuButtonFrame(); void MenuHeading(const char* title, bool draw_line = true); bool MenuHeadingButton(const char* title, const char* value = nullptr, bool enabled = true, bool draw_line = true); bool ActiveButton(const char* title, bool is_active, bool enabled = true,