mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-04 03:58:47 +02:00
Nav: Draft internal api to forward move request with loop/wrap options. Will rework for parallel scoring of two paths (as a generalization of the NavFlattened concept). (#787)
This commit is contained in:
66
imgui.cpp
66
imgui.cpp
@ -2251,7 +2251,7 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
|
||||
|
||||
// We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
|
||||
// For example, this ensure that items in one column are not reached when moving vertically from items in another column.
|
||||
NavClampRectToVisibleAreaForMoveDir(g.NavMoveDir, cand, window->ClipRect);
|
||||
NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect);
|
||||
|
||||
// Compute distance between boxes
|
||||
// FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
|
||||
@ -3227,6 +3227,7 @@ static void ImGui::NavUpdate()
|
||||
if (g.NavMoveRequestForward == ImGuiNavForward_None)
|
||||
{
|
||||
g.NavMoveDir = ImGuiDir_None;
|
||||
g.NavMoveRequestFlags = 0;
|
||||
if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
|
||||
{
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Left;
|
||||
@ -3234,11 +3235,13 @@ static void ImGui::NavUpdate()
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Up;
|
||||
if ((allowed_dir_flags & (1<<ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Down;
|
||||
}
|
||||
g.NavMoveClipDir = g.NavMoveDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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)
|
||||
IM_ASSERT(g.NavMoveDir != ImGuiDir_None);
|
||||
// (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.NavMoveRequestForward == ImGuiNavForward_ForwardQueued);
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardActive;
|
||||
}
|
||||
@ -4547,9 +4550,11 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
int start = (int)((window->ClipRect.Min.y - pos.y) / items_height);
|
||||
int end = (int)((window->ClipRect.Max.y - pos.y) / items_height);
|
||||
if (g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Up) // 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)
|
||||
start--;
|
||||
if (g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down)
|
||||
if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down)
|
||||
end++;
|
||||
|
||||
start = ImClamp(start, 0, items_count);
|
||||
@ -5101,16 +5106,51 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla
|
||||
return is_open;
|
||||
}
|
||||
|
||||
static void NavProcessMoveRequestWrapAround(ImGuiWindow* window)
|
||||
void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0)
|
||||
{
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
|
||||
ImGui::NavMoveRequestCancel();
|
||||
g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y;
|
||||
}
|
||||
IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None);
|
||||
ImGui::NavMoveRequestCancel();
|
||||
g.NavMoveDir = move_dir;
|
||||
g.NavMoveClipDir = clip_dir;
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
|
||||
g.NavMoveRequestFlags = move_flags;
|
||||
g.NavWindow->NavRectRel[g.NavLayer] = bb_rel;
|
||||
}
|
||||
|
||||
void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != 0)
|
||||
return;
|
||||
IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
|
||||
ImRect bb_rel = window->NavRectRel[0];
|
||||
|
||||
ImGuiDir clip_dir = g.NavMoveDir;
|
||||
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||
{
|
||||
bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||
{
|
||||
bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; }
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; }
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::EndPopup()
|
||||
@ -5120,7 +5160,7 @@ void ImGui::EndPopup()
|
||||
IM_ASSERT(g.CurrentPopupStack.Size > 0);
|
||||
|
||||
// Make all menus and popups wrap around for now, may need to expose that policy.
|
||||
NavProcessMoveRequestWrapAround(g.CurrentWindow);
|
||||
NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY);
|
||||
|
||||
End();
|
||||
}
|
||||
|
Reference in New Issue
Block a user