mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-15 09:13:13 +02:00
Merge branch 'master' into docking
# Conflicts: # backends/imgui_impl_vulkan.cpp # imgui.cpp
This commit is contained in:
289
imgui.cpp
289
imgui.cpp
@ -733,9 +733,11 @@ CODE
|
||||
Q&A: Usage
|
||||
----------
|
||||
|
||||
Q: Why is my widget not reacting when I click on it?
|
||||
Q: How can I have widgets with an empty label?
|
||||
Q: How can I have multiple widgets with the same label?
|
||||
Q: About the ID Stack system..
|
||||
- Why is my widget not reacting when I click on it?
|
||||
- How can I have widgets with an empty label?
|
||||
- How can I have multiple widgets with the same label?
|
||||
- How can I have multiple windows with the same label?
|
||||
Q: How can I display an image? What is ImTextureID, how does it works?
|
||||
Q: How can I use my own math types instead of ImVec2/ImVec4?
|
||||
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
|
||||
@ -928,6 +930,7 @@ static void NavUpdateCancelRequest();
|
||||
static void NavUpdateCreateMoveRequest();
|
||||
static float NavUpdatePageUpPageDown();
|
||||
static inline void NavUpdateAnyRequestFlag();
|
||||
static void NavUpdateCreateWrappingRequest();
|
||||
static void NavEndFrame();
|
||||
static bool NavScoreItem(ImGuiNavItemData* result);
|
||||
static void NavApplyItemToResult(ImGuiNavItemData* result);
|
||||
@ -936,6 +939,7 @@ static ImVec2 NavCalcPreferredRefPos();
|
||||
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
|
||||
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
|
||||
static void NavRestoreLayer(ImGuiNavLayer layer);
|
||||
static void NavRestoreHighlightAfterMove();
|
||||
static int FindWindowFocusIndex(ImGuiWindow* window);
|
||||
|
||||
// Error Checking and Debug Tools
|
||||
@ -2302,7 +2306,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items
|
||||
if (g.NavMoveScoringItems)
|
||||
unclipped_rect.Add(g.NavScoringRect);
|
||||
if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId)
|
||||
unclipped_rect.Add(ImRect(window->Pos + window->NavRectRel[0].Min, window->Pos + window->NavRectRel[0].Max)); // Could store and use NavJustMovedToRectRel
|
||||
unclipped_rect.Add(WindowRectRelToAbs(window, window->NavRectRel[0])); // Could store and use NavJustMovedToRectRel
|
||||
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
|
||||
@ -3835,25 +3839,26 @@ static void ImGui::UpdateMouseInputs()
|
||||
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
|
||||
{
|
||||
g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
|
||||
g.IO.MouseClickedCount[i] = 0; // Will be filled below
|
||||
g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
|
||||
g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
|
||||
g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
|
||||
g.IO.MouseDoubleClicked[i] = false;
|
||||
if (g.IO.MouseClicked[i])
|
||||
{
|
||||
bool is_repeated_click = false;
|
||||
if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime)
|
||||
{
|
||||
ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
|
||||
if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
|
||||
g.IO.MouseDoubleClicked[i] = true;
|
||||
g.IO.MouseClickedTime[i] = -g.IO.MouseDoubleClickTime * 2.0f; // Mark as "old enough" so the third click isn't turned into a double-click
|
||||
is_repeated_click = true;
|
||||
}
|
||||
if (is_repeated_click)
|
||||
g.IO.MouseClickedLastCount[i]++;
|
||||
else
|
||||
{
|
||||
g.IO.MouseClickedTime[i] = g.Time;
|
||||
}
|
||||
g.IO.MouseClickedLastCount[i] = 1;
|
||||
g.IO.MouseClickedTime[i] = g.Time;
|
||||
g.IO.MouseClickedPos[i] = g.IO.MousePos;
|
||||
g.IO.MouseDownWasDoubleClick[i] = g.IO.MouseDoubleClicked[i];
|
||||
g.IO.MouseClickedCount[i] = g.IO.MouseClickedLastCount[i];
|
||||
g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
|
||||
g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
|
||||
}
|
||||
@ -3865,9 +3870,12 @@ static void ImGui::UpdateMouseInputs()
|
||||
g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
|
||||
g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
|
||||
}
|
||||
if (!g.IO.MouseDown[i] && !g.IO.MouseReleased[i])
|
||||
g.IO.MouseDownWasDoubleClick[i] = false;
|
||||
if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
|
||||
|
||||
// We provide io.MouseDoubleClicked[] as a legacy service
|
||||
g.IO.MouseDoubleClicked[i] = (g.IO.MouseClickedCount[i] == 2);
|
||||
|
||||
// Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
|
||||
if (g.IO.MouseClicked[i])
|
||||
g.NavDisableMouseHover = false;
|
||||
}
|
||||
}
|
||||
@ -5042,7 +5050,14 @@ bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||
return g.IO.MouseDoubleClicked[button];
|
||||
return g.IO.MouseClickedCount[button] == 2;
|
||||
}
|
||||
|
||||
bool ImGui::IsMouseTripleClicked(ImGuiMouseButton button)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||
return g.IO.MouseClickedCount[button] == 3;
|
||||
}
|
||||
|
||||
// Return if a mouse click/drag went past the given threshold. Valid to call during the MouseReleased frame.
|
||||
@ -5765,7 +5780,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
|
||||
if (hovered || held)
|
||||
g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
|
||||
|
||||
if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
|
||||
if (held && g.IO.MouseClickedCount[0] == 2 && resize_grip_n == 0)
|
||||
{
|
||||
// Manual auto-fit when double-clicking
|
||||
size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
|
||||
@ -5795,7 +5810,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
|
||||
bool hovered, held;
|
||||
ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
|
||||
ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID()
|
||||
ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren);
|
||||
ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
|
||||
//GetForegroundDrawLists(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
|
||||
if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held)
|
||||
{
|
||||
@ -6028,6 +6043,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
|
||||
const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
|
||||
|
||||
// Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
|
||||
// FIXME-NAV: Might want (or not?) to set the equivalent of ImGuiButtonFlags_NoNavFocus so that mouse clicks on standard title bar items don't necessarily set nav/keyboard ref?
|
||||
const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
|
||||
g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
|
||||
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
|
||||
@ -6400,7 +6416,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
{
|
||||
// We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar.
|
||||
ImRect title_bar_rect = window->TitleBarRect();
|
||||
if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])
|
||||
if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseClickedCount[0] == 2)
|
||||
window->WantCollapseToggle = true;
|
||||
if (window->WantCollapseToggle)
|
||||
{
|
||||
@ -6622,7 +6638,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
// Inner rectangle
|
||||
// Not affected by window border size. Used by:
|
||||
// - InnerClipRect
|
||||
// - ScrollToBringRectIntoView()
|
||||
// - ScrollToRectEx()
|
||||
// - NavUpdatePageUpPageDown()
|
||||
// - Scrollbar()
|
||||
window->InnerRect.Min.x = window->Pos.x;
|
||||
@ -7248,11 +7264,16 @@ void ImGui::PopTextWrapPos()
|
||||
|
||||
static ImGuiWindow* GetCombinedRootWindow(ImGuiWindow* window, bool popup_hierarchy, bool dock_hierarchy)
|
||||
{
|
||||
window = window->RootWindow;
|
||||
if (popup_hierarchy)
|
||||
window = window->RootWindowPopupTree;
|
||||
if (dock_hierarchy)
|
||||
window = window->RootWindowDockTree;
|
||||
ImGuiWindow* last_window = NULL;
|
||||
while (last_window != window)
|
||||
{
|
||||
last_window = window;
|
||||
window = window->RootWindow;
|
||||
if (popup_hierarchy)
|
||||
window = window->RootWindowPopupTree;
|
||||
if (dock_hierarchy)
|
||||
window = window->RootWindowDockTree;
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
@ -7704,7 +7725,7 @@ void ImGui::SetItemDefaultFocus()
|
||||
|
||||
g.NavInitRequest = false;
|
||||
g.NavInitResultId = g.LastItemData.ID;
|
||||
g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos);
|
||||
g.NavInitResultRectRel = WindowRectAbsToRel(window, g.LastItemData.Rect);
|
||||
NavUpdateAnyRequestFlag();
|
||||
|
||||
// Scroll could be done in NavInitRequestApplyResult() via a opt-in flag (we however don't want regular init requests to scroll)
|
||||
@ -8658,8 +8679,8 @@ ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window, const ImRect& item_rect, ImGui
|
||||
|
||||
const bool fully_visible_x = item_rect.Min.x >= window_rect.Min.x && item_rect.Max.x <= window_rect.Max.x;
|
||||
const bool fully_visible_y = item_rect.Min.y >= window_rect.Min.y && item_rect.Max.y <= window_rect.Max.y;
|
||||
const bool can_be_fully_visible_x = item_rect.GetWidth() <= window_rect.GetWidth();
|
||||
const bool can_be_fully_visible_y = item_rect.GetHeight() <= window_rect.GetHeight();
|
||||
const bool can_be_fully_visible_x = (item_rect.GetWidth() + g.Style.ItemSpacing.x * 2.0f) <= window_rect.GetWidth();
|
||||
const bool can_be_fully_visible_y = (item_rect.GetHeight() + g.Style.ItemSpacing.y * 2.0f) <= window_rect.GetHeight();
|
||||
|
||||
if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
|
||||
{
|
||||
@ -9436,8 +9457,6 @@ void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id
|
||||
g.NavFocusScopeId = focus_scope_id;
|
||||
g.NavWindow->NavLastIds[nav_layer] = id;
|
||||
g.NavWindow->NavRectRel[nav_layer] = rect_rel;
|
||||
//g.NavDisableHighlight = false;
|
||||
//g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
||||
}
|
||||
|
||||
void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
|
||||
@ -9456,7 +9475,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
|
||||
g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
window->NavLastIds[nav_layer] = id;
|
||||
if (g.LastItemData.ID == id)
|
||||
window->NavRectRel[nav_layer] = ImRect(g.LastItemData.NavRect.Min - window->Pos, g.LastItemData.NavRect.Max - window->Pos);
|
||||
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||
|
||||
if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
||||
g.NavDisableMouseHover = true;
|
||||
@ -9636,7 +9655,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
|
||||
result->ID = g.LastItemData.ID;
|
||||
result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
result->InFlags = g.LastItemData.InFlags;
|
||||
result->RectRel = ImRect(g.LastItemData.NavRect.Min - window->Pos, g.LastItemData.NavRect.Max - window->Pos);
|
||||
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||
}
|
||||
|
||||
// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
|
||||
@ -9657,7 +9676,7 @@ static void ImGui::NavProcessItem()
|
||||
if (candidate_for_nav_default_focus || g.NavInitResultId == 0)
|
||||
{
|
||||
g.NavInitResultId = id;
|
||||
g.NavInitResultRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
|
||||
g.NavInitResultRectRel = WindowRectAbsToRel(window, nav_bb);
|
||||
}
|
||||
if (candidate_for_nav_default_focus)
|
||||
{
|
||||
@ -9704,7 +9723,7 @@ static void ImGui::NavProcessItem()
|
||||
g.NavLayer = window->DC.NavLayerCurrent;
|
||||
g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
g.NavIdIsAlive = true;
|
||||
window->NavRectRel[window->DC.NavLayerCurrent] = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); // Store item bounding box (relative to window position)
|
||||
window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9815,6 +9834,11 @@ void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
|
||||
g.NavLayer = layer;
|
||||
NavInitWindow(window, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::NavRestoreHighlightAfterMove()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
||||
}
|
||||
@ -9863,7 +9887,8 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
||||
static ImVec2 ImGui::NavCalcPreferredRefPos()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !window)
|
||||
{
|
||||
// Mouse (we need a fallback in case the mouse becomes invalid after being used)
|
||||
if (IsMousePosValid(&g.IO.MousePos))
|
||||
@ -9872,10 +9897,16 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
|
||||
}
|
||||
else
|
||||
{
|
||||
// When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item.
|
||||
const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
|
||||
ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
|
||||
ImGuiViewport* viewport = g.NavWindow->Viewport;
|
||||
// When navigation is active and mouse is disabled, pick a position around the bottom left of the currently navigated item
|
||||
// Take account of upcoming scrolling (maybe set mouse pos should be done in EndFrame?)
|
||||
ImRect rect_rel = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]);
|
||||
if (window->LastFrameActive != g.FrameCount && (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX))
|
||||
{
|
||||
ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
|
||||
rect_rel.Translate(window->Scroll - next_scroll);
|
||||
}
|
||||
ImVec2 pos = ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
|
||||
ImGuiViewport* viewport = window->Viewport;
|
||||
return ImFloor(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta.
|
||||
}
|
||||
}
|
||||
@ -9972,19 +10003,12 @@ static void ImGui::NavUpdate()
|
||||
g.NavTabbingInputableRemaining = 0;
|
||||
g.NavMoveSubmitted = g.NavMoveScoringItems = false;
|
||||
|
||||
// Apply application mouse position movement, after we had a chance to process move request result.
|
||||
// Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
|
||||
bool set_mouse_pos = false;
|
||||
if (g.NavMousePosDirty && g.NavIdIsAlive)
|
||||
{
|
||||
// Set mouse position given our knowledge of the navigated item position from last frame
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
|
||||
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
|
||||
{
|
||||
io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos();
|
||||
io.WantSetMousePos = true;
|
||||
//IMGUI_DEBUG_LOG("SetMousePos: (%.1f,%.1f)\n", io.MousePos.x, io.MousePos.y);
|
||||
}
|
||||
g.NavMousePosDirty = false;
|
||||
}
|
||||
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
|
||||
set_mouse_pos = true;
|
||||
g.NavMousePosDirty = false;
|
||||
g.NavIdIsAlive = false;
|
||||
g.NavJustTabbedId = 0;
|
||||
IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
|
||||
@ -10078,7 +10102,16 @@ static void ImGui::NavUpdate()
|
||||
if (!nav_keyboard_active && !nav_gamepad_active)
|
||||
{
|
||||
g.NavDisableHighlight = true;
|
||||
g.NavDisableMouseHover = g.NavMousePosDirty = false;
|
||||
g.NavDisableMouseHover = set_mouse_pos = false;
|
||||
}
|
||||
|
||||
// Update mouse position if requested
|
||||
// (This will take into account the possibility that a Scroll was queued in the window to offset our absolute mouse position before scroll has been applied)
|
||||
if (set_mouse_pos && (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
|
||||
{
|
||||
io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos();
|
||||
io.WantSetMousePos = true;
|
||||
//IMGUI_DEBUG_LOG("SetMousePos: (%.1f,%.1f)\n", io.MousePos.x, io.MousePos.y);
|
||||
}
|
||||
|
||||
// [DEBUG]
|
||||
@ -10087,7 +10120,7 @@ static void ImGui::NavUpdate()
|
||||
if (g.NavWindow)
|
||||
{
|
||||
ImDrawList* draw_list = GetForegroundDrawList(g.NavWindow);
|
||||
if (1) { for (int layer = 0; layer < 2; layer++) draw_list->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG]
|
||||
if (1) { for (int layer = 0; layer < 2; layer++) { ImRect r = WindowRectRelToAbs(g.NavWindow, g.NavWindow->NavRectRel[layer]); draw_list->AddRect(r.Min, r.Max, IM_COL32(255,200,0,255)); } } // [DEBUG]
|
||||
if (1) { ImU32 col = (!g.NavWindow->Hidden) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); draw_list->AddCircleFilled(p, 3.0f, col); draw_list->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
|
||||
}
|
||||
#endif
|
||||
@ -10106,10 +10139,7 @@ void ImGui::NavInitRequestApplyResult()
|
||||
SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
|
||||
g.NavIdIsAlive = true; // Mark as alive from previous frame as we got a result
|
||||
if (g.NavInitRequestFromMove)
|
||||
{
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
||||
}
|
||||
NavRestoreHighlightAfterMove();
|
||||
}
|
||||
|
||||
void ImGui::NavUpdateCreateMoveRequest()
|
||||
@ -10180,7 +10210,7 @@ void ImGui::NavUpdateCreateMoveRequest()
|
||||
// (can't focus a visible object like we can with the mouse).
|
||||
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 = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)));
|
||||
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
|
||||
{
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n");
|
||||
@ -10196,7 +10226,7 @@ void ImGui::NavUpdateCreateMoveRequest()
|
||||
if (window != NULL)
|
||||
{
|
||||
ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? window->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
||||
scoring_rect = ImRect(window->Pos + nav_rect_rel.Min, window->Pos + nav_rect_rel.Max);
|
||||
scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
|
||||
scoring_rect.TranslateY(scoring_rect_offset_y);
|
||||
scoring_rect.Min.x = ImMin(scoring_rect.Min.x + 1.0f, scoring_rect.Max.x);
|
||||
scoring_rect.Max.x = scoring_rect.Min.x;
|
||||
@ -10224,10 +10254,7 @@ void ImGui::NavMoveRequestApplyResult()
|
||||
if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
|
||||
g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
|
||||
if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
|
||||
{
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = true;
|
||||
}
|
||||
NavRestoreHighlightAfterMove();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -10245,23 +10272,17 @@ void ImGui::NavMoveRequestApplyResult()
|
||||
// Scroll to keep newly navigated item fully into view.
|
||||
if (g.NavLayer == ImGuiNavLayer_Main)
|
||||
{
|
||||
ImVec2 delta_scroll;
|
||||
if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
|
||||
{
|
||||
// FIXME: Should remove this
|
||||
float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
|
||||
delta_scroll.y = result->Window->Scroll.y - scroll_target;
|
||||
SetScrollY(result->Window, scroll_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
||||
delta_scroll = ScrollToRectEx(result->Window, rect_abs, g.NavMoveScrollFlags);
|
||||
ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel);
|
||||
ScrollToRectEx(result->Window, rect_abs, g.NavMoveScrollFlags);
|
||||
}
|
||||
|
||||
// Offset our result position so mouse position can be applied immediately after in NavUpdate()
|
||||
result->RectRel.TranslateX(-delta_scroll.x);
|
||||
result->RectRel.TranslateY(-delta_scroll.y);
|
||||
}
|
||||
|
||||
ClearActiveID();
|
||||
@ -10295,10 +10316,7 @@ void ImGui::NavMoveRequestApplyResult()
|
||||
|
||||
// Enable nav highlight
|
||||
if ((g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
|
||||
{
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
||||
}
|
||||
NavRestoreHighlightAfterMove();
|
||||
}
|
||||
|
||||
// Process NavCancel input (to close a popup, get back to parent, clear focus)
|
||||
@ -10321,6 +10339,7 @@ static void ImGui::NavUpdateCancelRequest()
|
||||
{
|
||||
// Leave the "menu" layer
|
||||
NavRestoreLayer(ImGuiNavLayer_Main);
|
||||
NavRestoreHighlightAfterMove();
|
||||
}
|
||||
else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
|
||||
{
|
||||
@ -10330,7 +10349,8 @@ static void ImGui::NavUpdateCancelRequest()
|
||||
IM_ASSERT(child_window->ChildId != 0);
|
||||
ImRect child_rect = child_window->Rect();
|
||||
FocusWindow(parent_window);
|
||||
SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, ImRect(child_rect.Min - parent_window->Pos, child_rect.Max - parent_window->Pos));
|
||||
SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_rect));
|
||||
NavRestoreHighlightAfterMove();
|
||||
}
|
||||
else if (g.OpenPopupStack.Size > 0)
|
||||
{
|
||||
@ -10357,7 +10377,7 @@ static float ImGui::NavUpdatePageUpPageDown()
|
||||
ImGuiIO& io = g.IO;
|
||||
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != ImGuiNavLayer_Main)
|
||||
if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL)
|
||||
return 0.0f;
|
||||
|
||||
const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
|
||||
@ -10367,6 +10387,9 @@ static float ImGui::NavUpdatePageUpPageDown()
|
||||
if (page_up_held == page_down_held && home_pressed == end_pressed) // Proceed if either (not both) are pressed, otherwise early out
|
||||
return 0.0f;
|
||||
|
||||
if (g.NavLayer != ImGuiNavLayer_Main)
|
||||
NavRestoreLayer(ImGuiNavLayer_Main);
|
||||
|
||||
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll)
|
||||
{
|
||||
// Fallback manual-scroll when window has no navigable item
|
||||
@ -10403,7 +10426,7 @@ static float ImGui::NavUpdatePageUpPageDown()
|
||||
// FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y
|
||||
// Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdgeY flag, we don't scroll immediately to avoid scrolling happening before nav result.
|
||||
// Preserve current horizontal position if we have any.
|
||||
nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y;
|
||||
nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f;
|
||||
if (nav_rect_rel.IsInverted())
|
||||
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
||||
g.NavMoveDir = ImGuiDir_Down;
|
||||
@ -10412,7 +10435,7 @@ static float ImGui::NavUpdatePageUpPageDown()
|
||||
}
|
||||
else if (end_pressed)
|
||||
{
|
||||
nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y;
|
||||
nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y;
|
||||
if (nav_rect_rel.IsInverted())
|
||||
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
||||
g.NavMoveDir = ImGuiDir_Up;
|
||||
@ -10433,64 +10456,66 @@ static void ImGui::NavEndFrame()
|
||||
NavUpdateWindowingOverlay();
|
||||
|
||||
// Perform wrap-around in menus
|
||||
// FIXME-NAV: Wrap may need to apply a weight bias on the other axis. e.g. 4x4 grid with 2 last items missing on last item won't handle LoopY/WrapY correctly.
|
||||
// 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;
|
||||
const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
|
||||
const ImGuiNavMoveFlags wanted_flags = ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY;
|
||||
if (window && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & wanted_flags) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
||||
if (g.NavWindow && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & wanted_flags) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
||||
NavUpdateCreateWrappingRequest();
|
||||
}
|
||||
|
||||
static void ImGui::NavUpdateCreateWrappingRequest()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
|
||||
bool do_forward = false;
|
||||
ImRect bb_rel = window->NavRectRel[g.NavLayer];
|
||||
ImGuiDir clip_dir = g.NavMoveDir;
|
||||
const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
|
||||
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||
{
|
||||
bool do_forward = false;
|
||||
ImRect bb_rel = window->NavRectRel[g.NavLayer];
|
||||
ImGuiDir clip_dir = g.NavMoveDir;
|
||||
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;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapX)
|
||||
{
|
||||
bb_rel.Min.x = bb_rel.Max.x =
|
||||
ImMax(window->SizeFull.x, window->ContentSize.x + window->WindowPadding.x * 2.0f) - window->Scroll.x;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapX)
|
||||
{
|
||||
bb_rel.TranslateY(-bb_rel.GetHeight());
|
||||
clip_dir = ImGuiDir_Up;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
|
||||
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y =
|
||||
ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y + decoration_up_height;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
||||
{
|
||||
bb_rel.TranslateX(-bb_rel.GetWidth());
|
||||
clip_dir = ImGuiDir_Left;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y + decoration_up_height;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
||||
{
|
||||
bb_rel.TranslateX(+bb_rel.GetWidth());
|
||||
clip_dir = ImGuiDir_Right;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
if (do_forward)
|
||||
{
|
||||
window->NavRectRel[g.NavLayer] = bb_rel;
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
|
||||
bb_rel.TranslateY(-bb_rel.GetHeight()); // Previous row
|
||||
clip_dir = ImGuiDir_Up;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||
{
|
||||
bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapX)
|
||||
{
|
||||
bb_rel.TranslateY(+bb_rel.GetHeight()); // Next row
|
||||
clip_dir = ImGuiDir_Down;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
||||
{
|
||||
bb_rel.TranslateX(-bb_rel.GetWidth()); // Previous column
|
||||
clip_dir = ImGuiDir_Left;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
||||
{
|
||||
bb_rel.TranslateX(+bb_rel.GetWidth()); // Next column
|
||||
clip_dir = ImGuiDir_Right;
|
||||
}
|
||||
do_forward = true;
|
||||
}
|
||||
if (!do_forward)
|
||||
return;
|
||||
window->NavRectRel[g.NavLayer] = bb_rel;
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
|
||||
}
|
||||
|
||||
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
|
||||
@ -10653,8 +10678,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
{
|
||||
ImGuiViewport* previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
|
||||
ClearActiveID();
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = true;
|
||||
NavRestoreHighlightAfterMove();
|
||||
apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
|
||||
ClosePopupsOverWindow(apply_focus_window, false);
|
||||
FocusWindow(apply_focus_window);
|
||||
@ -10706,6 +10730,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
|
||||
g.NavWindow->NavLastIds[new_nav_layer] = 0;
|
||||
NavRestoreLayer(new_nav_layer);
|
||||
NavRestoreHighlightAfterMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user