Merge branch 'master' into docking

# Conflicts:
#	docs/CHANGELOG.txt
#	imgui.cpp
#	imgui.h
#	imgui_demo.cpp
#	imgui_widgets.cpp
This commit is contained in:
ocornut 2024-10-18 18:59:27 +02:00
commit 4e2126ee44
14 changed files with 421 additions and 286 deletions

View File

@ -41,10 +41,12 @@ HOW TO UPDATE?
Breaking changes:
- Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with newly
exposed and reworked features. Kept inline redirection enum (will obsolete).
- The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
- This removes the requirement to redefine it for backends which are e.g. storing
descriptor sets or other 64-bits structures when building on 32-bits archs.
It therefore simplify various building scripts/helpers.
descriptor sets or other 64-bits structures when building on 32-bits archs
(namely our DX12 and Vulkan backends). It therefore simplify various building scripts/helpers.
- You may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID'
when passing your types to functions taking ImTextureID values, e.g. ImGui::Image().
In doubt it is almost always better to do an intermediate intptr_t cast, since it
@ -67,13 +69,30 @@ Other changes:
state to draw callbacks. (#6969, #5834, #7468, #3590)
- IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
- Error Handling: turned a few more functions into recoverable errors. (#1651)
- Nav: added io.ConfigNavEscapeClearFocusWindow to clear focused window on Escape. (#3200)
- Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing
back into same window later.
- Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
window. (#3200)
- Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
when e.g activating the item with mouse, then ctrl+tabbing back and forth.
- Nav (Keyboard/Gamepad navigation):
- Nav: added io.ConfigNavCursorVisibleAuto and io.ConfigNavCursorVisibleAlways to configure
visibility of navigation cursor. (#1074, #2048, #7237, #8059, #3200, #787)
- Set io.ConfigNavCursorVisibleAuto = true (default) to enable automatic toggling
of cursor visibility (mouse click hide the cursor, arrow keys makes it visible).
- Set io.ConfigNavCursorVisibleAlways to keep cursor always visible.
- Nav: added NavSetCursorVisible(bool visible) function to manipulate visibility of
navigation cursor (e.g. set default state, or after some actions). (#1074, #2048, #7237, #8059)
- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
- Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
- Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
- Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
is for some reason your app relies on imgui focus to take other decisions.
- Nav: pressing escape to hide nav highlight doesn't clear location from when Ctrl+Tabbing
back into same window later.
- Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
window. (#3200)
- Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
when e.g activating the item with mouse, then Ctrl+Tabbing back and forth.
- Disabled: clicking a disabled item focuses parent window. (#8064)
- InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
not display navigation highlight. Properly navigation on it by default. (#8057)
- InvisibleButton: added ImGuiButtonFlags_EnableNav to enable navigation. (#8057)
- Tooltips: fixed incorrect tooltip positioning when using keyboard/gamepad navigation
(1.91.3 regression). (#8036)
- DrawList: AddCallback() added an optional size parameter allowing to copy and
@ -89,6 +108,12 @@ Other changes:
preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
- InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is
enabled or not. (#6417)
- InputScalar: added an assert to clarify that ImGuiInputTextFlags_EnterReturnsTrue is not
supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065)
- imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render
OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE.
Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help).
(#7927, #7187, #6591, #6607) [@pthom]
- Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in
ImGui_ImplXXXX_RenderState structures during render loop. (#6969, #5834, #7468, #3590)
- Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler

View File

@ -405,7 +405,7 @@ DirectX9:
```
```cpp
DirectX11:
- ImTextureID should contain a 'ID3D11ShaderResourceView*' (poiter)
- ImTextureID should contain a 'ID3D11ShaderResourceView*' (pointer)
- See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
```
```cpp

View File

@ -302,14 +302,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16-bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
- nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab)
! nav: never clear NavId on some setup (e.g. gamepad centric)
- nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable.
- nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view?
- nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window"
- nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
- nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
- nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch)
- nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name)
- nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem
- nav: holding space to repeat a button doesn't show button activated during hold.
- nav: NavFlattened: init requests don't work properly on flattened siblings.
- nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings.
- nav: NavFlattened: ESC on a flattened child should select something.

View File

@ -83,10 +83,13 @@
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
// Only works in combination with IMGUI_ENABLE_FREETYPE.
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg.
// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions.
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
//---- Use stb_truetype to build and rasterize the font atlas (default)

238
imgui.cpp
View File

@ -438,6 +438,7 @@ CODE
- likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2024/10/18 (1.91.4) - renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor (for consistency with newly exposed and reworked features). Kept inline redirection enum (will obsolete).
- 2024/10/14 (1.91.4) - moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool (note the inverted value!).
kept legacy names (will obsolete) + code that copies settings once the first time. Dynamically changing the old value won't work. Switch to using the new value!
@ -1426,6 +1427,15 @@ ImGuiIO::ImGuiIO()
FontAllowUserScaling = false;
DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
// Keyboard/Gamepad Navigation options
ConfigNavSwapGamepadButtons = false;
ConfigNavMoveSetMousePos = false;
ConfigNavCaptureKeyboard = true;
ConfigNavEscapeClearFocusItem = true;
ConfigNavEscapeClearFocusWindow = false;
ConfigNavCursorVisibleAuto = true;
ConfigNavCursorVisibleAlways = false;
// Docking options (when ImGuiConfigFlags_DockingEnable is set)
ConfigDockingNoSplit = false;
ConfigDockingWithShift = false;
@ -1445,10 +1455,6 @@ ImGuiIO::ImGuiIO()
#else
ConfigMacOSXBehaviors = false;
#endif
ConfigNavSwapGamepadButtons = false;
ConfigNavMoveSetMousePos = false;
ConfigNavCaptureKeyboard = true;
ConfigNavEscapeClearFocusWindow = false;
ConfigInputTrickleEventQueue = true;
ConfigInputTextCursorBlink = true;
ConfigInputTextEnterKeepActive = false;
@ -3558,7 +3564,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
case ImGuiCol_TextLink: return "TextLink";
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
case ImGuiCol_DragDropTarget: return "DragDropTarget";
case ImGuiCol_NavHighlight: return "NavHighlight";
case ImGuiCol_NavCursor: return "NavCursor";
case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
@ -3763,26 +3769,26 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
}
}
void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags)
void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags)
{
ImGuiContext& g = *GImGui;
if (id != g.NavId)
return;
if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
if (!g.NavCursorVisible && !(flags & ImGuiNavRenderCursorFlags_AlwaysDraw))
return;
if (id == g.LastItemData.ID && (g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
if (id == g.LastItemData.ID && (g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
return;
ImGuiWindow* window = g.CurrentWindow;
if (window->DC.NavHideHighlightOneFrame)
return;
float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
float rounding = (flags & ImGuiNavRenderCursorFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
ImRect display_rect = bb;
display_rect.ClipWith(window->ClipRect);
const float thickness = 2.0f;
if (flags & ImGuiNavHighlightFlags_Compact)
if (flags & ImGuiNavRenderCursorFlags_Compact)
{
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
}
else
{
@ -3791,7 +3797,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
bool fully_visible = window->ClipRect.Contains(display_rect);
if (!fully_visible)
window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
if (!fully_visible)
window->DrawList->PopClipRect();
}
@ -3976,8 +3982,13 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
ViewportCreatedCount = PlatformWindowsCreatedCount = 0;
ViewportFocusedStampCount = 0;
NavCursorVisible = false;
NavHighlightItemUnderNav = false;
NavMousePosDirty = false;
NavIdIsAlive = false;
NavId = 0;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavLayer = ImGuiNavLayer_Main;
NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
@ -3985,10 +3996,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
NavHighlightActivatedTimer = 0.0f;
NavInputSource = ImGuiInputSource_Keyboard;
NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
NavIdIsAlive = false;
NavMousePosDirty = false;
NavDisableHighlight = true;
NavDisableMouseHover = false;
NavCursorHideFrames = 0;
NavAnyRequest = false;
NavInitRequest = false;
@ -4064,7 +4072,6 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
DragSpeedDefaultRatio = 1.0f / 100.0f;
DisabledAlphaBackup = 0.0f;
DisabledStackSize = 0;
LockMarkEdited = 0;
TooltipOverrideCount = 0;
TooltipPreviousWindow = NULL;
@ -4474,10 +4481,10 @@ ImGuiID ImGui::GetHoveredID()
void ImGui::MarkItemEdited(ImGuiID id)
{
// This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
// This marking is to be able to provide info for IsItemDeactivatedAfterEdit().
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
ImGuiContext& g = *GImGui;
if (g.LockMarkEdited > 0)
if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
return;
if (g.ActiveId == id || g.ActiveId == 0)
{
@ -4551,11 +4558,11 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0, "Invalid flags for IsItemHovered()!");
if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
if (g.NavHighlightItemUnderNav && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride))
{
if (!IsItemFocused())
return false;
if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
if ((g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false;
if (flags & ImGuiHoveredFlags_ForTooltip)
@ -4590,11 +4597,11 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
// Test if interactions on this window are blocked by an active popup or modal.
// The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here.
if (!IsWindowContentHoverable(window, flags) && !(g.LastItemData.InFlags & ImGuiItemFlags_NoWindowHoverableCheck))
if (!IsWindowContentHoverable(window, flags) && !(g.LastItemData.ItemFlags & ImGuiItemFlags_NoWindowHoverableCheck))
return false;
// Test if the item is disabled
if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
if ((g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false;
// Special handling for calling after Begin() which represent the title bar or tab.
@ -4604,7 +4611,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return false;
// Test if using AllowOverlap and overlapped
if ((g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap) && id != 0)
if ((g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap) && id != 0)
if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0)
if (g.HoveredIdPreviousFrame != g.LastItemData.ID)
return false;
@ -4637,7 +4644,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
// (this does not rely on LastItemData it can be called from a ButtonBehavior() call not following an ItemAdd() call)
// FIXME-LEGACY: the 'ImGuiItemFlags item_flags' parameter was added on 2023-06-28.
// If you used this in your legacy/custom widgets code:
// - Commonly: if your ItemHoverable() call comes after an ItemAdd() call: pass 'item_flags = g.LastItemData.InFlags'.
// - Commonly: if your ItemHoverable() call comes after an ItemAdd() call: pass 'item_flags = g.LastItemData.ItemFlags'.
// - Rare: otherwise you may pass 'item_flags = 0' (ImGuiItemFlags_None) unless you want to benefit from special behavior handled by ItemHoverable.
bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flags)
{
@ -4722,7 +4729,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
}
#endif
if (g.NavDisableMouseHover && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
if (g.NavHighlightItemUnderNav && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
return false;
return true;
@ -4747,7 +4754,7 @@ void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemS
{
ImGuiContext& g = *GImGui;
g.LastItemData.ID = item_id;
g.LastItemData.InFlags = in_flags;
g.LastItemData.ItemFlags = in_flags;
g.LastItemData.StatusFlags = item_flags;
g.LastItemData.Rect = g.LastItemData.NavRect = item_rect;
}
@ -4923,7 +4930,8 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
ImGuiContext& g = *GImGui;
FocusWindow(window);
SetActiveID(window->MoveId, window);
g.NavDisableHighlight = true;
if (g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = false;
g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
g.ActiveIdNoClearOnFocusLoss = true;
SetActiveIdUsingAllKeyboardKeys();
@ -5027,12 +5035,13 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
}
}
// Initiate moving window when clicking on empty space or title bar.
// Initiate focusing and moving window when clicking on empty space or title bar.
// Initiate focusing window when clicking on a disabled item.
// Handle left-click and right-click focus.
void ImGui::UpdateMouseMovingWindowEndFrame()
{
ImGuiContext& g = *GImGui;
if (g.ActiveId != 0 || g.HoveredId != 0)
if (g.ActiveId != 0 || (g.HoveredId != 0 && !g.HoveredIdIsDisabled))
return;
// Unless we just made a window/popup appear
@ -5058,7 +5067,8 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
g.MovingWindow = NULL;
// Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already)
// Cancel moving if clicked over an item which was disabled or inhibited by popups
// (when g.HoveredIdIsDisabled == true && g.HoveredId == 0 we are inhibited by popups, when g.HoveredIdIsDisabled == true && g.HoveredId != 0 we are over a disabled item)0 already)
if (g.HoveredIdIsDisabled)
g.MovingWindow = NULL;
}
@ -5072,7 +5082,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
// With right mouse button we close popups without changing focus based on where the mouse is aimed
// Instead, focus will be restored to the window under the bottom-most closed popup.
// (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger)
if (g.IO.MouseClicked[1])
if (g.IO.MouseClicked[1] && g.HoveredId == 0)
{
// Find the top-most window between HoveredWindow and the top-most Modal Window.
// This is where we can trim the popup stack.
@ -5376,7 +5386,7 @@ void ImGui::NewFrame()
//IM_ASSERT(g.IO.KeyAlt == IsKeyDown(ImGuiKey_LeftAlt) || IsKeyDown(ImGuiKey_RightAlt));
//IM_ASSERT(g.IO.KeySuper == IsKeyDown(ImGuiKey_LeftSuper) || IsKeyDown(ImGuiKey_RightSuper));
// Update gamepad/keyboard navigation
// Update keyboard/gamepad navigation
NavUpdate();
// Update mouse input state
@ -6103,7 +6113,7 @@ bool ImGui::IsAnyItemActive()
bool ImGui::IsAnyItemFocused()
{
ImGuiContext& g = *GImGui;
return g.NavId != 0 && !g.NavDisableHighlight;
return g.NavId != 0 && g.NavCursorVisible;
}
bool ImGui::IsItemVisible()
@ -6335,11 +6345,11 @@ void ImGui::EndChild()
if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !nav_flattened)
{
ItemAdd(bb, child_window->ChildId);
RenderNavHighlight(bb, child_window->ChildId);
RenderNavCursor(bb, child_window->ChildId);
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow)
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_Compact);
RenderNavCursor(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavRenderCursorFlags_Compact);
}
else
{
@ -6899,7 +6909,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
g.NavWindowingAccumDeltaSize = ImMax(g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size); // We need Pos+Size >= clmap_rect.Min, so Size >= clmap_rect.Min - Pos, so size_delta >= clmap_rect.Min - window->Pos - window->Size
g.NavWindowingToggleLayer = false;
g.NavDisableMouseHover = true;
g.NavHighlightItemUnderNav = true;
resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaSize);
if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
@ -7001,7 +7011,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
// Title bar only
const float backup_border_size = style.FrameBorderSize;
g.Style.FrameBorderSize = window->WindowBorderSize;
ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && g.NavCursorVisible) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
if (window->ViewportOwned)
title_bar_col |= IM_COL32_A_MASK; // No alpha (we don't support is_docking_transparent_payload here because simpler and less meaningful, but could with a bit of code shuffle/reuse)
RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
@ -8418,7 +8428,7 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
if (g.NavWindow != window)
{
SetNavWindow(window);
if (window && g.NavDisableMouseHover)
if (window && g.NavHighlightItemUnderNav)
g.NavMousePosDirty = true;
g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
g.NavLayer = ImGuiNavLayer_Main;
@ -9186,7 +9196,7 @@ void ImGui::FocusItem()
return;
}
ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight | ImGuiNavMoveFlags_NoSelect;
ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible | ImGuiNavMoveFlags_NoSelect;
ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
SetNavWindow(window);
NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
@ -9221,7 +9231,7 @@ void ImGui::SetKeyboardFocusHere(int offset)
SetNavWindow(window);
ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight;
ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible;
ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
if (offset == -1)
@ -10406,9 +10416,9 @@ static void ImGui::UpdateMouseInputs()
g.MouseStationaryTimer = mouse_stationary ? (g.MouseStationaryTimer + io.DeltaTime) : 0.0f;
//IMGUI_DEBUG_LOG("%.4f\n", g.MouseStationaryTimer);
// If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
// If mouse moved we re-enable mouse hovering in case it was disabled by keyboard/gamepad. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
g.NavDisableMouseHover = false;
g.NavHighlightItemUnderNav = false;
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
{
@ -10448,9 +10458,9 @@ static void ImGui::UpdateMouseInputs()
// We provide io.MouseDoubleClicked[] as a legacy service
io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2);
// Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
// Clicking any mouse button reactivate mouse hovering which may have been deactivated by keyboard/gamepad navigation
if (io.MouseClicked[i])
g.NavDisableMouseHover = false;
g.NavHighlightItemUnderNav = false;
}
}
@ -10918,7 +10928,7 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, Im
void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
{
ImGuiContext& g = *GImGui;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasShortcut;
g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasShortcut;
g.NextItemData.Shortcut = key_chord;
g.NextItemData.ShortcutFlags = flags;
}
@ -10930,7 +10940,7 @@ void ImGui::ItemHandleShortcut(ImGuiID id)
ImGuiInputFlags flags = g.NextItemData.ShortcutFlags;
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetNextItemShortcut) == 0); // Passing flags not supported by SetNextItemShortcut()!
if (g.LastItemData.InFlags & ImGuiItemFlags_Disabled)
if (g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled)
return;
if (flags & ImGuiInputFlags_Tooltip)
{
@ -11461,7 +11471,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
g.LastItemData.ID = id;
g.LastItemData.Rect = bb;
g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
g.LastItemData.InFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
// Note: we don't copy 'g.NextItemData.SelectionUserData' to an hypothetical g.LastItemData.SelectionUserData: since the former is not cleared.
@ -11479,7 +11489,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
// We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null.
// If we crash on a NULL g.NavWindow we need to fix the bug elsewhere.
if (!(g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
if (!(g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
{
// FIMXE-NAV: investigate changing the window tests into a simple 'if (g.NavFocusScopeId == g.CurrentFocusScopeId)' test.
window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
@ -11489,12 +11499,12 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
NavProcessItem();
}
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasShortcut)
if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasShortcut)
ItemHandleShortcut(id);
}
// Lightweight clear of SetNextItemXXX data.
g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
g.NextItemData.HasFlags = ImGuiNextItemDataFlags_None;
g.NextItemData.ItemFlags = ImGuiItemFlags_None;
#ifdef IMGUI_ENABLE_TEST_ENGINE
@ -11524,7 +11534,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!");
}
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
//if ((g.LastItemData.InFlags & ImGuiItemFlags_NoNav) == 0)
//if ((g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav) == 0)
// window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG]
#endif
@ -11723,7 +11733,7 @@ void ImGui::Unindent(float indent_w)
void ImGui::SetNextItemWidth(float item_width)
{
ImGuiContext& g = *GImGui;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasWidth;
g.NextItemData.Width = item_width;
}
@ -11734,7 +11744,7 @@ void ImGui::PushItemWidth(float item_width)
ImGuiWindow* window = g.CurrentWindow;
window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width
window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
}
void ImGui::PushMultiItemsWidths(int components, float w_full)
@ -11753,7 +11763,7 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
prev_split = next_split;
}
window->DC.ItemWidth = ImMax(prev_split, 1.0f);
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
}
void ImGui::PopItemWidth()
@ -11776,7 +11786,7 @@ float ImGui::CalcItemWidth()
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
float w;
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
w = g.NextItemData.Width;
else
w = window->DC.ItemWidth;
@ -12878,7 +12888,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
ImRect r_avoid;
if (!g.NavDisableHighlight && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos)
if (g.NavCursorVisible && g.NavHighlightItemUnderNav && !g.IO.ConfigNavMoveSetMousePos)
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
else
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
@ -12898,6 +12908,23 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
// In our terminology those should be interchangeable, yet right now this is super confusing.
// Those two functions are merely a legacy artifact, so at minimum naming should be clarified.
void ImGui::SetNavCursorVisible(bool visible)
{
ImGuiContext& g = *GImGui;
if (g.IO.ConfigNavCursorVisibleAlways)
visible = true;
g.NavCursorVisible = visible;
}
// (was called NavRestoreHighlightAfterMove() before 1.91.4)
void ImGui::SetNavCursorVisibleAfterMove()
{
ImGuiContext& g = *GImGui;
if (g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = true;
g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
}
void ImGui::SetNavWindow(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
@ -12959,9 +12986,9 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
g.NavDisableMouseHover = true;
else
g.NavDisableHighlight = true;
g.NavHighlightItemUnderNav = true;
else if (g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = false;
// Clear preferred scoring position (NavMoveRequestApplyResult() will tend to restore it)
NavClearPreferredPosForAxis(ImGuiAxis_X);
@ -12984,7 +13011,7 @@ static float inline NavScoreItemDistInterval(float cand_min, float cand_max, flo
return 0.0f;
}
// Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
// Scoring function for keyboard/gamepad directional navigation. Based on https://gist.github.com/rygorous/6981057
static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
{
ImGuiContext& g = *GImGui;
@ -13133,9 +13160,9 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
result->Window = window;
result->ID = g.LastItemData.ID;
result->FocusScopeId = g.CurrentFocusScopeId;
result->InFlags = g.LastItemData.InFlags;
result->ItemFlags = g.LastItemData.ItemFlags;
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
if (result->InFlags & ImGuiItemFlags_HasSelectionUserData)
if (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData)
{
IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
result->SelectionUserData = g.NextItemData.SelectionUserData; // INTENTIONAL: At this point this field is not cleared in NextItemData. Avoid unnecessary copy to LastItemData.
@ -13158,7 +13185,7 @@ static void ImGui::NavProcessItem()
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiID id = g.LastItemData.ID;
const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags;
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221)
if (window->DC.NavIsScrollPushableX == false)
@ -13220,7 +13247,7 @@ static void ImGui::NavProcessItem()
SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath
g.NavFocusScopeId = g.CurrentFocusScopeId;
g.NavIdIsAlive = true;
if (g.LastItemData.InFlags & ImGuiItemFlags_HasSelectionUserData)
if (g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
{
IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
g.NavLastValidSelectionUserData = g.NextItemData.SelectionUserData; // INTENTIONAL: At this point this field is not cleared in NextItemData. Avoid unnecessary copy to LastItemData.
@ -13341,7 +13368,7 @@ void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGu
ImGuiContext& g = *GImGui;
g.NavMoveScoringItems = false;
g.LastItemData.ID = tree_node_data->ID;
g.LastItemData.InFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper).
g.LastItemData.ItemFlags = tree_node_data->ItemFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper).
g.LastItemData.NavRect = tree_node_data->NavRect;
NavApplyItemToResult(result); // Result this instead of implementing a NavApplyPastTreeNodeToResult()
NavClearPreferredPosForAxis(ImGuiAxis_Y);
@ -13427,13 +13454,6 @@ void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
}
}
void ImGui::NavRestoreHighlightAfterMove()
{
ImGuiContext& g = *GImGui;
g.NavDisableHighlight = false;
g.NavDisableMouseHover = g.NavMousePosDirty = true;
}
static inline void ImGui::NavUpdateAnyRequestFlag()
{
ImGuiContext& g = *GImGui;
@ -13482,7 +13502,7 @@ static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
// Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
if ((g.NavDisableHighlight || !g.NavDisableMouseHover || !window) && !activated_shortcut)
if ((!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window) && !activated_shortcut)
return ImGuiInputSource_Mouse;
else
return ImGuiInputSource_Keyboard; // or Nav in general
@ -13586,11 +13606,14 @@ static void ImGui::NavUpdate()
NavMoveRequestApplyResult();
g.NavTabbingCounter = 0;
g.NavMoveSubmitted = g.NavMoveScoringItems = false;
if (g.NavCursorHideFrames > 0)
if (--g.NavCursorHideFrames == 0)
g.NavCursorVisible = true;
// 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)
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
if (g.NavCursorVisible && g.NavHighlightItemUnderNav && g.NavWindow)
set_mouse_pos = true;
g.NavMousePosDirty = false;
IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
@ -13606,7 +13629,7 @@ static void ImGui::NavUpdate()
// Set output flags for user application
io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
io.NavVisible = (io.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL);
io.NavVisible = (io.NavActive && g.NavId != 0 && g.NavCursorVisible) || (g.NavWindowingTarget != NULL);
// Process NavCancel input (to close a popup, get back to parent, clear focus)
NavUpdateCancelRequest();
@ -13614,7 +13637,7 @@ static void ImGui::NavUpdate()
// Process manual activation request
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
g.NavActivateFlags = ImGuiActivateFlags_None;
if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
if (g.NavId != 0 && g.NavCursorVisible && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
{
const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
@ -13639,7 +13662,9 @@ static void ImGui::NavUpdate()
}
}
if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
g.NavDisableHighlight = true;
g.NavCursorVisible = false;
else if (g.IO.ConfigNavCursorVisibleAlways && g.NavCursorHideFrames == 0)
g.NavCursorVisible = true;
if (g.NavActivateId != 0)
IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
@ -13696,8 +13721,8 @@ static void ImGui::NavUpdate()
// Always prioritize mouse highlight if navigation is disabled
if (!nav_keyboard_active && !nav_gamepad_active)
{
g.NavDisableHighlight = true;
g.NavDisableMouseHover = set_mouse_pos = false;
g.NavCursorVisible = false;
g.NavHighlightItemUnderNav = set_mouse_pos = false;
}
// Update mouse position if requested
@ -13732,7 +13757,7 @@ void ImGui::NavInitRequestApplyResult()
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
g.NavJustMovedToKeyMods = 0;
g.NavJustMovedToIsTabbing = false;
g.NavJustMovedToHasSelectionData = (result->InFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
}
// Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
@ -13743,7 +13768,7 @@ void ImGui::NavInitRequestApplyResult()
if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
g.NavLastValidSelectionUserData = result->SelectionUserData;
if (g.NavInitRequestFromMove)
NavRestoreHighlightAfterMove();
SetNavCursorVisibleAfterMove();
}
// Bias scoring rect ahead of scoring + update preferred pos (if missing) using source position
@ -13840,7 +13865,8 @@ void ImGui::NavUpdateCreateMoveRequest()
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "<NULL>", g.NavLayer);
g.NavInitRequest = g.NavInitRequestFromMove = true;
g.NavInitResult.ID = 0;
g.NavDisableHighlight = false;
if (g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = true;
}
// When using gamepad, we project the reference nav bounding box into window visible area.
@ -13904,7 +13930,7 @@ void ImGui::NavUpdateCreateTabbingRequest()
// See NavProcessItemForTabbingRequest() for a description of the various forward/backward tabbing cases with and without wrapping.
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
if (nav_keyboard_active)
g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavDisableHighlight == true && g.ActiveId == 0) ? 0 : +1;
g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavCursorVisible == false && g.ActiveId == 0) ? 0 : +1;
else
g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate;
@ -13936,9 +13962,9 @@ void ImGui::NavMoveRequestApplyResult()
if (result == NULL)
{
if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavHighlight;
if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
NavRestoreHighlightAfterMove();
g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavCursorVisible;
if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
SetNavCursorVisibleAfterMove();
NavClearPreferredPosForAxis(axis); // On a failed move, clear preferred pos for this axis.
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveSubmitted but not led to a result!\n");
return;
@ -13991,7 +14017,7 @@ void ImGui::NavMoveRequestApplyResult()
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
g.NavJustMovedToIsTabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
g.NavJustMovedToHasSelectionData = (result->InFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
//IMGUI_DEBUG_LOG_NAV("[nav] NavJustMovedFromFocusScopeId = 0x%08X, NavJustMovedToFocusScopeId = 0x%08X\n", g.NavJustMovedFromFocusScopeId, g.NavJustMovedToFocusScopeId);
}
@ -14011,7 +14037,7 @@ void ImGui::NavMoveRequestApplyResult()
}
// Tabbing: Activates Inputable, otherwise only Focus
if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->InFlags & ImGuiItemFlags_Inputable) == 0)
if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->ItemFlags & ImGuiItemFlags_Inputable) == 0)
g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
// Activate
@ -14023,9 +14049,9 @@ void ImGui::NavMoveRequestApplyResult()
g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
}
// Enable nav highlight
if ((g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
NavRestoreHighlightAfterMove();
// Make nav cursor visible
if ((g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
SetNavCursorVisibleAfterMove();
}
// Process Escape/NavCancel input (to close a popup, get back to parent, clear focus)
@ -14049,7 +14075,7 @@ static void ImGui::NavUpdateCancelRequest()
{
// Leave the "menu" layer
NavRestoreLayer(ImGuiNavLayer_Main);
NavRestoreHighlightAfterMove();
SetNavCursorVisibleAfterMove();
}
else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow)
{
@ -14059,7 +14085,7 @@ static void ImGui::NavUpdateCancelRequest()
IM_ASSERT(child_window->ChildId != 0);
FocusWindow(parent_window);
SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect()));
NavRestoreHighlightAfterMove();
SetNavCursorVisibleAfterMove();
}
else if (g.OpenPopupStack.Size > 0 && g.OpenPopupStack.back().Window != NULL && !(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
{
@ -14070,11 +14096,13 @@ static void ImGui::NavUpdateCancelRequest()
{
// Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
// FIXME-NAV: This should happen on window appearing.
if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
g.NavWindow->NavLastIds[0] = 0;
if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow)
if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
g.NavWindow->NavLastIds[0] = 0;
// Clear nav focus
g.NavId = 0;
if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow)
g.NavId = 0;
if (g.IO.ConfigNavEscapeClearFocusWindow)
FocusWindow(NULL);
}
@ -14408,7 +14436,7 @@ static void ImGui::NavUpdateWindowing()
const float NAV_MOVE_SPEED = 800.0f;
const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
g.NavDisableMouseHover = true;
g.NavHighlightItemUnderNav = true;
ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaPos);
if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
{
@ -14426,7 +14454,7 @@ static void ImGui::NavUpdateWindowing()
// Investigate for each of them: ClearActiveID(), NavRestoreHighlightAfterMove(), NavRestoreLastChildNavWindow(), ClosePopupsOverWindow(), NavInitWindow()
ImGuiViewport* previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
ClearActiveID();
NavRestoreHighlightAfterMove();
SetNavCursorVisibleAfterMove();
ClosePopupsOverWindow(apply_focus_window, false);
FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
apply_focus_window = g.NavWindow;
@ -14478,7 +14506,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();
SetNavCursorVisibleAfterMove();
}
}
}
@ -14619,7 +14647,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
// Rely on keeping other window->LastItemXXX fields intact.
source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
KeepAliveID(source_id);
bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.InFlags);
bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.ItemFlags);
if (is_hovered && g.IO.MouseClicked[mouse_button])
{
SetActiveID(source_id, window);
@ -16181,7 +16209,7 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window)
// We need to take account of the possibility that mouse may become invalid.
// Popups/Tooltip always set ViewportAllowPlatformMonitorExtend so GetWindowAllowedExtentRect() will return full monitor bounds.
ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.BeginPopupStack.back().OpenMousePos;
bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow);
bool use_mouse_ref = (!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !g.NavWindow);
bool mouse_valid = IsMousePosValid(&mouse_ref);
if ((window->Appearing || (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_ChildMenu))) && (!use_mouse_ref || mouse_valid))
window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
@ -21558,7 +21586,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId);
Text("NavActivateFlags: %04X", g.NavActivateFlags);
Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
Text("NavCursorVisible: %d, NavHighlightItemUnderNav: %d", g.NavCursorVisible, g.NavHighlightItemUnderNav);
Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
Text("NavFocusRoute[] = ");
for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
@ -21698,7 +21726,7 @@ bool ImGui::DebugBreakButton(const char* label, const char* description_of_locat
ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z);
ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z);
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
RenderFrame(bb.Min, bb.Max, GetColorU32(col4f), true, g.Style.FrameRounding);
RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, g.Style.ButtonTextAlign, &bb);

53
imgui.h
View File

@ -29,7 +29,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.91.4 WIP"
#define IMGUI_VERSION_NUM 19134
#define IMGUI_VERSION_NUM 19136
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch
@ -589,7 +589,7 @@ namespace ImGui
// the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x
// - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
// - Format string may also be set to NULL or use the default format ("%f" or "%d").
// - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
// - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For keyboard/gamepad navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
// - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used.
// - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum.
// - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them.
@ -928,10 +928,12 @@ namespace ImGui
IMGUI_API void PopClipRect();
// Focus, Activation
// - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item"
IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window.
IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of of a newly appearing window.
IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
// Keyboard/Gamepad Navigation
IMGUI_API void SetNavCursorVisible(bool visible); // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse.
// Overlapping mode
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
@ -1024,7 +1026,7 @@ namespace ImGui
// - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
// Inputs Utilities: Mouse specific
// Inputs Utilities: Mouse
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
// - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
// - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold')
@ -1115,8 +1117,8 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programmatically giving it focus)
ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y)
ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
ImGuiWindowFlags_NoNavInputs = 1 << 16, // No gamepad/keyboard navigation within the window
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB)
ImGuiWindowFlags_NoNavInputs = 1 << 16, // No keyboard/gamepad navigation within the window
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with keyboard/gamepad navigation (e.g. skipped by CTRL+TAB)
ImGuiWindowFlags_UnsavedDocument = 1 << 18, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
ImGuiWindowFlags_NoDocking = 1 << 19, // Disable docking of this window
ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
@ -1158,7 +1160,7 @@ enum ImGuiChildFlags_
ImGuiChildFlags_AutoResizeY = 1 << 5, // Enable auto-resizing height. Read "IMPORTANT: Size measurement" details above.
ImGuiChildFlags_AlwaysAutoResize = 1 << 6, // Combined with AutoResizeX/AutoResizeY. Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED.
ImGuiChildFlags_FrameStyle = 1 << 7, // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding.
ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow keyboard/gamepad navigation to cross over parent border to this child or between sibling child windows.
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@ -1193,7 +1195,7 @@ enum ImGuiInputTextFlags_
// Inputs
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function.
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
@ -1365,7 +1367,7 @@ enum ImGuiHoveredFlags_
ImGuiHoveredFlags_AllowWhenOverlappedByItem = 1 << 8, // IsItemHovered() only: Return true even if the item uses AllowOverlap mode and is overlapped by another hoverable item.
ImGuiHoveredFlags_AllowWhenOverlappedByWindow = 1 << 9, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window.
ImGuiHoveredFlags_AllowWhenDisabled = 1 << 10, // IsItemHovered() only: Return true even if the item is disabled
ImGuiHoveredFlags_NoNavOverride = 1 << 11, // IsItemHovered() only: Disable using gamepad/keyboard navigation state when active, always query mouse
ImGuiHoveredFlags_NoNavOverride = 1 << 11, // IsItemHovered() only: Disable using keyboard/gamepad navigation state when active, always query mouse
ImGuiHoveredFlags_AllowWhenOverlapped = ImGuiHoveredFlags_AllowWhenOverlappedByItem | ImGuiHoveredFlags_AllowWhenOverlappedByWindow,
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows,
@ -1752,7 +1754,7 @@ enum ImGuiCol_
ImGuiCol_TextLink, // Hyperlink color
ImGuiCol_TextSelectedBg,
ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target
ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item
ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible
ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active
ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active
@ -1762,6 +1764,7 @@ enum ImGuiCol_
ImGuiCol_TabActive = ImGuiCol_TabSelected, // [renamed in 1.90.9]
ImGuiCol_TabUnfocused = ImGuiCol_TabDimmed, // [renamed in 1.90.9]
ImGuiCol_TabUnfocusedActive = ImGuiCol_TabDimmedSelected, // [renamed in 1.90.9]
ImGuiCol_NavHighlight = ImGuiCol_NavCursor, // [renamed in 1.91.4]
#endif
};
@ -1821,7 +1824,7 @@ enum ImGuiButtonFlags_
ImGuiButtonFlags_MouseButtonRight = 1 << 1, // React on right mouse button
ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
//ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft,
ImGuiButtonFlags_EnableNav = 1 << 3, // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default.
};
// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
@ -2305,7 +2308,7 @@ struct ImGuiIO
// Configuration // Default value
//------------------------------------------------------------------
ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Keyboard/Gamepad navigation options, etc.
ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame.
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. May change every frame.
@ -2321,6 +2324,15 @@ struct ImGuiIO
ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
ImVec2 DisplayFramebufferScale; // = (1, 1) // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale.
// Keyboard/Gamepad Navigation options
bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
bool ConfigNavMoveSetMousePos; // = false // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true.
bool ConfigNavCaptureKeyboard; // = true // Sets io.WantCaptureKeyboard when io.NavActive is set.
bool ConfigNavEscapeClearFocusItem; // = true // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).
bool ConfigNavCursorVisibleAuto; // = true // Using directional navigation key makes the cursor visible. Mouse click hides the cursor.
bool ConfigNavCursorVisibleAlways; // = false // Navigation cursor is always visible.
// Docking options (when ImGuiConfigFlags_DockingEnable is set)
bool ConfigDockingNoSplit; // = false // Simplified docking mode: disable window splitting, so docking is limited to merging multiple windows together into tab-bars.
bool ConfigDockingWithShift; // = false // Enable docking with holding Shift key (reduce visual noise, allows dropping in wider space)
@ -2337,10 +2349,6 @@ struct ImGuiIO
// (you can visualize and interact with all options in 'Demo->Configuration')
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
bool ConfigNavMoveSetMousePos; // = false // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true.
bool ConfigNavCaptureKeyboard; // = true // Sets io.WantCaptureKeyboard when io.NavActive is set.
bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape (when no item is active, no popup open etc.) clears focused window + navigation id/highlight.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only).
@ -2458,7 +2466,7 @@ struct ImGuiIO
bool WantSetMousePos; // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when io.ConfigNavMoveSetMousePos is enabled.
bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!
bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
bool NavVisible; // Keyboard/Gamepad navigation highlight is visible and allowed (will handle ImGuiKey_NavXXX events).
float Framerate; // Estimate of application framerate (rolling average over 60 frames, based on io.DeltaTime), in frame per second. Solely for convenience. Slow applications may not want to use a moving average or may want to reset underlying buffers occasionally.
int MetricsRenderVertices; // Vertices output during last call to Render()
int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3
@ -3872,8 +3880,8 @@ namespace ImGui
//-- OBSOLETED in 1.89 (from August 2022)
//IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // --> Use new ImageButton() signature (explicit item id, regular FramePadding). Refer to code in 1.91 if you want to grab a copy of this version.
//-- OBSOLETED in 1.88 (from May 2022)
//static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
//static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value.
//static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
//static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value.
//-- OBSOLETED in 1.86 (from November 2021)
//IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper.
//-- OBSOLETED in 1.85 (from August 2021)
@ -3956,10 +3964,7 @@ namespace ImGui
#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// RENAMED IMGUI_DISABLE_METRICS_WINDOW > IMGUI_DISABLE_DEBUG_TOOLS in 1.88 (from June 2022)
#if defined(IMGUI_DISABLE_METRICS_WINDOW) && !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS)
#define IMGUI_DISABLE_DEBUG_TOOLS
#endif
#if defined(IMGUI_DISABLE_METRICS_WINDOW) && defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
#ifdef IMGUI_DISABLE_METRICS_WINDOW
#error IMGUI_DISABLE_METRICS_WINDOW was renamed to IMGUI_DISABLE_DEBUG_TOOLS, please use new name.
#endif

View File

@ -543,6 +543,20 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::SeparatorText("Keyboard/Gamepad Navigation");
ImGui::Checkbox("io.ConfigNavSwapGamepadButtons", &io.ConfigNavSwapGamepadButtons);
ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard);
ImGui::Checkbox("io.ConfigNavEscapeClearFocusItem", &io.ConfigNavEscapeClearFocusItem);
ImGui::SameLine(); HelpMarker("Pressing Escape clears focused item.");
ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
ImGui::Checkbox("io.ConfigNavCursorVisibleAuto", &io.ConfigNavCursorVisibleAuto);
ImGui::SameLine(); HelpMarker("Using directional navigation key makes the cursor visible. Mouse click hides the cursor.");
ImGui::Checkbox("io.ConfigNavCursorVisibleAlways", &io.ConfigNavCursorVisibleAlways);
ImGui::SameLine(); HelpMarker("Navigation cursor is always visible.");
ImGui::SeparatorText("Docking");
ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", &io.ConfigFlags, ImGuiConfigFlags_DockingEnable);
ImGui::SameLine();
@ -581,14 +595,6 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Unindent();
}
ImGui::SeparatorText("Navigation");
ImGui::Checkbox("io.ConfigNavSwapGamepadButtons", &io.ConfigNavSwapGamepadButtons);
ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard);
ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
ImGui::SeparatorText("Widgets");
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
@ -1070,7 +1076,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
// The following examples are passed for documentation purpose but may not be useful to most users.
// Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
// 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or gamepad/keyboard is being used.
// 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or keyboard/gamepad is being used.
// With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
ImGui::Button("Manual", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))

View File

@ -232,7 +232,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
@ -297,7 +297,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
@ -363,7 +363,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);

View File

@ -145,7 +145,7 @@ struct ImGuiLocEntry; // A localization entry.
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
struct ImGuiMultiSelectState; // Multi-selection persistent state (for focused selection).
struct ImGuiMultiSelectTempData; // Multi-selection temporary state (while traversing).
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
struct ImGuiNavItemData; // Result of a keyboard/gamepad directional navigation move query result
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
struct ImGuiNextItemData; // Storage for SetNextItem** functions
@ -183,7 +183,7 @@ typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // F
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
typedef int ImGuiNavRenderCursorFlags; // -> enum ImGuiNavRenderCursorFlags_//Flags: for RenderNavCursor()
typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
typedef int ImGuiNextItemDataFlags; // -> enum ImGuiNextItemDataFlags_ // Flags: for SetNextItemXXX() functions
typedef int ImGuiNextWindowDataFlags; // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions
@ -834,8 +834,8 @@ enum ImGuiDataTypePrivate_
//-----------------------------------------------------------------------------
// Extend ImGuiItemFlags
// - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags.
// - output: stored in g.LastItemData.InFlags
// - input: PushItemFlag() manipulates g.CurrentItemFlags, g.NextItemData.ItemFlags, ItemAdd() calls may add extra flags too.
// - output: stored in g.LastItemData.ItemFlags
enum ImGuiItemFlagsPrivate_
{
// Controlled by user
@ -844,7 +844,8 @@ enum ImGuiItemFlagsPrivate_
ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover.
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
ImGuiItemFlags_NoMarkEdited = 1 << 16, // false // Skip calling MarkItemEdited()
// Controlled by widget code
ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
@ -897,9 +898,8 @@ enum ImGuiInputTextFlagsPrivate_
{
// [Internal]
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data
ImGuiInputTextFlags_MergedItem = 1 << 28, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 29, // For internal use by InputScalar() and TempInputScalar()
ImGuiInputTextFlags_MergedItem = 1 << 27, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 28, // For internal use by InputScalar() and TempInputScalar()
};
// Extend ImGuiButtonFlags_
@ -919,7 +919,7 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
ImGuiButtonFlags_NoKeyModsAllowed = 1 << 16, // disable mouse interaction if a key modifier is held
ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated (FIXME: this is essentially used every time an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags)
ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated (FIXME: this is essentially used every time an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.ItemFlags)
ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
@ -958,7 +958,7 @@ enum ImGuiSelectableFlagsPrivate_
enum ImGuiTreeNodeFlagsPrivate_
{
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, but reversed trees (#6517)
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517)
ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
};
@ -1228,7 +1228,7 @@ enum ImGuiNextItemDataFlags_
struct ImGuiNextItemData
{
ImGuiNextItemDataFlags Flags;
ImGuiNextItemDataFlags HasFlags; // Called HasFlags instead of Flags to avoid mistaking this
ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
// Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem()
ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData()
@ -1242,14 +1242,14 @@ struct ImGuiNextItemData
ImGuiID StorageId; // Set by SetNextItemStorageID()
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; }
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
inline void ClearFlags() { HasFlags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
};
// Status storage for the last submitted item
struct ImGuiLastItemData
{
ImGuiID ID;
ImGuiItemFlags InFlags; // See ImGuiItemFlags_
ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
ImRect Rect; // Full rectangle
ImRect NavRect; // Navigation scoring rectangle (not displayed)
@ -1269,7 +1269,7 @@ struct ImGuiTreeNodeStackData
{
ImGuiID ID;
ImGuiTreeNodeFlags TreeFlags;
ImGuiItemFlags InFlags; // Used for nav landing
ImGuiItemFlags ItemFlags; // Used for nav landing
ImRect NavRect; // Used for nav landing
};
@ -1568,12 +1568,18 @@ enum ImGuiScrollFlags_
ImGuiScrollFlags_MaskY_ = ImGuiScrollFlags_KeepVisibleEdgeY | ImGuiScrollFlags_KeepVisibleCenterY | ImGuiScrollFlags_AlwaysCenterY,
};
enum ImGuiNavHighlightFlags_
enum ImGuiNavRenderCursorFlags_
{
ImGuiNavHighlightFlags_None = 0,
ImGuiNavHighlightFlags_Compact = 1 << 1, // Compact highlight, no padding
ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse.
ImGuiNavHighlightFlags_NoRounding = 1 << 3,
ImGuiNavRenderCursorFlags_None = 0,
ImGuiNavRenderCursorFlags_Compact = 1 << 1, // Compact highlight, no padding/distance from focused item
ImGuiNavRenderCursorFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) even when g.NavCursorVisible == false, aka even when using the mouse.
ImGuiNavRenderCursorFlags_NoRounding = 1 << 3,
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiNavHighlightFlags_None = ImGuiNavRenderCursorFlags_None, // Renamed in 1.91.4
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
ImGuiNavHighlightFlags_NoRounding = ImGuiNavRenderCursorFlags_NoRounding, // Renamed in 1.91.4
#endif
};
enum ImGuiNavMoveFlags_
@ -1594,7 +1600,7 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_IsPageMove = 1 << 11, // Identify a PageDown/PageUp request.
ImGuiNavMoveFlags_Activate = 1 << 12, // Activate/select target item.
ImGuiNavMoveFlags_NoSelect = 1 << 13, // Don't trigger selection by not setting g.NavJustMovedTo
ImGuiNavMoveFlags_NoSetNavHighlight = 1 << 14, // Do not alter the visible state of keyboard vs mouse nav highlight
ImGuiNavMoveFlags_NoSetNavCursorVisible = 1 << 14, // Do not alter the nav cursor visible state
ImGuiNavMoveFlags_NoClearActiveId = 1 << 15, // (Experimental) Do not clear active id when applying move result
};
@ -1612,17 +1618,17 @@ struct ImGuiNavItemData
ImGuiID ID; // Init,Move // Best candidate item ID
ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID
ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space
ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags
ImGuiItemFlags ItemFlags; // ????,Move // Best candidate item flags
float DistBox; // Move // Best candidate box distance to current NavId
float DistCenter; // Move // Best candidate center distance to current NavId
float DistAxial; // Move // Best candidate axial distance to current NavId
ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionUserData() value. Valid if (InFlags & ImGuiItemFlags_HasSelectionUserData)
ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionUserData() value. Valid if (ItemFlags & ImGuiItemFlags_HasSelectionUserData)
ImGuiNavItemData() { Clear(); }
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
void Clear() { Window = NULL; ID = FocusScopeId = 0; ItemFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
};
// Storage for PushFocusScope()
// Storage for PushFocusScope(), g.FocusScopeStack[], g.NavFocusRoute[]
struct ImGuiFocusScopeData
{
ImGuiID ID;
@ -2329,9 +2335,15 @@ struct ImGuiContext
int PlatformWindowsCreatedCount; // Unique sequential creation counter (mostly for testing/debugging)
int ViewportFocusedStampCount; // Every time the front-most window changes, we stamp its viewport with an incrementing counter
// Gamepad/keyboard Navigation
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
// Keyboard/Gamepad Navigation
bool NavCursorVisible; // Nav focus cursor/rectangle is visible? We hide it after a mouse click. We show it after a nav move.
bool NavHighlightItemUnderNav; // Disable mouse hovering highlight. Highlight navigation focused item instead of mouse hovered item.
//bool NavDisableHighlight; // Old name for !g.NavCursorVisible before 1.91.4 (2024/10/18). OPPOSITE VALUE (g.NavDisableHighlight == !g.NavCursorVisible)
//bool NavDisableMouseHover; // Old name for g.NavHighlightItemUnderNav before 1.91.1 (2024/10/18) this was called When user starts using keyboard/gamepad, we hide mouse hovering highlight until mouse is touched again.
bool NavMousePosDirty; // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default)
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
ImGuiID NavId; // Focused item for navigation
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
@ -2345,10 +2357,7 @@ struct ImGuiContext
ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
bool NavMousePosDirty; // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (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 NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
ImS8 NavCursorHideFrames;
// Navigation: Init & Move Requests
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
@ -2380,7 +2389,7 @@ struct ImGuiContext
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyChord NavJustMovedToKeyMods;
bool NavJustMovedToIsTabbing; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
bool NavJustMovedToHasSelectionData; // Copy of move result's InFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
@ -2485,7 +2494,6 @@ struct ImGuiContext
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled()
short DisabledStackSize;
short LockMarkEdited;
short TooltipOverrideCount;
ImGuiWindow* TooltipPreviousWindow; // Window of last tooltip submitted during the frame
ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined
@ -3265,7 +3273,7 @@ namespace ImGui
// Basic Accessors
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; }
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.ItemFlags; }
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
@ -3334,7 +3342,7 @@ namespace ImGui
IMGUI_API bool BeginComboPreview();
IMGUI_API void EndComboPreview();
// Gamepad/Keyboard Navigation
// Keyboard/Gamepad Navigation
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
IMGUI_API void NavInitRequestApplyResult();
IMGUI_API bool NavMoveRequestButNoResultYet();
@ -3347,7 +3355,7 @@ namespace ImGui
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API void NavHighlightActivated(ImGuiID id);
IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis);
IMGUI_API void NavRestoreHighlightAfterMove();
IMGUI_API void SetNavCursorVisibleAfterMove();
IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX();
IMGUI_API void SetNavWindow(ImGuiWindow* window);
IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
@ -3519,6 +3527,8 @@ namespace ImGui
IMGUI_API void RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_rect);
// Typing-Select API
// (provide Windows Explorer style "select items by typing partial name" + "cycle through items by typing same letter" feature)
// (this is currently not documented nor used by main library, but should work. See "widgets_typingselect" in imgui_test_suite for usage code. Please let us know if you use this!)
IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None);
IMGUI_API int TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
@ -3638,7 +3648,10 @@ namespace ImGui
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None); // Navigation highlight
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4
#endif
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow);
@ -3779,9 +3792,8 @@ namespace ImGui
// Obsolete functions
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89
inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
//inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89
//inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
//inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():

View File

@ -3139,7 +3139,7 @@ void ImGui::TableHeader(const char* label)
if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
}
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding);
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding);
if (held)
table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;

View File

@ -505,7 +505,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Default behavior inherited from item flags
// Note that _both_ ButtonFlags and ItemFlags are valid sources, so copy one into the item_flags and only check that.
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
if (flags & ImGuiButtonFlags_AllowOverlap)
item_flags |= ImGuiItemFlags_AllowOverlap;
@ -559,7 +559,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
}
// Process initial action
if (!(flags & ImGuiButtonFlags_NoKeyModsAllowed) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
const bool mods_ok = !(flags & ImGuiButtonFlags_NoKeyModsAllowed) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt);
if (mods_ok)
{
if (mouse_button_clicked != -1 && g.ActiveId != id)
{
@ -606,7 +607,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if (!has_repeated_at_least_once)
pressed = true;
if (!(flags & ImGuiButtonFlags_NoNavFocus))
SetFocusID(id, window);
SetFocusID(id, window); // FIXME: Lack of FocusWindow() call here is inconsistent with other paths. Research why.
ClearActiveID();
}
}
@ -618,13 +619,13 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
pressed = true;
}
if (pressed)
g.NavDisableHighlight = true;
if (pressed && g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = false;
}
// Gamepad/Keyboard handling
// Keyboard/Gamepad navigation handling
// We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover)
if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav)
if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
hovered = true;
if (g.NavActivateDownId == id)
@ -687,8 +688,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
}
ClearActiveID();
}
if (!(flags & ImGuiButtonFlags_NoNavFocus))
g.NavDisableHighlight = true;
if (!(flags & ImGuiButtonFlags_NoNavFocus) && g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = false;
}
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{
@ -738,7 +739,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
if (g.LogEnabled)
@ -785,11 +786,12 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiBut
ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
ItemSize(size);
if (!ItemAdd(bb, id))
if (!ItemAdd(bb, id, NULL, (flags & ImGuiButtonFlags_EnableNav) ? ImGuiItemFlags_None : ImGuiItemFlags_NoNav))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
RenderNavCursor(bb, id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags);
return pressed;
@ -815,7 +817,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
// Render
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
const ImU32 text_col = GetColorU32(ImGuiCol_Text);
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir);
@ -856,7 +858,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
ImU32 bg_col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
if (hovered)
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact);
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
ImU32 cross_col = GetColorU32(ImGuiCol_Text);
ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
@ -885,7 +887,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
ImU32 text_col = GetColorU32(ImGuiCol_Text);
if (hovered || held)
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact);
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
if (dock_node)
RenderArrowDockMenu(window->DrawList, bb.Min, g.FontSize, text_col);
@ -1096,7 +1098,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& imag
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
if (bg_col.w > 0.0f)
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
@ -1154,7 +1156,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
ItemSize(total_bb, style.FramePadding.y);
const bool is_visible = ItemAdd(total_bb, id);
const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
const bool is_multi_select = (g.LastItemData.ItemFlags & ImGuiItemFlags_IsMultiSelect) != 0;
if (!is_visible)
if (!is_multi_select || !g.BoxSelectState.UnclipMode || !g.BoxSelectState.UnclipRect.Overlaps(total_bb)) // Extra layer of "no logic clip" for box-select support
{
@ -1184,10 +1186,10 @@ bool ImGui::Checkbox(const char* label, bool* v)
}
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
const bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
const bool mixed_value = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
if (is_visible)
{
RenderNavHighlight(total_bb, id);
RenderNavCursor(total_bb, id);
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
if (mixed_value)
@ -1289,7 +1291,7 @@ bool ImGui::RadioButton(const char* label, bool active)
if (pressed)
MarkItemEdited(id);
RenderNavHighlight(total_bb, id);
RenderNavCursor(total_bb, id);
const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
if (active)
@ -1429,7 +1431,7 @@ bool ImGui::TextLink(const char* label)
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_None);
RenderNavCursor(bb, id);
if (hovered)
SetMouseCursor(ImGuiMouseCursor_Hand);
@ -1860,7 +1862,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
// Render shape
const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
if (!(flags & ImGuiComboFlags_NoPreview))
window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
if (!(flags & ImGuiComboFlags_NoArrowButton))
@ -2566,7 +2568,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
}
if (g.ActiveId != id)
return false;
if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
if ((g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
return false;
switch (data_type)
@ -2613,7 +2615,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (format == NULL)
format = DataTypeGetInfo(data_type)->PrintFmt;
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags);
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
if (!temp_input_is_active)
{
@ -2662,7 +2664,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
// Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderNavHighlight(frame_bb, id);
RenderNavCursor(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
// Drag behavior
@ -3053,14 +3055,14 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
if (decimal_precision > 0)
{
input_delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
input_delta /= 100.0f; // Keyboard/Gamepad tweak speeds in % of slider bounds
if (tweak_slow)
input_delta /= 10.0f;
}
else
{
if ((v_range_f >= -100.0f && v_range_f <= 100.0f && v_range_f != 0.0f) || tweak_slow)
input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / v_range_f; // Gamepad/keyboard tweak speeds in integer steps
input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / v_range_f; // Keyboard/Gamepad tweak speeds in integer steps
else
input_delta /= 100.0f;
}
@ -3108,7 +3110,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
}
if (set_new_value)
if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
if ((g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
set_new_value = false;
if (set_new_value)
@ -3213,7 +3215,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (format == NULL)
format = DataTypeGetInfo(data_type)->PrintFmt;
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags);
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
if (!temp_input_is_active)
{
@ -3244,7 +3246,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
// Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderNavHighlight(frame_bb, id);
RenderNavCursor(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
// Slider behavior
@ -3379,7 +3381,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
if (format == NULL)
format = DataTypeGetInfo(data_type)->PrintFmt;
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags);
const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
if (clicked || g.NavActivateId == id)
{
@ -3393,7 +3395,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
// Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderNavHighlight(frame_bb, id);
RenderNavCursor(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
// Slider behavior
@ -3587,7 +3589,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
ClearActiveID();
g.CurrentWindow->DC.CursorPos = bb.Min;
g.LastItemData.InFlags |= ImGuiItemFlags_AllowDuplicateId;
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId;
bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
if (init)
{
@ -3605,6 +3607,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
{
// FIXME: May need to clarify display behavior if format doesn't contain %.
// "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405
ImGuiContext& g = *GImGui;
const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
char fmt_buf[32];
char data_buf[32];
@ -3614,8 +3617,8 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
ImStrTrimBlanks(data_buf);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
bool value_changed = false;
if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
{
@ -3634,6 +3637,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
}
// Only mark as edited if new value is different
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
if (value_changed)
MarkItemEdited(id);
@ -3644,7 +3648,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
void ImGui::SetNextItemRefVal(ImGuiDataType data_type, void* p_data)
{
ImGuiContext& g = *GImGui;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasRefVal;
g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasRefVal;
memcpy(&g.NextItemData.RefVal, p_data, DataTypeGetInfo(data_type)->Size);
}
@ -3658,11 +3662,12 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
ImGuiContext& g = *GImGui;
ImGuiStyle& style = g.Style;
IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
if (format == NULL)
format = DataTypeGetInfo(data_type)->PrintFmt;
void* p_data_default = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue;
void* p_data_default = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue;
char buf[64];
if ((flags & ImGuiInputTextFlags_DisplayEmptyRefVal) && DataTypeCompare(data_type, p_data, p_data_default) == 0)
@ -3670,8 +3675,10 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
else
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
flags |= (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
// Disable the MarkItemEdited() call in InputText but keep ImGuiItemStatusFlags_Edited.
// We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
bool value_changed = false;
if (p_step == NULL)
@ -3723,6 +3730,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
PopID();
EndGroup();
}
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
if (value_changed)
MarkItemEdited(g.LastItemData.ID);
@ -4126,6 +4135,7 @@ ImGuiInputTextState::ImGuiInputTextState()
{
memset(this, 0, sizeof(*this));
Stb = IM_NEW(ImStbTexteditState);
memset(Stb, 0, sizeof(*Stb));
}
ImGuiInputTextState::~ImGuiInputTextState()
@ -4469,16 +4479,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
// Ensure mouse cursor is set even after switching to keyboard/gamepad mode. May generalize further? (#6417)
bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags | ImGuiItemFlags_NoNavDisableMouseHover);
bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags | ImGuiItemFlags_NoNavDisableMouseHover);
if (hovered)
SetMouseCursor(ImGuiMouseCursor_TextInput);
if (hovered && g.NavDisableMouseHover)
if (hovered && g.NavHighlightItemUnderNav)
hovered = false;
// We are only allowed to access the state if we are already the active widget.
ImGuiInputTextState* state = GetInputTextState(id);
if (g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly)
if (g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly)
flags |= ImGuiInputTextFlags_ReadOnly;
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
@ -5098,7 +5108,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Render frame
if (!is_multiline)
{
RenderNavHighlight(frame_bb, id);
RenderNavCursor(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
}
@ -5305,7 +5315,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (g.LastItemData.ID == 0 || g.LastItemData.ID != GetWindowScrollbarID(draw_window, ImGuiAxis_Y))
{
g.LastItemData.ID = id;
g.LastItemData.InFlags = item_data_backup.InFlags;
g.LastItemData.ItemFlags = item_data_backup.ItemFlags;
g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
}
}
@ -5320,7 +5330,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
if (value_changed)
MarkItemEdited(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
@ -5634,7 +5644,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// Drag and Drop Target
// NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
{
bool accepted_drag_drop = false;
if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
@ -6110,7 +6120,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
else
window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding);
}
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
{
if (g.Style.FrameBorderSize > 0.0f)
@ -6201,8 +6211,9 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
bool allow_opt_datatype = !(flags & ImGuiColorEditFlags_DataTypeMask_);
if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
return;
ImGuiContext& g = *GImGui;
g.LockMarkEdited++;
PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
ImGuiColorEditFlags opts = g.ColorEditOptions;
if (allow_opt_inputs)
{
@ -6244,8 +6255,8 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
}
g.ColorEditOptions = opts;
PopItemFlag();
EndPopup();
g.LockMarkEdited--;
}
void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
@ -6254,8 +6265,9 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
return;
ImGuiContext& g = *GImGui;
g.LockMarkEdited++;
PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
if (allow_opt_picker)
{
ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
@ -6284,8 +6296,8 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
if (allow_opt_picker) Separator();
CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
}
PopItemFlag();
EndPopup();
g.LockMarkEdited--;
}
//-------------------------------------------------------------------------
@ -6416,7 +6428,7 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
ImGuiStorage* storage = window->DC.StateStorage;
bool is_open;
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasOpen)
{
if (g.NextItemData.OpenCond & ImGuiCond_Always)
{
@ -6462,7 +6474,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
tree_node_data->ID = g.LastItemData.ID;
tree_node_data->TreeFlags = flags;
tree_node_data->InFlags = g.LastItemData.InFlags;
tree_node_data->ItemFlags = g.LastItemData.ItemFlags;
tree_node_data->NavRect = g.LastItemData.NavRect;
window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
}
@ -6511,7 +6523,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f);
// Compute open and multi-select states before ItemAdd() as it clear NextItem data.
ImGuiID storage_id = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasStorageID) ? g.NextItemData.StorageId : id;
ImGuiID storage_id = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasStorageID) ? g.NextItemData.StorageId : id;
bool is_open = TreeNodeUpdateNextOpen(storage_id, flags);
bool is_visible;
@ -6564,7 +6576,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
}
ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None;
if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap))
if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap))
button_flags |= ImGuiButtonFlags_AllowOverlap;
if (!is_leaf)
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
@ -6576,7 +6588,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
const bool is_multi_select = (g.LastItemData.ItemFlags & ImGuiItemFlags_IsMultiSelect) != 0;
if (is_multi_select) // We absolutely need to distinguish open vs select so _OpenOnArrow comes by default
flags |= (flags & ImGuiTreeNodeFlags_OpenOnMask_) == 0 ? ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick : ImGuiTreeNodeFlags_OpenOnArrow;
@ -6623,7 +6635,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if ((flags & ImGuiTreeNodeFlags_OpenOnMask_) == 0 || (g.NavActivateId == id && !is_multi_select))
toggled = true; // Single click
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
toggled |= is_mouse_x_over_arrow && !g.NavHighlightItemUnderNav; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2)
toggled = true; // Double click
}
@ -6672,15 +6684,15 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// Render
{
const ImU32 text_col = GetColorU32(ImGuiCol_Text);
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact;
ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact;
if (is_multi_select)
nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
if (display_frame)
{
// Framed type
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
if (flags & ImGuiTreeNodeFlags_Bullet)
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
else if (!is_leaf)
@ -6700,7 +6712,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
}
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
if (flags & ImGuiTreeNodeFlags_Bullet)
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
else if (!is_leaf)
@ -6793,7 +6805,7 @@ void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems)
return;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen;
g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasOpen;
g.NextItemData.OpenVal = is_open;
g.NextItemData.OpenCond = (ImU8)(cond ? cond : ImGuiCond_Always);
}
@ -6804,7 +6816,7 @@ void ImGui::SetNextItemStorageID(ImGuiID storage_id)
ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems)
return;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasStorageID;
g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasStorageID;
g.NextItemData.StorageId = storage_id;
}
@ -6930,7 +6942,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
is_visible = ItemAdd(bb, id, NULL, extra_item_flags);
}
const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
const bool is_multi_select = (g.LastItemData.ItemFlags & ImGuiItemFlags_IsMultiSelect) != 0;
if (!is_visible)
if (!is_multi_select || !g.BoxSelectState.UnclipMode || !g.BoxSelectState.UnclipRect.Overlaps(bb)) // Extra layer of "no logic clip" for box-select support (would be more overhead to add to ItemAdd)
return false;
@ -6958,7 +6970,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; }
if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; }
if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }
if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
// Multi-selection support (header)
const bool was_selected = selected;
@ -6990,13 +7002,14 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
selected = pressed = true;
}
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with keyboard/gamepad
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
{
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
if (!g.NavHighlightItemUnderNav && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
{
SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
g.NavDisableHighlight = true;
if (g.IO.ConfigNavCursorVisibleAuto)
g.NavCursorVisible = false;
}
}
if (pressed)
@ -7021,10 +7034,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
}
if (g.NavId == id)
{
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding;
ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding;
if (is_multi_select)
nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
RenderNavHighlight(bb, id, nav_highlight_flags);
nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
RenderNavCursor(bb, id, nav_render_cursor_flags);
}
}
@ -7040,7 +7053,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
// Automatically close popups
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.InFlags & ImGuiItemFlags_AutoClosePopups))
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups))
CloseCurrentPopup();
if (disabled_item && !disabled_global)
@ -7195,7 +7208,7 @@ int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count,
else
idx = TypingSelectFindBestLeadingMatch(req, items_count, get_item_name_func, user_data);
if (idx != -1)
NavRestoreHighlightAfterMove();
SetNavCursorVisibleAfterMove();
return idx;
}
@ -7394,7 +7407,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
ImRect box_select_r = bs->BoxSelectRectCurr;
box_select_r.ClipWith(scope_rect);
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavHighlight)); // FIXME-MULTISELECT: Styling
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT: Styling
// Scroll
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
@ -8619,8 +8632,13 @@ void ImGui::EndMenuBar()
IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check (FIXME: Seems unnecessary)
FocusWindow(window);
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.NavDisableMouseHover = g.NavMousePosDirty = true;
// FIXME-NAV: How to deal with this when not using g.IO.ConfigNavCursorVisibleAuto?
if (g.NavCursorVisible)
{
g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection. Will be set again
g.NavCursorHideFrames = 2;
}
g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
}
}
@ -8832,7 +8850,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (!enabled)
EndDisabled();
const bool hovered = (g.HoveredId == id) && enabled && !g.NavDisableMouseHover;
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
if (menuset_is_open)
PopItemFlag();
@ -8867,7 +8885,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
// The 'HovereWindow == window' check creates an inconsistency (e.g. moving away from menu slowly tends to hit same window, whereas moving away fast does not)
// But we also need to not close the top-menu menu when moving over void. Perhaps we should extend the triangle check to a larger polygon.
// (Remember to test this on BeginPopup("A")->BeginMenu("B") sequence which behaves slightly differently as B isn't a Child of A and hovering isn't shared.)
if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavDisableMouseHover && g.ActiveId == 0)
if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavHighlightItemUnderNav && g.ActiveId == 0)
want_close = true;
// Open
@ -8882,7 +8900,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
{
want_open = want_open_nav_init = true;
NavMoveRequestCancel();
NavRestoreHighlightAfterMove();
SetNavCursorVisibleAfterMove();
}
}
else
@ -10013,7 +10031,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Calculate tab contents size
ImVec2 size = TabItemCalcSize(label, (p_open != NULL) || (flags & ImGuiTabItemFlags_UnsavedDocument));
tab->RequestedWidth = -1.0f;
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
size.x = tab->RequestedWidth = g.NextItemData.Width;
if (tab_is_new)
tab->Width = ImMax(1.0f, size.x);
@ -10207,7 +10225,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
float y_offset = 1.0f * g.CurrentDpiScale;
display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), style.TabBarOverlineSize);
}
RenderNavHighlight(bb, id);
RenderNavCursor(bb, id);
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);

View File

@ -38,7 +38,25 @@ You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain color
### Using OpenType SVG fonts (SVGinOT)
- *SVG in Open Type* is a standard by Adobe and Mozilla for color OpenType and Open Font Format fonts. It allows font creators to embed complete SVG files within a font enabling full color and even animations.
- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT
- Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above
1. Add `#define IMGUI_ENABLE_FREETYPE_LUNASVG` in your `imconfig.h`.
2. Get latest lunasvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install lunasvg --triplet=x64-windows`.
- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT
- Two alternatives are possible to render SVG fonts: use "lunasvg" or "plutosvg". plutosvg will support some more fonts (e.g. NotoColorEmoji-Regular) and may load them faster.
#### Using lunasvg
Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above
- Add `#define IMGUI_ENABLE_FREETYPE_LUNASVG` in your `imconfig.h`.
- Get latest lunasvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install lunasvg --triplet=x64-windows`.
#### Using plutosvg (and plutovg)
- Add `#define IMGUI_ENABLE_FREETYPE_PLUTOSVG` in your `imconfig.h`.
- Compile and link with plutosvg *and* plutovg (which is required by plutosvg)
_Compilation hints for plutovg_
- Compile all source files in `plutovg/source/*.c`
- Add include directory: `plutovg/include` + `plutovg/stb`
_Compilation hints for plutosvg_
- Compile `plutosvg/source/plutosvg.c`
- Add include directory: `plutosvg/source`
- Add define: `PLUTOSVG_HAS_FREETYPE`
- Link with: plutovg, freetype

View File

@ -6,8 +6,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2024/10/17: added plutosvg support for SVG Fonts (seems faster/better than lunasvg). Enable by using '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG'. (#7927)
// 2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
// 2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG' (#6591)
// 2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG'. (#6591)
// 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
@ -45,12 +46,21 @@
#include FT_GLYPH_H // <freetype/ftglyph.h>
#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// Handle LunaSVG and PlutoSVG
#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) && defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG)
#error "Cannot enable both IMGUI_ENABLE_FREETYPE_LUNASVG and IMGUI_ENABLE_FREETYPE_PLUTOSVG"
#endif
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
#include FT_OTSVG_H // <freetype/otsvg.h>
#include FT_BBOX_H // <freetype/ftbbox.h>
#include <lunasvg.h>
#endif
#ifdef IMGUI_ENABLE_FREETYPE_PLUTOSVG
#include <plutosvg.h>
#endif
#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) || defined (IMGUI_ENABLE_FREETYPE_PLUTOSVG)
#if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
#error IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
#error IMGUI_ENABLE_FREETYPE_PLUTOSVG or IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
#endif
#endif
@ -269,11 +279,11 @@ namespace
// Need an outline for this to work
FT_GlyphSlot slot = Face->glyph;
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) || defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG)
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG);
#else
#if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_PLUTOSVG or IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
#endif
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
@ -810,6 +820,10 @@ static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot };
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", &hooks);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
#ifdef IMGUI_ENABLE_FREETYPE_PLUTOSVG
// With plutosvg, use provided hooks
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", plutosvg_ft_svg_hooks());
#endif // IMGUI_ENABLE_FREETYPE_PLUTOSVG
bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
FT_Done_Library(ft_library);

View File

@ -5,6 +5,13 @@
#include "imgui.h" // IMGUI_API
#ifndef IMGUI_DISABLE
// Usage:
// - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to enable support for imgui_freetype in imgui.
// Optional support for OpenType SVG fonts:
// - Add '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG' to use plutosvg (not provided). See #7927.
// - Add '#define IMGUI_ENABLE_FREETYPE_LUNASVG' to use lunasvg (not provided). See #6591.
// Forward declarations
struct ImFontAtlas;
struct ImFontBuilderIO;