mirror of https://github.com/ocornut/imgui
Nav: first committed pass for manual moving and manual scrolling (after a bunch of attempts) (#323)
This commit is contained in:
parent
4309b8c1ed
commit
04157da291
82
imgui.cpp
82
imgui.cpp
|
@ -662,6 +662,7 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
|
||||||
|
|
||||||
static void SetCurrentFont(ImFont* font);
|
static void SetCurrentFont(ImFont* font);
|
||||||
static void SetCurrentWindow(ImGuiWindow* window);
|
static void SetCurrentWindow(ImGuiWindow* window);
|
||||||
|
static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x);
|
||||||
static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
|
static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
|
||||||
static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond);
|
static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond);
|
||||||
static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond);
|
static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond);
|
||||||
|
@ -2364,8 +2365,7 @@ static void NavUpdate()
|
||||||
IM_ASSERT(g.NavWindow);
|
IM_ASSERT(g.NavWindow);
|
||||||
|
|
||||||
// Scroll to keep newly navigated item fully into view
|
// Scroll to keep newly navigated item fully into view
|
||||||
ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos, g.NavWindow->InnerRect.Max - g.NavWindow->Pos);
|
ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1));
|
||||||
window_rect_rel.Expand(1.0f);
|
|
||||||
//g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG]
|
//g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG]
|
||||||
if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel))
|
if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel))
|
||||||
{
|
{
|
||||||
|
@ -2394,6 +2394,7 @@ static void NavUpdate()
|
||||||
// Apply result from previous navigation directional move request
|
// Apply result from previous navigation directional move request
|
||||||
ImGui::SetActiveID(0);
|
ImGui::SetActiveID(0);
|
||||||
SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel);
|
SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel);
|
||||||
|
g.NavMoveFromClampedRefRect = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation windowing mode (change focus, move/resize window)
|
// Navigation windowing mode (change focus, move/resize window)
|
||||||
|
@ -2433,6 +2434,19 @@ static void NavUpdate()
|
||||||
g.NavWindowingDisplayAlpha = 1.0f;
|
g.NavWindowingDisplayAlpha = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move window
|
||||||
|
if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
|
||||||
|
{
|
||||||
|
const ImVec2 move_delta = ImGui::NavGetMovingDir(1);
|
||||||
|
if (move_delta.x != 0.0f || move_delta.y != 0.0f)
|
||||||
|
{
|
||||||
|
const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
|
||||||
|
g.NavWindowingTarget->PosFloat += move_delta * move_speed;
|
||||||
|
if (!(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoSavedSettings))
|
||||||
|
MarkSettingsDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsKeyDownMap(ImGuiKey_NavMenu))
|
if (!IsKeyDownMap(ImGuiKey_NavMenu))
|
||||||
{
|
{
|
||||||
// Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most)
|
// Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most)
|
||||||
|
@ -2537,16 +2551,44 @@ static void NavUpdate()
|
||||||
g.NavWindow = g.FocusedWindow;
|
g.NavWindow = g.FocusedWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback manual-scroll with NavUp/NavDown when window has no navigable item
|
// Scrolling
|
||||||
if (g.FocusedWindow && !g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down))
|
if (g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav))
|
||||||
{
|
{
|
||||||
float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
// Fallback manual-scroll with NavUp/NavDown when window has no navigable item
|
||||||
|
const float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
||||||
|
if (!g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down))
|
||||||
SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed));
|
SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed));
|
||||||
|
|
||||||
|
// Manual scroll with NavScrollXXX keys
|
||||||
|
ImVec2 scroll_dir = ImGui::NavGetMovingDir(1, 1.0f/10.0f, 10.0f);
|
||||||
|
if (scroll_dir.x != 0.0f && g.NavWindow->ScrollbarX)
|
||||||
|
{
|
||||||
|
SetWindowScrollX(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.x + scroll_dir.x * scroll_speed));
|
||||||
|
g.NavMoveFromClampedRefRect = true;
|
||||||
|
}
|
||||||
|
if (scroll_dir.y != 0.0f)
|
||||||
|
{
|
||||||
|
SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + scroll_dir.y * scroll_speed));
|
||||||
|
g.NavMoveFromClampedRefRect = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset search
|
// Reset search
|
||||||
g.NavMoveResultId = 0;
|
g.NavMoveResultId = 0;
|
||||||
g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX;
|
g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX;
|
||||||
|
if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0)
|
||||||
|
{
|
||||||
|
// When we have manually scrolled and NavId is out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items
|
||||||
|
ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1));
|
||||||
|
if (!window_rect_rel.Contains(g.NavRefRectRel))
|
||||||
|
{
|
||||||
|
float pad = g.NavWindow->CalcFontSize() * 0.5f;
|
||||||
|
window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intend of starting navigation from first fully visible item
|
||||||
|
window_rect_rel.Clip(g.NavRefRectRel);
|
||||||
|
g.NavId = 0;
|
||||||
|
}
|
||||||
|
g.NavMoveFromClampedRefRect = false;
|
||||||
|
}
|
||||||
|
|
||||||
// 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.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect();
|
g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect();
|
||||||
|
@ -4737,7 +4779,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
||||||
if (g.NavWindowingTarget == window)
|
if (g.NavWindowingTarget == window)
|
||||||
{
|
{
|
||||||
const float resize_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
|
const float resize_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
|
||||||
nav_resize_delta = NavGetMovingDir() * resize_speed;
|
nav_resize_delta = NavGetMovingDir(0) * resize_speed;
|
||||||
held |= (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f); // For coloring
|
held |= (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f); // For coloring
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5469,6 +5511,13 @@ ImVec2 ImGui::GetWindowPos()
|
||||||
return window->Pos;
|
return window->Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
|
||||||
|
{
|
||||||
|
window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
|
||||||
|
window->Scroll.x = new_scroll_x;
|
||||||
|
window->DC.CursorMaxPos.x -= window->Scroll.x;
|
||||||
|
}
|
||||||
|
|
||||||
static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
|
static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
|
||||||
{
|
{
|
||||||
window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
|
window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
|
||||||
|
@ -7043,13 +7092,28 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision)
|
||||||
return precision;
|
return precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 ImGui::NavGetMovingDir()
|
ImVec2 ImGui::NavGetMovingDir(int stick_no, float slow_factor, float fast_factor)
|
||||||
{
|
{
|
||||||
|
IM_ASSERT(stick_no >= 0 && stick_no < 2);
|
||||||
ImVec2 dir(0.0f, 0.0f);
|
ImVec2 dir(0.0f, 0.0f);
|
||||||
|
if (stick_no == 0)
|
||||||
|
{
|
||||||
if (IsKeyDownMap(ImGuiKey_NavLeft)) dir.x -= 1.0f;
|
if (IsKeyDownMap(ImGuiKey_NavLeft)) dir.x -= 1.0f;
|
||||||
if (IsKeyDownMap(ImGuiKey_NavRight)) dir.x += 1.0f;
|
if (IsKeyDownMap(ImGuiKey_NavRight)) dir.x += 1.0f;
|
||||||
if (IsKeyDownMap(ImGuiKey_NavUp)) dir.y -= 1.0f;
|
if (IsKeyDownMap(ImGuiKey_NavUp)) dir.y -= 1.0f;
|
||||||
if (IsKeyDownMap(ImGuiKey_NavDown)) dir.y += 1.0f;
|
if (IsKeyDownMap(ImGuiKey_NavDown)) dir.y += 1.0f;
|
||||||
|
}
|
||||||
|
if (stick_no == 1)
|
||||||
|
{
|
||||||
|
if (IsKeyDownMap(ImGuiKey_NavScrollLeft)) dir.x -= 1.0f;
|
||||||
|
if (IsKeyDownMap(ImGuiKey_NavScrollRight)) dir.x += 1.0f;
|
||||||
|
if (IsKeyDownMap(ImGuiKey_NavScrollUp)) dir.y -= 1.0f;
|
||||||
|
if (IsKeyDownMap(ImGuiKey_NavScrollDown)) dir.y += 1.0f;
|
||||||
|
}
|
||||||
|
if (slow_factor != 0.0f && IsKeyDownMap(ImGuiKey_NavTweakSlower))
|
||||||
|
dir *= slow_factor;
|
||||||
|
if (fast_factor != 0.0f && IsKeyDownMap(ImGuiKey_NavTweakFaster))
|
||||||
|
dir *= fast_factor;
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10458,7 +10522,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||||
}
|
}
|
||||||
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
|
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
|
||||||
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
|
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
|
||||||
if (show_clip_rects && ImGui::IsItemHovered())
|
if (show_clip_rects && (ImGui::IsItemHovered() || ImGui::IsItemFocused()))
|
||||||
{
|
{
|
||||||
ImRect clip_rect = pcmd->ClipRect;
|
ImRect clip_rect = pcmd->ClipRect;
|
||||||
ImRect vtxs_rect;
|
ImRect vtxs_rect;
|
||||||
|
@ -10482,7 +10546,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||||
buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
|
buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
|
||||||
}
|
}
|
||||||
ImGui::Selectable(buf, false);
|
ImGui::Selectable(buf, false);
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
|
||||||
overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle
|
overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle
|
||||||
}
|
}
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
|
|
5
imgui.h
5
imgui.h
|
@ -604,8 +604,13 @@ enum ImGuiKey_
|
||||||
ImGuiKey_NavRight, // e.g. Right arrow, D-Pad right
|
ImGuiKey_NavRight, // e.g. Right arrow, D-Pad right
|
||||||
ImGuiKey_NavUp, // e.g. Up arrow, D-Pad up
|
ImGuiKey_NavUp, // e.g. Up arrow, D-Pad up
|
||||||
ImGuiKey_NavDown, // e.g. Down arrow, D-Pad down
|
ImGuiKey_NavDown, // e.g. Down arrow, D-Pad down
|
||||||
|
ImGuiKey_NavScrollLeft, // e.g. Analog left
|
||||||
|
ImGuiKey_NavScrollRight,// e.g. Analog right
|
||||||
|
ImGuiKey_NavScrollUp, // e.g. Analog up
|
||||||
|
ImGuiKey_NavScrollDown, // e.g. Analog down
|
||||||
ImGuiKey_NavTweakFaster,// e.g. Shift key, R-trigger
|
ImGuiKey_NavTweakFaster,// e.g. Shift key, R-trigger
|
||||||
ImGuiKey_NavTweakSlower,// e.g. Alt key, L-trigger
|
ImGuiKey_NavTweakSlower,// e.g. Alt key, L-trigger
|
||||||
|
ImGuiKey_NavLast_,
|
||||||
|
|
||||||
ImGuiKey_COUNT
|
ImGuiKey_COUNT
|
||||||
};
|
};
|
||||||
|
|
|
@ -1904,7 +1904,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
|
||||||
static void ShowExampleAppFixedOverlay(bool* p_open)
|
static void ShowExampleAppFixedOverlay(bool* p_open)
|
||||||
{
|
{
|
||||||
ImGui::SetNextWindowPos(ImVec2(10,10));
|
ImGui::SetNextWindowPos(ImVec2(10,10));
|
||||||
if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings))
|
if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoNav))
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -423,6 +423,7 @@ struct ImGuiContext
|
||||||
ImRect NavInitDefaultResultRectRel;
|
ImRect NavInitDefaultResultRectRel;
|
||||||
bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus()
|
bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus()
|
||||||
bool NavMoveRequest; // Move request for this frame
|
bool NavMoveRequest; // Move request for this frame
|
||||||
|
bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items
|
||||||
ImGuiNavDir NavMoveDir; // West/East/North/South
|
ImGuiNavDir NavMoveDir; // West/East/North/South
|
||||||
ImGuiID NavMoveResultId; // Best move request candidate
|
ImGuiID NavMoveResultId; // Best move request candidate
|
||||||
float NavMoveResultDistBox; // Best move request candidate box distance to current NavId
|
float NavMoveResultDistBox; // Best move request candidate box distance to current NavId
|
||||||
|
@ -784,7 +785,7 @@ namespace ImGui
|
||||||
IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing);
|
IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing);
|
||||||
|
|
||||||
IMGUI_API ImVec2 NavGetTweakDelta();
|
IMGUI_API ImVec2 NavGetTweakDelta();
|
||||||
IMGUI_API ImVec2 NavGetMovingDir();
|
IMGUI_API ImVec2 NavGetMovingDir(int stick_no, float slow_factor = 0.0f, float fast_factor = 0.0f);
|
||||||
|
|
||||||
inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); }
|
inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); }
|
||||||
inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
|
inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
|
||||||
|
|
Loading…
Reference in New Issue