mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-15 01:17:00 +00:00
Nav: split NavMoveRequest into NavMoveSubmitted + NavMoveScoringItems to allow operation to defer a move request and provide result immediately + fix regular scoring needlesly running during init + some renaming.
This commit is contained in:
parent
eb6c16d3dd
commit
7b913db1ce
185
imgui.cpp
185
imgui.cpp
@ -2258,21 +2258,21 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect
|
// We create the union of the ClipRect and the scoring rect which at worst should be 1 page away from ClipRect
|
||||||
ImRect unclipped_rect = window->ClipRect;
|
ImRect unclipped_rect = window->ClipRect;
|
||||||
if (g.NavMoveRequest)
|
if (g.NavMoveScoringItems)
|
||||||
unclipped_rect.Add(g.NavScoringRect);
|
unclipped_rect.Add(g.NavScoringRect);
|
||||||
if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId)
|
if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId)
|
||||||
unclipped_rect.Add(ImRect(window->Pos + window->NavRectRel[0].Min, window->Pos + window->NavRectRel[0].Max));
|
unclipped_rect.Add(ImRect(window->Pos + window->NavRectRel[0].Min, window->Pos + window->NavRectRel[0].Max)); // Could store and use NavJustMovedToRectRel
|
||||||
|
|
||||||
const ImVec2 pos = window->DC.CursorPos;
|
const ImVec2 pos = window->DC.CursorPos;
|
||||||
int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
|
int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
|
||||||
int end = (int)((unclipped_rect.Max.y - pos.y) / items_height);
|
int end = (int)((unclipped_rect.Max.y - pos.y) / items_height);
|
||||||
|
|
||||||
// When performing a navigation request, ensure we have one item extra in the direction we are moving to
|
// When performing a navigation request, ensure we have one item extra in the direction we are moving to
|
||||||
if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up)
|
if (g.NavMoveScoringItems && g.NavMoveClipDir == ImGuiDir_Up)
|
||||||
start--;
|
start--;
|
||||||
if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down)
|
if (g.NavMoveScoringItems && g.NavMoveClipDir == ImGuiDir_Down)
|
||||||
end++;
|
end++;
|
||||||
|
|
||||||
start = ImClamp(start, 0, items_count);
|
start = ImClamp(start, 0, items_count);
|
||||||
@ -6534,7 +6534,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
|||||||
g.NavFocusScopeId = 0;
|
g.NavFocusScopeId = 0;
|
||||||
g.NavIdIsAlive = false;
|
g.NavIdIsAlive = false;
|
||||||
g.NavLayer = ImGuiNavLayer_Main;
|
g.NavLayer = ImGuiNavLayer_Main;
|
||||||
g.NavInitRequest = g.NavMoveRequest = false;
|
g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false;
|
||||||
NavUpdateAnyRequestFlag();
|
NavUpdateAnyRequestFlag();
|
||||||
//IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
|
//IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
|
||||||
}
|
}
|
||||||
@ -8755,7 +8755,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
|
|||||||
if (g.NavLayer != window->DC.NavLayerCurrent)
|
if (g.NavLayer != window->DC.NavLayerCurrent)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const ImRect& curr = g.NavScoringRect; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
|
const ImRect curr = g.NavScoringRect; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
|
||||||
g.NavScoringCount++;
|
g.NavScoringCount++;
|
||||||
|
|
||||||
// When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
|
// When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
|
||||||
@ -8822,7 +8822,6 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
|
|||||||
}
|
}
|
||||||
else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
|
else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
|
||||||
{
|
{
|
||||||
if (IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; }
|
|
||||||
if (quadrant == g.NavMoveDir)
|
if (quadrant == g.NavMoveDir)
|
||||||
{
|
{
|
||||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
|
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
|
||||||
@ -8835,7 +8834,8 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
|
|||||||
|
|
||||||
// Is it in the quadrant we're interesting in moving to?
|
// Is it in the quadrant we're interesting in moving to?
|
||||||
bool new_best = false;
|
bool new_best = false;
|
||||||
if (quadrant == g.NavMoveDir)
|
const ImGuiDir move_dir = g.NavMoveDir;
|
||||||
|
if (quadrant == move_dir)
|
||||||
{
|
{
|
||||||
// Does it beat the current best candidate?
|
// Does it beat the current best candidate?
|
||||||
if (dist_box < result->DistBox)
|
if (dist_box < result->DistBox)
|
||||||
@ -8857,7 +8857,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
|
|||||||
// Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
|
// Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
|
||||||
// (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
|
// (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
|
||||||
// this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
|
// this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
|
||||||
if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
|
if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
|
||||||
new_best = true;
|
new_best = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8870,7 +8870,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
|
|||||||
// Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
|
// Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
|
||||||
if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match
|
if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match
|
||||||
if (g.NavLayer == ImGuiNavLayer_Menu && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
if (g.NavLayer == ImGuiNavLayer_Menu && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
||||||
if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f))
|
if ((move_dir == ImGuiDir_Left && dax < 0.0f) || (move_dir == ImGuiDir_Right && dax > 0.0f) || (move_dir == ImGuiDir_Up && day < 0.0f) || (move_dir == ImGuiDir_Down && day > 0.0f))
|
||||||
{
|
{
|
||||||
result->DistAxial = dist_axial;
|
result->DistAxial = dist_axial;
|
||||||
new_best = true;
|
new_best = true;
|
||||||
@ -8891,9 +8891,6 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result, ImGuiWindow* w
|
|||||||
static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
|
static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
//if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
|
|
||||||
// return;
|
|
||||||
|
|
||||||
const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
|
const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
|
||||||
const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
|
const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
|
||||||
|
|
||||||
@ -8915,27 +8912,29 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process Move Request (scoring for navigation)
|
// Process Move Request (scoring for navigation)
|
||||||
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
|
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy)
|
||||||
if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
|
if (g.NavMoveScoringItems)
|
||||||
{
|
{
|
||||||
ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
|
if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
|
||||||
#if IMGUI_DEBUG_NAV_SCORING
|
{
|
||||||
// [DEBUG] Score all items in NavWindow at all times
|
ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
|
||||||
if (!g.NavMoveRequest)
|
bool new_best = NavScoreItem(result, nav_bb);
|
||||||
g.NavMoveDir = g.NavMoveDirLast;
|
|
||||||
bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest;
|
|
||||||
#else
|
|
||||||
bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb);
|
|
||||||
#endif
|
|
||||||
if (new_best)
|
|
||||||
NavApplyItemToResult(result, window, id, nav_bb_rel);
|
|
||||||
|
|
||||||
// Features like PageUp/PageDown need to maintain a separate score for the visible set of items.
|
#if IMGUI_DEBUG_NAV_SCORING
|
||||||
const float VISIBLE_RATIO = 0.70f;
|
// [DEBUG] Scoring all items in NavWindow at all times
|
||||||
if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
|
if (g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult)
|
||||||
if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
|
new_best = false;
|
||||||
if (NavScoreItem(&g.NavMoveResultLocalVisibleSet, nav_bb))
|
#endif
|
||||||
NavApplyItemToResult(&g.NavMoveResultLocalVisibleSet, window, id, nav_bb_rel);
|
if (new_best)
|
||||||
|
NavApplyItemToResult(result, window, id, nav_bb_rel);
|
||||||
|
|
||||||
|
// Features like PageUp/PageDown need to maintain a separate score for the visible set of items.
|
||||||
|
const float VISIBLE_RATIO = 0.70f;
|
||||||
|
if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
|
||||||
|
if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
|
||||||
|
if (NavScoreItem(&g.NavMoveResultLocalVisible, nav_bb))
|
||||||
|
NavApplyItemToResult(&g.NavMoveResultLocalVisible, window, id, nav_bb_rel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update window-relative bounding box of navigated item
|
// Update window-relative bounding box of navigated item
|
||||||
@ -8952,13 +8951,13 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
|
|||||||
bool ImGui::NavMoveRequestButNoResultYet()
|
bool ImGui::NavMoveRequestButNoResultYet()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
|
return g.NavMoveScoringItems && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::NavMoveRequestCancel()
|
void ImGui::NavMoveRequestCancel()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
g.NavMoveRequest = false;
|
g.NavMoveSubmitted = g.NavMoveScoringItems = false;
|
||||||
NavUpdateAnyRequestFlag();
|
NavUpdateAnyRequestFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8966,12 +8965,12 @@ void ImGui::NavMoveRequestCancel()
|
|||||||
void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags)
|
void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
IM_ASSERT(g.NavMoveRequestForwardToNextFrame == false);
|
IM_ASSERT(g.NavMoveForwardToNextFrame == false);
|
||||||
NavMoveRequestCancel();
|
NavMoveRequestCancel();
|
||||||
g.NavMoveRequestForwardToNextFrame = true;
|
g.NavMoveForwardToNextFrame = true;
|
||||||
g.NavMoveDir = move_dir;
|
g.NavMoveDir = move_dir;
|
||||||
g.NavMoveClipDir = clip_dir;
|
g.NavMoveClipDir = clip_dir;
|
||||||
g.NavMoveRequestFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
|
g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire
|
// Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire
|
||||||
@ -8980,8 +8979,9 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wra
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
IM_ASSERT(wrap_flags != 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY
|
IM_ASSERT(wrap_flags != 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY
|
||||||
if (g.NavWindow == window && g.NavMoveRequest && g.NavLayer == ImGuiNavLayer_Main)
|
// In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it, NavEndFrame() will do the same test
|
||||||
g.NavMoveRequestFlags |= wrap_flags;
|
if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main)
|
||||||
|
g.NavMoveFlags |= wrap_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
|
// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
|
||||||
@ -9026,7 +9026,7 @@ void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
|
|||||||
static inline void ImGui::NavUpdateAnyRequestFlag()
|
static inline void ImGui::NavUpdateAnyRequestFlag()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
|
g.NavAnyRequest = g.NavMoveScoringItems || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
|
||||||
if (g.NavAnyRequest)
|
if (g.NavAnyRequest)
|
||||||
IM_ASSERT(g.NavWindow != NULL);
|
IM_ASSERT(g.NavWindow != NULL);
|
||||||
}
|
}
|
||||||
@ -9128,7 +9128,7 @@ static void ImGui::NavUpdate()
|
|||||||
|
|
||||||
io.WantSetMousePos = false;
|
io.WantSetMousePos = false;
|
||||||
#if 0
|
#if 0
|
||||||
if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
|
if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard)
|
// Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard)
|
||||||
@ -9172,9 +9172,9 @@ static void ImGui::NavUpdate()
|
|||||||
g.NavJustMovedToId = 0;
|
g.NavJustMovedToId = 0;
|
||||||
|
|
||||||
// Process navigation move request
|
// Process navigation move request
|
||||||
if (g.NavMoveRequest)
|
if (g.NavMoveSubmitted)
|
||||||
NavMoveRequestApplyResult();
|
NavMoveRequestApplyResult();
|
||||||
g.NavMoveRequest = false;
|
g.NavMoveSubmitted = g.NavMoveScoringItems = false;
|
||||||
|
|
||||||
// Apply application mouse position movement, after we had a chance to process move request result.
|
// Apply application mouse position movement, after we had a chance to process move request result.
|
||||||
if (g.NavMousePosDirty && g.NavIdIsAlive)
|
if (g.NavMousePosDirty && g.NavIdIsAlive)
|
||||||
@ -9243,12 +9243,13 @@ static void ImGui::NavUpdate()
|
|||||||
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item
|
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item
|
||||||
ImGuiWindow* window = g.NavWindow;
|
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.
|
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) //-V560
|
const ImGuiDir move_dir = g.NavMoveDir;
|
||||||
|
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && move_dir != ImGuiDir_None)
|
||||||
{
|
{
|
||||||
if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
|
if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
|
||||||
SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
|
SetScrollX(window, ImFloor(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
|
||||||
if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)
|
if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
|
||||||
SetScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
|
SetScrollY(window, ImFloor(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
|
||||||
}
|
}
|
||||||
|
|
||||||
// *Normal* Manual scroll with NavScrollXXX keys
|
// *Normal* Manual scroll with NavScrollXXX keys
|
||||||
@ -9296,20 +9297,20 @@ void ImGui::NavUpdateCreateMoveRequest()
|
|||||||
ImGuiIO& io = g.IO;
|
ImGuiIO& io = g.IO;
|
||||||
ImGuiWindow* window = g.NavWindow;
|
ImGuiWindow* window = g.NavWindow;
|
||||||
|
|
||||||
if (g.NavMoveRequestForwardToNextFrame)
|
if (g.NavMoveForwardToNextFrame && window != NULL)
|
||||||
{
|
{
|
||||||
// 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)
|
// 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)
|
// (preserve most state, which were already set by the NavMoveRequestForward() function)
|
||||||
IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
|
IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
|
||||||
IM_ASSERT(g.NavMoveRequestFlags & ImGuiNavMoveFlags_Forwarded);
|
IM_ASSERT(g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded);
|
||||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir);
|
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir);
|
||||||
g.NavMoveRequestForwardToNextFrame = false;
|
g.NavMoveForwardToNextFrame = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Initiate directional inputs request
|
// Initiate directional inputs request
|
||||||
g.NavMoveDir = ImGuiDir_None;
|
g.NavMoveDir = ImGuiDir_None;
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
|
g.NavMoveFlags = ImGuiNavMoveFlags_None;
|
||||||
if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
|
if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
|
||||||
{
|
{
|
||||||
const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat;
|
const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat;
|
||||||
@ -9324,24 +9325,36 @@ void ImGui::NavUpdateCreateMoveRequest()
|
|||||||
// Update PageUp/PageDown/Home/End scroll
|
// Update PageUp/PageDown/Home/End scroll
|
||||||
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
|
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
|
||||||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||||
float nav_scoring_rect_offset_y = 0.0f;
|
float scoring_rect_offset_y = 0.0f;
|
||||||
if (nav_keyboard_active)
|
if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
|
||||||
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown();
|
scoring_rect_offset_y = NavUpdatePageUpPageDown();
|
||||||
|
|
||||||
|
// [DEBUG] Always send a request
|
||||||
|
#if IMGUI_DEBUG_NAV_SCORING
|
||||||
|
if (io.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
|
||||||
|
g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3);
|
||||||
|
if (io.KeyCtrl && g.NavMoveDir == ImGuiDir_None)
|
||||||
|
{
|
||||||
|
g.NavMoveDir = g.NavMoveDirForDebug;
|
||||||
|
g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 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 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
|
||||||
|
// FIXME: Would be nice to call a single function to initiate a new request
|
||||||
if (g.NavMoveDir != ImGuiDir_None)
|
if (g.NavMoveDir != ImGuiDir_None)
|
||||||
{
|
{
|
||||||
IM_ASSERT(window != NULL);
|
IM_ASSERT(window != NULL);
|
||||||
g.NavMoveRequest = true;
|
g.NavMoveSubmitted = g.NavMoveScoringItems = true;
|
||||||
g.NavMoveRequestKeyMods = io.KeyMods;
|
g.NavMoveKeyMods = io.KeyMods;
|
||||||
g.NavMoveDirLast = g.NavMoveDir;
|
g.NavMoveDirForDebug = g.NavMoveDir;
|
||||||
g.NavMoveResultLocal.Clear();
|
g.NavMoveResultLocal.Clear();
|
||||||
g.NavMoveResultLocalVisibleSet.Clear();
|
g.NavMoveResultLocalVisible.Clear();
|
||||||
g.NavMoveResultOther.Clear();
|
g.NavMoveResultOther.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moving with no reference triggers a init request
|
// Moving with no reference triggers a init request
|
||||||
if (g.NavMoveRequest && g.NavId == 0)
|
if (g.NavMoveSubmitted && g.NavId == 0)
|
||||||
{
|
{
|
||||||
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer);
|
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer);
|
||||||
g.NavInitRequest = g.NavInitRequestFromMove = true;
|
g.NavInitRequest = g.NavInitRequestFromMove = true;
|
||||||
@ -9352,7 +9365,7 @@ void ImGui::NavUpdateCreateMoveRequest()
|
|||||||
// When using gamepad, we project the reference nav bounding box into window visible area.
|
// 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
|
// 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).
|
// (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)
|
if (g.NavMoveSubmitted && 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));
|
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]))
|
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
|
||||||
@ -9366,17 +9379,18 @@ void ImGui::NavUpdateCreateMoveRequest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
// 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();
|
ImRect scoring_rect;
|
||||||
if (window)
|
if (window != NULL)
|
||||||
{
|
{
|
||||||
ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? window->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
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);
|
scoring_rect = ImRect(window->Pos + nav_rect_rel.Min, window->Pos + nav_rect_rel.Max);
|
||||||
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
|
scoring_rect.TranslateY(scoring_rect_offset_y);
|
||||||
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
|
scoring_rect.Min.x = ImMin(scoring_rect.Min.x + 1.0f, scoring_rect.Max.x);
|
||||||
g.NavScoringRect.Max.x = g.NavScoringRect.Min.x;
|
scoring_rect.Max.x = scoring_rect.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().
|
IM_ASSERT(!scoring_rect.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]
|
//GetForegroundDrawList()->AddRect(scoring_rect.Min, scoring_rect.Max, IM_COL32(255,200,0,255)); // [DEBUG]
|
||||||
}
|
}
|
||||||
|
g.NavScoringRect = scoring_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply result from previous frame navigation directional move request. Always called from NavUpdate()
|
// Apply result from previous frame navigation directional move request. Always called from NavUpdate()
|
||||||
@ -9399,9 +9413,9 @@ void ImGui::NavMoveRequestApplyResult()
|
|||||||
ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
|
ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
|
||||||
|
|
||||||
// PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
|
// PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
|
||||||
if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
|
if (g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
|
||||||
if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId)
|
if (g.NavMoveResultLocalVisible.ID != 0 && g.NavMoveResultLocalVisible.ID != g.NavId)
|
||||||
result = &g.NavMoveResultLocalVisibleSet;
|
result = &g.NavMoveResultLocalVisible;
|
||||||
|
|
||||||
// Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
|
// Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
|
||||||
if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
|
if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
|
||||||
@ -9413,7 +9427,7 @@ void ImGui::NavMoveRequestApplyResult()
|
|||||||
if (g.NavLayer == ImGuiNavLayer_Main)
|
if (g.NavLayer == ImGuiNavLayer_Main)
|
||||||
{
|
{
|
||||||
ImVec2 delta_scroll;
|
ImVec2 delta_scroll;
|
||||||
if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge)
|
if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdge)
|
||||||
{
|
{
|
||||||
float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
|
float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
|
||||||
delta_scroll.y = result->Window->Scroll.y - scroll_target;
|
delta_scroll.y = result->Window->Scroll.y - scroll_target;
|
||||||
@ -9437,7 +9451,7 @@ void ImGui::NavMoveRequestApplyResult()
|
|||||||
// Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId)
|
// Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId)
|
||||||
g.NavJustMovedToId = result->ID;
|
g.NavJustMovedToId = result->ID;
|
||||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||||
g.NavJustMovedToKeyMods = g.NavMoveRequestKeyMods;
|
g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
|
||||||
}
|
}
|
||||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
|
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
|
||||||
SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
|
SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
|
||||||
@ -9492,18 +9506,17 @@ static void ImGui::NavUpdateCancelRequest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle PageUp/PageDown/Home/End keys
|
// Handle PageUp/PageDown/Home/End keys
|
||||||
|
// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
|
||||||
// FIXME-NAV: how to get Home/End to aim at the beginning/end of a 2D grid?
|
// FIXME-NAV: how to get Home/End to aim at the beginning/end of a 2D grid?
|
||||||
static float ImGui::NavUpdatePageUpPageDown()
|
static float ImGui::NavUpdatePageUpPageDown()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiIO& io = g.IO;
|
ImGuiIO& io = g.IO;
|
||||||
|
|
||||||
if (g.NavMoveDir != ImGuiDir_None || g.NavWindow == NULL)
|
ImGuiWindow* window = g.NavWindow;
|
||||||
return 0.0f;
|
if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != ImGuiNavLayer_Main)
|
||||||
if ((g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != ImGuiNavLayer_Main)
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
ImGuiWindow* window = g.NavWindow;
|
|
||||||
const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
|
const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
|
||||||
const bool page_down_held = IsKeyDown(io.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown);
|
const bool page_down_held = IsKeyDown(io.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown);
|
||||||
const bool home_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home);
|
const bool home_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home);
|
||||||
@ -9533,14 +9546,14 @@ static float ImGui::NavUpdatePageUpPageDown()
|
|||||||
nav_scoring_rect_offset_y = -page_offset_y;
|
nav_scoring_rect_offset_y = -page_offset_y;
|
||||||
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
|
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
|
||||||
g.NavMoveClipDir = ImGuiDir_Up;
|
g.NavMoveClipDir = ImGuiDir_Up;
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
||||||
}
|
}
|
||||||
else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
|
else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
|
||||||
{
|
{
|
||||||
nav_scoring_rect_offset_y = +page_offset_y;
|
nav_scoring_rect_offset_y = +page_offset_y;
|
||||||
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
|
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
|
||||||
g.NavMoveClipDir = ImGuiDir_Down;
|
g.NavMoveClipDir = ImGuiDir_Down;
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
||||||
}
|
}
|
||||||
else if (home_pressed)
|
else if (home_pressed)
|
||||||
{
|
{
|
||||||
@ -9551,7 +9564,8 @@ static float ImGui::NavUpdatePageUpPageDown()
|
|||||||
if (nav_rect_rel.IsInverted())
|
if (nav_rect_rel.IsInverted())
|
||||||
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
||||||
g.NavMoveDir = ImGuiDir_Down;
|
g.NavMoveDir = ImGuiDir_Down;
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
||||||
|
// FIXME-NAV: MoveClipDir left to _None, intentional?
|
||||||
}
|
}
|
||||||
else if (end_pressed)
|
else if (end_pressed)
|
||||||
{
|
{
|
||||||
@ -9559,7 +9573,8 @@ static float ImGui::NavUpdatePageUpPageDown()
|
|||||||
if (nav_rect_rel.IsInverted())
|
if (nav_rect_rel.IsInverted())
|
||||||
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
||||||
g.NavMoveDir = ImGuiDir_Up;
|
g.NavMoveDir = ImGuiDir_Up;
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
||||||
|
// FIXME-NAV: MoveClipDir left to _None, intentional?
|
||||||
}
|
}
|
||||||
return nav_scoring_rect_offset_y;
|
return nav_scoring_rect_offset_y;
|
||||||
}
|
}
|
||||||
@ -9577,9 +9592,9 @@ static void ImGui::NavEndFrame()
|
|||||||
// Perform wrap-around in menus
|
// Perform wrap-around in menus
|
||||||
// FIXME-NAV: Wrap (not Loop) support could be handled by the scoring function and then WrapX would function without an extra frame.
|
// FIXME-NAV: Wrap (not Loop) support could be handled by the scoring function and then WrapX would function without an extra frame.
|
||||||
ImGuiWindow* window = g.NavWindow;
|
ImGuiWindow* window = g.NavWindow;
|
||||||
const ImGuiNavMoveFlags move_flags = g.NavMoveRequestFlags;
|
const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
|
||||||
const ImGuiNavMoveFlags wanted_flags = ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY;
|
const ImGuiNavMoveFlags wanted_flags = ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY;
|
||||||
if (window && NavMoveRequestButNoResultYet() && (g.NavMoveRequestFlags & wanted_flags) && (g.NavMoveRequestFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
if (window && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & wanted_flags) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
||||||
{
|
{
|
||||||
bool do_forward = false;
|
bool do_forward = false;
|
||||||
ImRect bb_rel = window->NavRectRel[g.NavLayer];
|
ImRect bb_rel = window->NavRectRel[g.NavLayer];
|
||||||
|
@ -1180,9 +1180,10 @@ enum ImGuiNavMoveFlags_
|
|||||||
ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
|
ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
|
||||||
ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness
|
ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness
|
||||||
ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
|
ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
|
||||||
ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible (used by PageUp/PageDown)
|
ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
|
||||||
ImGuiNavMoveFlags_ScrollToEdge = 1 << 6,
|
ImGuiNavMoveFlags_ScrollToEdge = 1 << 6,
|
||||||
ImGuiNavMoveFlags_Forwarded = 1 << 7
|
ImGuiNavMoveFlags_Forwarded = 1 << 7,
|
||||||
|
ImGuiNavMoveFlags_DebugNoResult = 1 << 8
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ImGuiNavLayer
|
enum ImGuiNavLayer
|
||||||
@ -1511,27 +1512,31 @@ struct ImGuiContext
|
|||||||
ImGuiKeyModFlags NavJustMovedToKeyMods;
|
ImGuiKeyModFlags NavJustMovedToKeyMods;
|
||||||
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
||||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
|
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
|
||||||
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
|
|
||||||
int NavScoringCount; // Metrics for debugging
|
|
||||||
ImGuiNavLayer 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.
|
ImGuiNavLayer 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.
|
||||||
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
|
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
|
||||||
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
|
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
|
||||||
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
|
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
|
||||||
bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
|
bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
|
||||||
bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
|
bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
|
||||||
|
|
||||||
|
// Navigation: Init & Move Requests
|
||||||
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
|
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
|
||||||
bool NavInitRequest; // Init request for appearing window to select first item
|
bool NavInitRequest; // Init request for appearing window to select first item
|
||||||
bool NavInitRequestFromMove;
|
bool NavInitRequestFromMove;
|
||||||
ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
|
ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
|
||||||
ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window)
|
ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window)
|
||||||
bool NavMoveRequest; // Move request for this frame
|
bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame()
|
||||||
bool NavMoveRequestForwardToNextFrame;
|
bool NavMoveScoringItems; // Move request submitted, still scoring incoming items
|
||||||
ImGuiNavMoveFlags NavMoveRequestFlags;
|
bool NavMoveForwardToNextFrame;
|
||||||
ImGuiKeyModFlags NavMoveRequestKeyMods;
|
ImGuiNavMoveFlags NavMoveFlags;
|
||||||
ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request
|
ImGuiKeyModFlags NavMoveKeyMods;
|
||||||
|
ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down)
|
||||||
|
ImGuiDir NavMoveDirForDebug;
|
||||||
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
|
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
|
||||||
|
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
|
||||||
|
int NavScoringCount; // Metrics for debugging
|
||||||
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
|
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
|
||||||
ImGuiNavItemData NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
||||||
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
||||||
|
|
||||||
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
||||||
@ -1714,8 +1719,6 @@ struct ImGuiContext
|
|||||||
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
||||||
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
|
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
|
||||||
NavInputSource = ImGuiInputSource_None;
|
NavInputSource = ImGuiInputSource_None;
|
||||||
NavScoringRect = ImRect();
|
|
||||||
NavScoringCount = 0;
|
|
||||||
NavLayer = ImGuiNavLayer_Main;
|
NavLayer = ImGuiNavLayer_Main;
|
||||||
NavIdTabCounter = INT_MAX;
|
NavIdTabCounter = INT_MAX;
|
||||||
NavIdIsAlive = false;
|
NavIdIsAlive = false;
|
||||||
@ -1726,11 +1729,13 @@ struct ImGuiContext
|
|||||||
NavInitRequest = false;
|
NavInitRequest = false;
|
||||||
NavInitRequestFromMove = false;
|
NavInitRequestFromMove = false;
|
||||||
NavInitResultId = 0;
|
NavInitResultId = 0;
|
||||||
NavMoveRequest = false;
|
NavMoveSubmitted = false;
|
||||||
NavMoveRequestForwardToNextFrame = false;
|
NavMoveScoringItems = false;
|
||||||
NavMoveRequestFlags = ImGuiNavMoveFlags_None;
|
NavMoveForwardToNextFrame = false;
|
||||||
NavMoveRequestKeyMods = ImGuiKeyModFlags_None;
|
NavMoveFlags = ImGuiNavMoveFlags_None;
|
||||||
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
NavMoveKeyMods = ImGuiKeyModFlags_None;
|
||||||
|
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
|
||||||
|
NavScoringCount = 0;
|
||||||
|
|
||||||
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
|
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
|
||||||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
||||||
@ -2452,7 +2457,7 @@ namespace ImGui
|
|||||||
|
|
||||||
// Gamepad/Keyboard Navigation
|
// Gamepad/Keyboard Navigation
|
||||||
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
|
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
|
||||||
IMGUI_API bool NavMoveRequestButNoResultYet(); // Should be called ~NavMoveRequestIsActiveButNoResultYet()
|
IMGUI_API bool NavMoveRequestButNoResultYet();
|
||||||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags);
|
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags);
|
||||||
IMGUI_API void NavMoveRequestCancel();
|
IMGUI_API void NavMoveRequestCancel();
|
||||||
IMGUI_API void NavMoveRequestApplyResult();
|
IMGUI_API void NavMoveRequestApplyResult();
|
||||||
|
@ -6687,10 +6687,11 @@ void ImGui::EndMenuBar()
|
|||||||
// Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
|
// Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
|
||||||
if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
||||||
{
|
{
|
||||||
|
// Try to find out if the request is for one of our child menu
|
||||||
ImGuiWindow* nav_earliest_child = g.NavWindow;
|
ImGuiWindow* nav_earliest_child = g.NavWindow;
|
||||||
while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
||||||
nav_earliest_child = nav_earliest_child->ParentWindow;
|
nav_earliest_child = nav_earliest_child->ParentWindow;
|
||||||
if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && (g.NavMoveRequestFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
||||||
{
|
{
|
||||||
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
|
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
|
||||||
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering)
|
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering)
|
||||||
@ -6700,7 +6701,7 @@ void ImGui::EndMenuBar()
|
|||||||
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
|
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
|
||||||
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
|
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
|
||||||
g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
||||||
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveRequestFlags); // Repeat
|
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags); // Repeat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user