Nav: Forwarded (wrap/loop) request don't mistakenly wreck reference pos.

Amend 6656553
This commit is contained in:
ocornut 2023-05-10 15:01:02 +02:00
parent 430c05991c
commit bcfc1ad8f6
3 changed files with 19 additions and 14 deletions

View File

@ -10671,7 +10671,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
NavClearPreferredPosForAxis(ImGuiAxis_Y);
}
ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
static ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
{
if (ImFabs(dx) > ImFabs(dy))
return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
@ -11044,7 +11044,8 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wra
ImGuiContext& g = *GImGui;
IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_ ) != 0 && (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY
// In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it, NavEndFrame() will do the same test
// In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it:
// as NavEndFrame() will do the same test. It will end up calling NavUpdateCreateWrappingRequest().
if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main)
g.NavMoveFlags = (g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags;
}
@ -11369,7 +11370,7 @@ void ImGui::NavInitRequestApplyResult()
}
// Bias scoring rect ahead of scoring + update preferred pos (if missing) using source position
static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir move_dir)
static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir move_dir, ImGuiNavMoveFlags move_flags)
{
// Bias initial rect
ImGuiContext& g = *GImGui;
@ -11378,15 +11379,18 @@ static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir mo
// Initialize bias on departure if we don't have any. So mouse-click + arrow will record bias.
// - We default to L/U bias, so moving down from a large source item into several columns will land on left-most column.
// - But each successful move sets new bias on one axis, only cleared when using mouse.
if ((move_flags & ImGuiNavMoveFlags_Forwarded) == 0)
{
if (preferred_pos_rel.x == FLT_MAX)
preferred_pos_rel.x = ImMin(r.Min.x + 1.0f, r.Max.x) - rel_to_abs_offset.x;
if (preferred_pos_rel.y == FLT_MAX)
preferred_pos_rel.y = r.GetCenter().y - rel_to_abs_offset.y;
}
// Apply general bias on the other axis
if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
if ((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) && preferred_pos_rel.x != FLT_MAX)
r.Min.x = r.Max.x = preferred_pos_rel.x + rel_to_abs_offset.x;
else
else if ((move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) && preferred_pos_rel.y != FLT_MAX)
r.Min.y = r.Max.y = preferred_pos_rel.y + rel_to_abs_offset.y;
}
@ -11497,7 +11501,7 @@ void ImGui::NavUpdateCreateMoveRequest()
scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
scoring_rect.TranslateY(scoring_rect_offset_y);
if (g.NavMoveSubmitted)
NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer], g.NavMoveDir);
NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer], g.NavMoveDir, g.NavMoveFlags);
IM_ASSERT(!scoring_rect.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allow us to remove extraneous ImFabs() calls in NavScoreItem().
//GetForegroundDrawList()->AddRect(scoring_rect.Min, scoring_rect.Max, IM_COL32(255,200,0,255)); // [DEBUG]
//if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG]
@ -11785,7 +11789,9 @@ static void ImGui::NavUpdateCreateWrappingRequest()
bool do_forward = false;
ImRect bb_rel = window->NavRectRel[g.NavLayer];
ImGuiDir clip_dir = g.NavMoveDir;
const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
//const ImGuiAxis move_axis = (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
{
bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;

View File

@ -21,9 +21,9 @@
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345')
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.89.6 WIP"
#define IMGUI_VERSION_NUM 18956
#define IMGUI_VERSION_NUM 18957
#define IMGUI_HAS_TABLE
/*

View File

@ -479,7 +479,6 @@ IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, c
IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; }
IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy);
// Helper: ImVec1 (1D vector)
// (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches)