mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-22 15:46:35 +00:00
Nav: extracted sections of NavUpdate() into a NavUpdateCreateMoveRequest() function. Only clearing results when a request is activated.
This commit is contained in:
parent
ccfb20095e
commit
bb6a60b1ff
177
imgui.cpp
177
imgui.cpp
@ -909,6 +909,7 @@ static void NavUpdateWindowing();
|
||||
static void NavUpdateWindowingOverlay();
|
||||
static void NavUpdateInitResult();
|
||||
static void NavUpdateCancelRequest();
|
||||
static void NavUpdateCreateMoveRequest();
|
||||
static float NavUpdatePageUpPageDown();
|
||||
static inline void NavUpdateAnyRequestFlag();
|
||||
static void NavEndFrame();
|
||||
@ -9110,8 +9111,8 @@ static void ImGui::NavUpdate()
|
||||
|
||||
// Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard)
|
||||
// (do it before we map Keyboard input!)
|
||||
bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||
bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
||||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
||||
if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad)
|
||||
{
|
||||
if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f
|
||||
@ -9210,55 +9211,9 @@ static void ImGui::NavUpdate()
|
||||
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId;
|
||||
g.NavNextActivateId = 0;
|
||||
|
||||
if (g.NavMoveRequestForwardToNextFrame)
|
||||
{
|
||||
// Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
|
||||
// (Preserve g.NavMoveRequestFlags, g.NavMoveClipDir which were set by the NavMoveRequestForward() function)
|
||||
IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
|
||||
IM_ASSERT(g.NavMoveRequestFlags & ImGuiNavMoveFlags_Forwarded);
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir);
|
||||
g.NavMoveRequestForwardToNextFrame = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initiate directional inputs request
|
||||
g.NavMoveDir = ImGuiDir_None;
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
|
||||
if (g.NavWindow && !g.NavWindowingTarget && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
|
||||
{
|
||||
const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat;
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && (IsNavInputTest(ImGuiNavInput_DpadLeft, read_mode) || IsNavInputTest(ImGuiNavInput_KeyLeft_, read_mode))) { g.NavMoveDir = ImGuiDir_Left; }
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && (IsNavInputTest(ImGuiNavInput_DpadRight, read_mode) || IsNavInputTest(ImGuiNavInput_KeyRight_, read_mode))) { g.NavMoveDir = ImGuiDir_Right; }
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && (IsNavInputTest(ImGuiNavInput_DpadUp, read_mode) || IsNavInputTest(ImGuiNavInput_KeyUp_, read_mode))) { g.NavMoveDir = ImGuiDir_Up; }
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && (IsNavInputTest(ImGuiNavInput_DpadDown, read_mode) || IsNavInputTest(ImGuiNavInput_KeyDown_, read_mode))) { g.NavMoveDir = ImGuiDir_Down; }
|
||||
}
|
||||
g.NavMoveClipDir = g.NavMoveDir;
|
||||
}
|
||||
|
||||
// Update PageUp/PageDown/Home/End scroll
|
||||
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
|
||||
float nav_scoring_rect_offset_y = 0.0f;
|
||||
if (nav_keyboard_active)
|
||||
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown();
|
||||
|
||||
// If we initiate a movement request and have no current NavId, we initiate a InitDefaultRequest that will be used as a fallback if the direction fails to find a match
|
||||
if (g.NavMoveDir != ImGuiDir_None)
|
||||
{
|
||||
g.NavMoveRequest = true;
|
||||
g.NavMoveRequestKeyMods = io.KeyMods;
|
||||
g.NavMoveDirLast = g.NavMoveDir;
|
||||
}
|
||||
if (g.NavMoveRequest && g.NavId == 0)
|
||||
{
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer);
|
||||
g.NavInitRequest = g.NavInitRequestFromMove = true;
|
||||
// Reassigning with same value, we're being explicit here.
|
||||
g.NavInitResultId = 0; // -V1048
|
||||
g.NavDisableHighlight = false;
|
||||
}
|
||||
// Process move requests
|
||||
NavUpdateCreateMoveRequest();
|
||||
NavUpdateAnyRequestFlag();
|
||||
if (g.NavMoveDir != ImGuiDir_None)
|
||||
IM_ASSERT(g.NavMoveRequest);
|
||||
|
||||
// Scrolling
|
||||
if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget)
|
||||
@ -9266,7 +9221,7 @@ static void ImGui::NavUpdate()
|
||||
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
||||
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
|
||||
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) //-V560
|
||||
{
|
||||
if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
|
||||
SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
|
||||
@ -9283,36 +9238,7 @@ static void ImGui::NavUpdate()
|
||||
SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
|
||||
}
|
||||
|
||||
// Reset search results
|
||||
g.NavMoveResultLocal.Clear();
|
||||
g.NavMoveResultLocalVisibleSet.Clear();
|
||||
g.NavMoveResultOther.Clear();
|
||||
|
||||
// When using gamepad, we project the reference nav bounding box into window visible area.
|
||||
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
|
||||
// (can't focus a visible object like we can with the mouse).
|
||||
if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main)
|
||||
{
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1));
|
||||
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
|
||||
{
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n");
|
||||
float pad = window->CalcFontSize() * 0.5f;
|
||||
window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
|
||||
window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel);
|
||||
g.NavId = g.NavFocusScopeId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
|
||||
ImRect nav_rect_rel = g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted() ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
||||
g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : ImRect(0, 0, 0, 0);
|
||||
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
|
||||
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
|
||||
g.NavScoringRect.Max.x = g.NavScoringRect.Min.x;
|
||||
IM_ASSERT(!g.NavScoringRect.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
|
||||
//GetForegroundDrawList()->AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG]
|
||||
// [DEBUG]
|
||||
g.NavScoringCount = 0;
|
||||
#if IMGUI_DEBUG_NAV_RECTS
|
||||
if (g.NavWindow)
|
||||
@ -9342,6 +9268,95 @@ static void ImGui::NavUpdateInitResult()
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::NavUpdateCreateMoveRequest()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiIO& io = g.IO;
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
|
||||
if (g.NavMoveRequestForwardToNextFrame)
|
||||
{
|
||||
// Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
|
||||
// (preserve most state, which were already set by the NavMoveRequestForward() function)
|
||||
IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
|
||||
IM_ASSERT(g.NavMoveRequestFlags & ImGuiNavMoveFlags_Forwarded);
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir);
|
||||
g.NavMoveRequestForwardToNextFrame = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initiate directional inputs request
|
||||
g.NavMoveDir = ImGuiDir_None;
|
||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
|
||||
if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
|
||||
{
|
||||
const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat;
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && (IsNavInputTest(ImGuiNavInput_DpadLeft, read_mode) || IsNavInputTest(ImGuiNavInput_KeyLeft_, read_mode))) { g.NavMoveDir = ImGuiDir_Left; }
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && (IsNavInputTest(ImGuiNavInput_DpadRight, read_mode) || IsNavInputTest(ImGuiNavInput_KeyRight_, read_mode))) { g.NavMoveDir = ImGuiDir_Right; }
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && (IsNavInputTest(ImGuiNavInput_DpadUp, read_mode) || IsNavInputTest(ImGuiNavInput_KeyUp_, read_mode))) { g.NavMoveDir = ImGuiDir_Up; }
|
||||
if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && (IsNavInputTest(ImGuiNavInput_DpadDown, read_mode) || IsNavInputTest(ImGuiNavInput_KeyDown_, read_mode))) { g.NavMoveDir = ImGuiDir_Down; }
|
||||
}
|
||||
g.NavMoveClipDir = g.NavMoveDir;
|
||||
}
|
||||
|
||||
// Update PageUp/PageDown/Home/End scroll
|
||||
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
|
||||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||
float nav_scoring_rect_offset_y = 0.0f;
|
||||
if (nav_keyboard_active)
|
||||
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown();
|
||||
|
||||
// If we initiate a movement request and have no current NavId, we initiate a InitDefaultRequest that will be used as a fallback if the direction fails to find a match
|
||||
if (g.NavMoveDir != ImGuiDir_None)
|
||||
{
|
||||
IM_ASSERT(window != NULL);
|
||||
g.NavMoveRequest = true;
|
||||
g.NavMoveRequestKeyMods = io.KeyMods;
|
||||
g.NavMoveDirLast = g.NavMoveDir;
|
||||
g.NavMoveResultLocal.Clear();
|
||||
g.NavMoveResultLocalVisibleSet.Clear();
|
||||
g.NavMoveResultOther.Clear();
|
||||
}
|
||||
|
||||
// Moving with no reference triggers a init request
|
||||
if (g.NavMoveRequest && g.NavId == 0)
|
||||
{
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer);
|
||||
g.NavInitRequest = g.NavInitRequestFromMove = true;
|
||||
g.NavInitResultId = 0;
|
||||
g.NavDisableHighlight = false;
|
||||
}
|
||||
|
||||
// When using gamepad, we project the reference nav bounding box into window visible area.
|
||||
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
|
||||
// (can't focus a visible object like we can with the mouse).
|
||||
if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main && window != NULL)
|
||||
{
|
||||
ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1));
|
||||
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
|
||||
{
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n");
|
||||
float pad = window->CalcFontSize() * 0.5f;
|
||||
window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
|
||||
window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel);
|
||||
g.NavId = g.NavFocusScopeId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
|
||||
g.NavScoringRect = ImRect();
|
||||
if (window)
|
||||
{
|
||||
ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? window->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
||||
g.NavScoringRect = ImRect(window->Pos + nav_rect_rel.Min, window->Pos + nav_rect_rel.Max);
|
||||
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
|
||||
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
|
||||
g.NavScoringRect.Max.x = g.NavScoringRect.Min.x;
|
||||
IM_ASSERT(!g.NavScoringRect.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
|
||||
//GetForegroundDrawList()->AddRect(g.NavScoringRect.Min, g.NavScoringRect.Max, IM_COL32(255,200,0,255)); // [DEBUG]
|
||||
}
|
||||
}
|
||||
|
||||
// Apply result from previous frame navigation directional move request. Always called from NavUpdate()
|
||||
void ImGui::NavMoveRequestApplyResult()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user