From 0b045d8de5afb72121b47746ce73e5fa11a5fd1d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 26 Jul 2018 19:00:17 +0200 Subject: [PATCH] Nav: Tweaked CTRL+TAB to hide visual noise on fast switch + fading out screen dimming and highlight to make the experience less harsh --- imgui.cpp | 38 +++++++++++++++++++++++++++----------- imgui_internal.h | 7 ++++--- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index da6befed..e052f0d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -856,6 +856,10 @@ static const ImS64 IM_S64_MAX = 9223372036854775807ll; static const ImU64 IM_U64_MIN = 0; static const ImU64 IM_U64_MAX = 0xFFFFFFFFFFFFFFFFull; +// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. +static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in +static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear + //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- @@ -3056,7 +3060,7 @@ static void NavUpdateWindowingHighlightWindow(int focus_change_dir) if (!window_target) window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); if (window_target) // Don't reset windowing target if there's a single window in the list - g.NavWindowingTarget = window_target; + g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target; g.NavWindowingToggleLayer = false; } @@ -3074,23 +3078,32 @@ static void ImGui::NavUpdateWindowing() return; } + // Fade out + if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) + { + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f); + if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) + g.NavWindowingTargetAnim = NULL; + } + + // Start CTRL-TAB or Square+L/R window selection bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard); if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1)) { - g.NavWindowingTarget = window; - g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f; + g.NavWindowingTarget = g.NavWindowingTargetAnim = window; + g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; } // Gamepad update - g.NavWindowingHighlightTimer += g.IO.DeltaTime; + g.NavWindowingTimer += g.IO.DeltaTime; if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad) { // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f)); + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // Select window to focus const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow); @@ -3116,7 +3129,7 @@ static void ImGui::NavUpdateWindowing() if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard) { // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.15f) / 0.04f)); // 1.0f + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f if (IsKeyPressedMap(ImGuiKey_Tab, true)) NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1); if (!g.IO.KeyCtrl) @@ -3201,6 +3214,9 @@ void ImGui::NavUpdateWindowingList() ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindowingTarget != NULL); + if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY) + return; + if (g.NavWindowingList == NULL) g.NavWindowingList = FindWindowByName("###NavWindowingList"); SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); @@ -3928,10 +3944,10 @@ void ImGui::NewFrame() UpdateHoveredWindowAndCaptureFlags(); // Background darkening/whitening - if (GetFrontMostPopupModal() != NULL || g.NavWindowingTarget != NULL) + if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); else - g.DimBgRatio = 0.0f; + g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); g.MouseCursor = ImGuiMouseCursor_Arrow; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; @@ -6485,7 +6501,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Draw modal window background (darkens what is behind them, all viewports) const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFrames <= 0; - const bool dim_bg_for_window_list = g.NavWindowingTarget && (window == g.NavWindowingTarget->RootWindow); + const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow); if (dim_bg_for_modal || dim_bg_for_window_list) { const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio); @@ -6493,7 +6509,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Draw navigation selection/windowing rectangle background - if (dim_bg_for_window_list && window == g.NavWindowingTarget->RootWindow) + if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim) { ImRect bb = window->Rect(); bb.Expand(g.FontSize); @@ -6575,7 +6591,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Draw navigation selection/windowing rectangle border - if (g.NavWindowingTarget == window) + if (g.NavWindowingTargetAnim == window) { float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding); ImRect bb = window->Rect(); diff --git a/imgui_internal.h b/imgui_internal.h index 5d6242a9..f76dbded 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -672,8 +672,9 @@ struct ImGuiContext ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. + ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f ImGuiWindow* NavWindowingList; - float NavWindowingHighlightTimer; + float NavWindowingTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. @@ -801,8 +802,8 @@ struct ImGuiContext NavInputSource = ImGuiInputSource_None; NavScoringRectScreen = ImRect(); NavScoringCount = 0; - NavWindowingTarget = NavWindowingList = NULL; - NavWindowingHighlightTimer = NavWindowingHighlightAlpha = 0.0f; + NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; + NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; NavLayer = 0; NavIdTabCounter = INT_MAX;