mirror of
https://github.com/ocornut/imgui.git
synced 2025-12-20 05:15:36 +00:00
Merge branch 'master' into docking
# Conflicts: # imgui.cpp # imgui_demo.cpp # imgui_internal.h
This commit is contained in:
311
imgui.cpp
311
imgui.cpp
@@ -132,7 +132,7 @@ CODE
|
||||
|
||||
- MOUSE CONTROLS
|
||||
- Mouse wheel: Scroll vertically.
|
||||
- SHIFT+Mouse wheel: Scroll horizontally.
|
||||
- Shift+Mouse wheel: Scroll horizontally.
|
||||
- Click [X]: Close a window, available when 'bool* p_open' is passed to ImGui::Begin().
|
||||
- Click ^, Double-Click title: Collapse window.
|
||||
- Drag on corner/border: Resize window (double-click to auto fit window to its contents).
|
||||
@@ -140,23 +140,23 @@ CODE
|
||||
- Left-click outside popup: Close popup stack (right-click over underlying popup: Partially close popup stack).
|
||||
|
||||
- TEXT EDITOR
|
||||
- Hold SHIFT or Drag Mouse: Select text.
|
||||
- CTRL+Left/Right: Word jump.
|
||||
- CTRL+Shift+Left/Right: Select words.
|
||||
- CTRL+A or Double-Click: Select All.
|
||||
- CTRL+X, CTRL+C, CTRL+V: Use OS clipboard.
|
||||
- CTRL+Z Undo.
|
||||
- CTRL+Y or CTRL+Shift+Z: Redo.
|
||||
- Hold Shift or Drag Mouse: Select text.
|
||||
- Ctrl+Left/Right: Word jump.
|
||||
- Ctrl+Shift+Left/Right: Select words.
|
||||
- Ctrl+A or Double-Click: Select All.
|
||||
- Ctrl+X, Ctrl+C, Ctrl+V: Use OS clipboard.
|
||||
- Ctrl+Z Undo.
|
||||
- Ctrl+Y or Ctrl+Shift+Z: Redo.
|
||||
- ESCAPE: Revert text to its original value.
|
||||
- On OSX, controls are automatically adjusted to match standard OSX text editing 2ts and behaviors.
|
||||
|
||||
- KEYBOARD CONTROLS
|
||||
- Basic:
|
||||
- Tab, SHIFT+Tab Cycle through text editable fields.
|
||||
- CTRL+Tab, CTRL+Shift+Tab Cycle through windows.
|
||||
- CTRL+Click Input text into a Slider or Drag widget.
|
||||
- Tab, Shift+Tab Cycle through text editable fields.
|
||||
- Ctrl+Tab, Ctrl+Shift+Tab Cycle through windows.
|
||||
- Ctrl+Click Input text into a Slider or Drag widget.
|
||||
- Extended features with `io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard`:
|
||||
- Tab, SHIFT+Tab: Cycle through every items.
|
||||
- Tab, Shift+Tab: Cycle through every items.
|
||||
- Arrow keys Move through items using directional navigation. Tweak value.
|
||||
- Arrow keys + Alt, Shift Tweak slower, tweak faster (when using arrow keys).
|
||||
- Enter Activate item (prefer text input when possible).
|
||||
@@ -165,7 +165,7 @@ CODE
|
||||
- Page Up, Page Down Previous page, next page.
|
||||
- Home, End Scroll to top, scroll to bottom.
|
||||
- Alt Toggle between scrolling layer and menu layer.
|
||||
- CTRL+Tab then Ctrl+Arrows Move window. Hold SHIFT to resize instead of moving.
|
||||
- Ctrl+Tab then Ctrl+Arrows Move window. Hold Shift to resize instead of moving.
|
||||
- Output when ImGuiConfigFlags_NavEnableKeyboard set,
|
||||
- io.WantCaptureKeyboard flag is set when keyboard is claimed.
|
||||
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
|
||||
@@ -1260,13 +1260,13 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
||||
#endif
|
||||
|
||||
// Debug options
|
||||
#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Hold CTRL to display for all candidates. CTRL+Arrow to change last direction.
|
||||
#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Hold Ctrl to display for all candidates. Ctrl+Arrow to change last direction.
|
||||
#define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window
|
||||
|
||||
// Default font size if unspecified in both style.FontSizeBase and AddFontXXX() calls.
|
||||
static const float FONT_DEFAULT_SIZE = 20.0f;
|
||||
|
||||
// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
|
||||
// When using Ctrl+Tab (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
|
||||
static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
|
||||
static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
|
||||
static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut.
|
||||
@@ -1340,7 +1340,7 @@ static void ErrorCheckNewFrameSanityChecks();
|
||||
static void ErrorCheckEndFrameSanityChecks();
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
static void UpdateDebugToolItemPicker();
|
||||
static void UpdateDebugToolStackQueries();
|
||||
static void UpdateDebugToolItemPathQuery();
|
||||
static void UpdateDebugToolFlashStyleColor();
|
||||
#endif
|
||||
|
||||
@@ -5329,7 +5329,7 @@ void ImGui::StopMouseMovingWindow()
|
||||
}
|
||||
|
||||
// Handle mouse moving window
|
||||
// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
|
||||
// Note: moving window with the navigation keys (Square + d-pad / Ctrl+Tab + Arrows) are processed in NavUpdateWindowing()
|
||||
// FIXME: We don't have strong guarantee that g.MovingWindow stay synced with g.ActiveId == g.MovingWindow->MoveId.
|
||||
// This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs,
|
||||
// but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other.
|
||||
@@ -5642,7 +5642,7 @@ void ImGui::NewFrame()
|
||||
KeepAliveID(g.DragDropPayload.SourceId);
|
||||
|
||||
// [DEBUG]
|
||||
if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl) // Count is locked while holding CTRL
|
||||
if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl) // Count is locked while holding Ctrl
|
||||
g.DebugDrawIdConflictsId = 0;
|
||||
if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
|
||||
g.DebugDrawIdConflictsId = g.HoveredIdPreviousFrame;
|
||||
@@ -5822,7 +5822,7 @@ void ImGui::NewFrame()
|
||||
// [DEBUG] Update debug features
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
UpdateDebugToolItemPicker();
|
||||
UpdateDebugToolStackQueries();
|
||||
UpdateDebugToolItemPathQuery();
|
||||
UpdateDebugToolFlashStyleColor();
|
||||
if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0)
|
||||
{
|
||||
@@ -6069,14 +6069,14 @@ static void ImGui::RenderDimmedBackgrounds()
|
||||
}
|
||||
else if (dim_bg_for_window_list)
|
||||
{
|
||||
// Draw dimming behind CTRL+Tab target window and behind CTRL+Tab UI window
|
||||
// Draw dimming behind Ctrl+Tab target window and behind Ctrl+Tab UI window
|
||||
RenderDimmedBackgroundBehindWindow(g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio));
|
||||
if (g.NavWindowingListWindow != NULL && g.NavWindowingListWindow->Viewport && g.NavWindowingListWindow->Viewport != g.NavWindowingTargetAnim->Viewport)
|
||||
RenderDimmedBackgroundBehindWindow(g.NavWindowingListWindow, GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio));
|
||||
viewports_already_dimmed[0] = g.NavWindowingTargetAnim->Viewport;
|
||||
viewports_already_dimmed[1] = g.NavWindowingListWindow ? g.NavWindowingListWindow->Viewport : NULL;
|
||||
|
||||
// Draw border around CTRL+Tab target window
|
||||
// Draw border around Ctrl+Tab target window
|
||||
ImGuiWindow* window = g.NavWindowingTargetAnim;
|
||||
ImGuiViewport* viewport = window->Viewport;
|
||||
float distance = g.FontSize;
|
||||
@@ -6146,7 +6146,7 @@ void ImGui::EndFrame()
|
||||
g.CurrentWindow->Active = false;
|
||||
End();
|
||||
|
||||
// Update navigation: CTRL+Tab, wrap-around requests
|
||||
// Update navigation: Ctrl+Tab, wrap-around requests
|
||||
NavEndFrame();
|
||||
|
||||
// Update docking
|
||||
@@ -7902,7 +7902,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
bool window_title_visible_elsewhere = false;
|
||||
if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive))
|
||||
window_title_visible_elsewhere = true;
|
||||
else if (g.NavWindowingListWindow != NULL && (flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB
|
||||
else if (g.NavWindowingListWindow != NULL && (flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using Ctrl+Tab
|
||||
window_title_visible_elsewhere = true;
|
||||
else if (flags & ImGuiWindowFlags_ChildMenu)
|
||||
window_title_visible_elsewhere = true;
|
||||
@@ -8456,10 +8456,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
{
|
||||
IMGUI_DEBUG_LOG_VIEWPORT("[viewport] Window '%s' closed by PlatformRequestClose\n", window->Name);
|
||||
*p_open = false;
|
||||
g.NavWindowingToggleLayer = false; // Assume user mapped PlatformRequestClose on ALT-F4 so we disable ALT for menu toggle. False positive not an issue. // FIXME-NAV: Try removing.
|
||||
g.NavWindowingToggleLayer = false; // Assume user mapped PlatformRequestClose on Alt-F4 so we disable Alt for menu toggle. False positive not an issue. // FIXME-NAV: Try removing.
|
||||
}
|
||||
|
||||
// Pressing CTRL+C copy window content into the clipboard
|
||||
// Pressing Ctrl+C copy window content into the clipboard
|
||||
// [EXPERIMENTAL] Breaks on nested Begin/End pairs. We need to work that out and add better logging scope.
|
||||
// [EXPERIMENTAL] Text outputs has many issues.
|
||||
if (g.IO.ConfigWindowsCopyContentsWithCtrlC)
|
||||
@@ -8830,6 +8830,15 @@ bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowInBeginStack(ImGuiWindow* window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
for (int n = g.CurrentWindowStack.Size - 1; n >= 0; n--)
|
||||
if (g.CurrentWindowStack[n].Window == window)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
|
||||
{
|
||||
if (window->RootWindow == potential_parent)
|
||||
@@ -10672,7 +10681,7 @@ static void ImGui::UpdateMouseInputs()
|
||||
ImGuiIO& io = g.IO;
|
||||
|
||||
// Mouse Wheel swapping flag
|
||||
// As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead
|
||||
// As a standard behavior holding Shift while using Vertical Mouse Wheel triggers Horizontal scroll instead
|
||||
// - We avoid doing it on OSX as it the OS input layer handles this already.
|
||||
// - FIXME: However this means when running on OSX over Emscripten, Shift+WheelY will incur two swapping (1 in OS, 1 here), canceling the feature.
|
||||
// - FIXME: When we can distinguish e.g. touchpad scroll events from mouse ones, we'll set this accordingly based on input source.
|
||||
@@ -11691,7 +11700,7 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
||||
Separator();
|
||||
if (g.IO.ConfigDebugHighlightIdConflictsShowItemPicker)
|
||||
{
|
||||
Text("(Hold CTRL to: use ");
|
||||
Text("(Hold Ctrl to: use ");
|
||||
SameLine(0.0f, 0.0f);
|
||||
if (SmallButton("Item Picker"))
|
||||
DebugStartItemPicker();
|
||||
@@ -11700,11 +11709,10 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
||||
}
|
||||
else
|
||||
{
|
||||
Text("(Hold CTRL to ");
|
||||
Text("(Hold Ctrl to: ");
|
||||
}
|
||||
SameLine(0.0f, 0.0f);
|
||||
if (SmallButton("Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||
g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
|
||||
TextLinkOpenURL("read FAQ \"About ID Stack System\"", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
|
||||
SameLine(0.0f, 0.0f);
|
||||
Text(")");
|
||||
EndErrorTooltip();
|
||||
@@ -11713,8 +11721,8 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
||||
if (g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip()) // Amend at end of frame
|
||||
{
|
||||
Separator();
|
||||
Text("(Hold CTRL to:");
|
||||
SameLine();
|
||||
Text("(Hold Ctrl to: ");
|
||||
SameLine(0.0f, 0.0f);
|
||||
if (SmallButton("Enable Asserts"))
|
||||
g.IO.ConfigErrorRecoveryEnableAssert = true;
|
||||
//SameLine();
|
||||
@@ -11727,7 +11735,7 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Pseudo-tooltip. Follow mouse until CTRL is held. When CTRL is held we lock position, allowing to click it.
|
||||
// Pseudo-tooltip. Follow mouse until Ctrl is held. When Ctrl is held we lock position, allowing to click it.
|
||||
bool ImGui::BeginErrorTooltip()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -12595,17 +12603,17 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext
|
||||
tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
|
||||
}
|
||||
|
||||
// Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
|
||||
if ((tooltip_flags & ImGuiTooltipFlags_OverridePrevious) && g.TooltipPreviousWindow != NULL && g.TooltipPreviousWindow->Active && !IsWindowInBeginStack(g.TooltipPreviousWindow))
|
||||
{
|
||||
//IMGUI_DEBUG_LOG("[tooltip] '%s' already active, using +1 for this frame\n", window_name);
|
||||
SetWindowHiddenAndSkipItemsForCurrentFrame(g.TooltipPreviousWindow);
|
||||
g.TooltipOverrideCount++;
|
||||
}
|
||||
|
||||
const char* window_name_template = is_dragdrop_tooltip ? "##Tooltip_DragDrop_%02d" : "##Tooltip_%02d";
|
||||
char window_name[32];
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, g.TooltipOverrideCount);
|
||||
if ((tooltip_flags & ImGuiTooltipFlags_OverridePrevious) && g.TooltipPreviousWindow != NULL && g.TooltipPreviousWindow->Active)
|
||||
{
|
||||
// Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
|
||||
//IMGUI_DEBUG_LOG("[tooltip] '%s' already active, using +1 for this frame\n", window_name);
|
||||
SetWindowHiddenAndSkipItemsForCurrentFrame(g.TooltipPreviousWindow);
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, ++g.TooltipOverrideCount);
|
||||
}
|
||||
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
|
||||
Begin(window_name, NULL, flags | extra_window_flags);
|
||||
// 2023-03-09: Added bool return value to the API, but currently always returning true.
|
||||
@@ -13752,7 +13760,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result, const ImRect& nav_bb)
|
||||
const ImGuiDir move_dir = g.NavMoveDir;
|
||||
#if IMGUI_DEBUG_NAV_SCORING
|
||||
char buf[200];
|
||||
if (g.IO.KeyCtrl) // Hold CTRL to preview score in matching quadrant. CTRL+Arrow to rotate.
|
||||
if (g.IO.KeyCtrl) // Hold Ctrl to preview score in matching quadrant. Ctrl+Arrow to rotate.
|
||||
{
|
||||
if (quadrant == move_dir)
|
||||
{
|
||||
@@ -14304,7 +14312,7 @@ static void ImGui::NavUpdate()
|
||||
if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == ImGuiNavLayer_Main)
|
||||
g.NavWindow->NavLastChildNavWindow = NULL;
|
||||
|
||||
// Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.)
|
||||
// Update Ctrl+Tab and Windowing features (hold Square to move/resize/etc.)
|
||||
NavUpdateWindowing();
|
||||
|
||||
// Set output flags for user application
|
||||
@@ -14521,7 +14529,7 @@ void ImGui::NavUpdateCreateMoveRequest()
|
||||
g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y);
|
||||
}
|
||||
|
||||
// [DEBUG] Always send a request when holding CTRL. Hold CTRL + Arrow change the direction.
|
||||
// [DEBUG] Always send a request when holding Ctrl. Hold Ctrl + Arrow change the direction.
|
||||
#if IMGUI_DEBUG_NAV_SCORING
|
||||
//if (io.KeyCtrl && IsKeyPressed(ImGuiKey_C))
|
||||
// g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3);
|
||||
@@ -14873,7 +14881,7 @@ static void ImGui::NavEndFrame()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// Show CTRL+TAB list window
|
||||
// Show Ctrl+Tab list window
|
||||
if (g.NavWindowingTarget != NULL)
|
||||
NavUpdateWindowingOverlay();
|
||||
|
||||
@@ -14943,8 +14951,8 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
|
||||
}
|
||||
|
||||
// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
|
||||
// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically.
|
||||
// Can we focus this window with Ctrl+Tab (or PadMenu + PadFocusPrev/PadFocusNext)
|
||||
// Note that NoNavFocus makes the window not reachable with Ctrl+Tab but it can still be focused with mouse or programmatically.
|
||||
// If you want a window to never be focused, you may use the e.g. NoInputs flag.
|
||||
bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
|
||||
{
|
||||
@@ -14999,7 +15007,7 @@ static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window)
|
||||
|
||||
// If the window has ONLY a menu layer (no main layer), select it directly
|
||||
// Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame,
|
||||
// so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since
|
||||
// so Ctrl+Tab where the keys are only held for 1 frame will be able to use correct layers mask since
|
||||
// the target window as already been previewed once.
|
||||
// FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases,
|
||||
// we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask*
|
||||
@@ -15015,7 +15023,7 @@ static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window)
|
||||
}
|
||||
|
||||
// Windowing management mode
|
||||
// Keyboard: CTRL+Tab (change focus/move/resize), Alt (toggle menu layer)
|
||||
// Keyboard: Ctrl+Tab (change focus/move/resize), Alt (toggle menu layer)
|
||||
// Gamepad: Hold Menu/Square (change focus/move/resize), Tap Menu/Square (toggle menu layer)
|
||||
static void ImGui::NavUpdateWindowing()
|
||||
{
|
||||
@@ -15026,7 +15034,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
bool apply_toggle_layer = false;
|
||||
|
||||
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
||||
bool allow_windowing = (modal_window == NULL); // FIXME: This prevent CTRL+TAB from being usable with windows that are inside the Begin-stack of that modal.
|
||||
bool allow_windowing = (modal_window == NULL); // FIXME: This prevent Ctrl+Tab from being usable with windows that are inside the Begin-stack of that modal.
|
||||
if (!allow_windowing)
|
||||
g.NavWindowingTarget = NULL;
|
||||
|
||||
@@ -15038,7 +15046,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
g.NavWindowingTargetAnim = NULL;
|
||||
}
|
||||
|
||||
// Start CTRL+Tab or Square+L/R window selection
|
||||
// Start Ctrl+Tab or Square+L/R window selection
|
||||
// (g.ConfigNavWindowingKeyNext/g.ConfigNavWindowingKeyPrev defaults are ImGuiMod_Ctrl|ImGuiKey_Tab and ImGuiMod_Ctrl|ImGuiMod_Shift|ImGuiKey_Tab)
|
||||
const ImGuiID owner_id = ImHashStr("##NavUpdateWindowing");
|
||||
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
||||
@@ -15106,7 +15114,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
// Keyboard: Focus
|
||||
if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_Keyboard)
|
||||
{
|
||||
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
|
||||
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast Ctrl+Tab doesn't add visual noise
|
||||
ImGuiKeyChord shared_mods = ((g.ConfigNavWindowingKeyNext ? g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (g.ConfigNavWindowingKeyPrev ? g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_;
|
||||
IM_ASSERT(shared_mods != 0); // Next/Prev shortcut currently needs a shared modifier to "hold", otherwise Prev actions would keep cycling between two windows.
|
||||
g.NavWindowingTimer += io.DeltaTime;
|
||||
@@ -15117,7 +15125,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
apply_focus_window = g.NavWindowingTarget;
|
||||
}
|
||||
|
||||
// Keyboard: Press and Release ALT to toggle menu layer
|
||||
// Keyboard: Press and Release Alt to toggle menu layer
|
||||
const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt };
|
||||
bool windowing_toggle_layer_start = false;
|
||||
if (g.NavWindow != NULL && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
|
||||
@@ -15226,7 +15234,7 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
|
||||
return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingUntitled);
|
||||
}
|
||||
|
||||
// Overlay displayed when using CTRL+TAB. Called by EndFrame().
|
||||
// Overlay displayed when using Ctrl+Tab. Called by EndFrame().
|
||||
void ImGui::NavUpdateWindowingOverlay()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -22518,7 +22526,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
Text("Keys down:"); for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (!IsKeyDown(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); }
|
||||
Text("Keys pressed:"); for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (!IsKeyPressed(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
|
||||
Text("Keys released:"); for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (!IsKeyReleased(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
|
||||
Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
|
||||
Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "Ctrl " : "", io.KeyShift ? "Shift " : "", io.KeyAlt ? "Alt " : "", io.KeySuper ? "Super " : "");
|
||||
Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; SameLine(); Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
|
||||
DebugRenderKeyboardPreview(GetWindowDrawList());
|
||||
Unindent();
|
||||
@@ -23518,7 +23526,7 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags)
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
|
||||
ImGui::SetItemTooltip("Hold Shift when clicking to enable for 2 frames only (useful for spammy log entries)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23738,81 +23746,83 @@ void ImGui::UpdateDebugToolItemPicker()
|
||||
EndTooltip();
|
||||
}
|
||||
|
||||
// [DEBUG] ID Stack Tool: update queries. Called by NewFrame()
|
||||
void ImGui::UpdateDebugToolStackQueries()
|
||||
// Update queries. The steps are: -1: query Stack, >= 0: query each stack item
|
||||
// We can only perform 1 ID Info query every frame. This is designed so the GetID() tests are cheap and constant-time
|
||||
static ImGuiID DebugItemPathQuery_UpdateAndGetHookId(ImGuiDebugItemPathQuery* query, ImGuiID id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiIDStackTool* tool = &g.DebugIDStackTool;
|
||||
|
||||
// Clear hook when id stack tool is not visible
|
||||
g.DebugHookIdInfoId = 0;
|
||||
tool->QueryHookActive = false;
|
||||
if (g.FrameCount != tool->LastActiveFrame + 1)
|
||||
return;
|
||||
|
||||
// Update queries. The steps are: -1: query Stack, >= 0: query each stack item
|
||||
// We can only perform 1 ID Info query every frame. This is designed so the GetID() tests are cheap and constant-time
|
||||
const ImGuiID query_main_id = g.HoveredIdPreviousFrame ? g.HoveredIdPreviousFrame : g.ActiveId;
|
||||
if (tool->QueryMainId != query_main_id)
|
||||
// Update query. Clear hook when no active query
|
||||
if (query->MainID != id)
|
||||
{
|
||||
tool->QueryMainId = query_main_id;
|
||||
tool->StackLevel = -1;
|
||||
tool->Results.resize(0);
|
||||
tool->ResultPathsBuf.resize(0);
|
||||
query->MainID = id;
|
||||
query->Step = -1;
|
||||
query->Complete = false;
|
||||
query->Results.resize(0);
|
||||
query->ResultsDescBuf.resize(0);
|
||||
}
|
||||
if (query_main_id == 0)
|
||||
return;
|
||||
query->Active = false;
|
||||
if (id == 0)
|
||||
return 0;
|
||||
|
||||
// Advance to next stack level when we got our result, or after 2 frames (in case we never get a result)
|
||||
int stack_level = tool->StackLevel;
|
||||
if (stack_level >= 0 && stack_level < tool->Results.Size)
|
||||
if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
|
||||
tool->StackLevel++;
|
||||
if (query->Step >= 0 && query->Step < query->Results.Size)
|
||||
if (query->Results[query->Step].QuerySuccess || query->Results[query->Step].QueryFrameCount > 2)
|
||||
query->Step++;
|
||||
|
||||
// Update hook
|
||||
stack_level = tool->StackLevel;
|
||||
if (stack_level == -1)
|
||||
// Update status and hook
|
||||
query->Complete = (query->Step == query->Results.Size);
|
||||
if (query->Step == -1)
|
||||
{
|
||||
g.DebugHookIdInfoId = query_main_id;
|
||||
tool->QueryHookActive = true;
|
||||
query->Active = true;
|
||||
return id;
|
||||
}
|
||||
else if (stack_level >= 0 && stack_level < tool->Results.Size)
|
||||
else if (query->Step >= 0 && query->Step < query->Results.Size)
|
||||
{
|
||||
g.DebugHookIdInfoId = tool->Results[stack_level].ID;
|
||||
tool->Results[stack_level].QueryFrameCount++;
|
||||
tool->QueryHookActive = true;
|
||||
query->Results[query->Step].QueryFrameCount++;
|
||||
query->Active = true;
|
||||
return query->Results[query->Step].ID;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// [DEBUG] ID Stack Tool: update query. Called by NewFrame()
|
||||
void ImGui::UpdateDebugToolItemPathQuery()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiID id = 0;
|
||||
if (g.DebugIDStackTool.LastActiveFrame + 1 == g.FrameCount)
|
||||
id = g.HoveredIdPreviousFrame ? g.HoveredIdPreviousFrame : g.ActiveId;
|
||||
g.DebugHookIdInfoId = DebugItemPathQuery_UpdateAndGetHookId(&g.DebugItemPathQuery, id);
|
||||
}
|
||||
|
||||
// [DEBUG] ID Stack tool: hooks called by GetID() family functions
|
||||
void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiIDStackTool* tool = &g.DebugIDStackTool;
|
||||
if (tool->QueryHookActive == false)
|
||||
ImGuiDebugItemPathQuery* query = &g.DebugItemPathQuery;
|
||||
if (query->Active == false)
|
||||
{
|
||||
IM_ASSERT(id == 0);
|
||||
return;
|
||||
}
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
// Step 0: stack query
|
||||
// Step -1: stack query
|
||||
// This assumes that the ID was computed with the current ID stack, which tends to be the case for our widget.
|
||||
if (tool->StackLevel == -1)
|
||||
if (query->Step == -1)
|
||||
{
|
||||
IM_ASSERT(tool->Results.Size == 0);
|
||||
tool->StackLevel++;
|
||||
tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
|
||||
IM_ASSERT(query->Results.Size == 0);
|
||||
query->Step++;
|
||||
query->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
|
||||
for (int n = 0; n < window->IDStack.Size + 1; n++)
|
||||
tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] : id;
|
||||
query->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] : id;
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1+: query for individual level
|
||||
IM_ASSERT(tool->StackLevel >= 0);
|
||||
if (tool->StackLevel != window->IDStack.Size)
|
||||
// Step 0+: query for individual level
|
||||
IM_ASSERT(query->Step >= 0);
|
||||
if (query->Step != window->IDStack.Size)
|
||||
return;
|
||||
ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel];
|
||||
ImGuiStackLevelInfo* info = &query->Results[query->Step];
|
||||
IM_ASSERT(info->ID == id && info->QueryFrameCount > 0);
|
||||
|
||||
if (info->DescOffset == -1)
|
||||
@@ -23837,30 +23847,56 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat
|
||||
default:
|
||||
IM_ASSERT(0);
|
||||
}
|
||||
info->DescOffset = tool->ResultPathsBuf.size();
|
||||
tool->ResultPathsBuf.append(result, result_end + 1); // Include zero terminator
|
||||
info->DescOffset = query->ResultsDescBuf.size();
|
||||
query->ResultsDescBuf.append(result, result_end + 1); // Include zero terminator
|
||||
}
|
||||
info->QuerySuccess = true;
|
||||
info->DataType = (ImS8)data_type;
|
||||
if (info->DataType == -1)
|
||||
info->DataType = (ImS8)data_type;
|
||||
}
|
||||
|
||||
static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool, int n, bool format_for_ui, char* buf, size_t buf_size)
|
||||
static int DebugItemPathQuery_FormatLevelInfo(ImGuiDebugItemPathQuery* query, int n, bool format_for_ui, char* buf, size_t buf_size)
|
||||
{
|
||||
ImGuiStackLevelInfo* info = &tool->Results[n];
|
||||
ImGuiStackLevelInfo* info = &query->Results[n];
|
||||
ImGuiWindow* window = (info->DescOffset == -1 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
|
||||
if (window) // Source: window name (because the root ID don't call GetID() and so doesn't get hooked)
|
||||
if (window) // Source: window name (because the root ID don't call GetID() and so doesn't get hooked)
|
||||
return ImFormatString(buf, buf_size, format_for_ui ? "\"%s\" [window]" : "%s", ImHashSkipUncontributingPrefix(window->Name));
|
||||
if (info->QuerySuccess) // Source: GetID() hooks (prioritize over ItemInfo() because we frequently use patterns like: PushID(str), Button("") where they both have same id)
|
||||
return ImFormatString(buf, buf_size, (format_for_ui && info->DataType == ImGuiDataType_String) ? "\"%s\"" : "%s", ImHashSkipUncontributingPrefix(&tool->ResultPathsBuf.Buf[info->DescOffset]));
|
||||
if (tool->StackLevel < tool->Results.Size) // Only start using fallback below when all queries are done, so during queries we don't flickering ??? markers.
|
||||
if (info->QuerySuccess) // Source: GetID() hooks (prioritize over ItemInfo() because we frequently use patterns like: PushID(str), Button("") where they both have same id)
|
||||
return ImFormatString(buf, buf_size, (format_for_ui && info->DataType == ImGuiDataType_String) ? "\"%s\"" : "%s", ImHashSkipUncontributingPrefix(&query->ResultsDescBuf.Buf[info->DescOffset]));
|
||||
if (query->Step < query->Results.Size) // Only start using fallback below when all queries are done, so during queries we don't flickering ??? markers.
|
||||
return (*buf = 0);
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
if (const char* label = ImGuiTestEngine_FindItemDebugLabel(GImGui, info->ID)) // Source: ImGuiTestEngine's ItemInfo()
|
||||
if (const char* label = ImGuiTestEngine_FindItemDebugLabel(GImGui, info->ID)) // Source: ImGuiTestEngine's ItemInfo()
|
||||
return ImFormatString(buf, buf_size, format_for_ui ? "??? \"%s\"" : "%s", ImHashSkipUncontributingPrefix(label));
|
||||
#endif
|
||||
return ImFormatString(buf, buf_size, "???");
|
||||
}
|
||||
|
||||
static const char* DebugItemPathQuery_GetResultAsPath(ImGuiDebugItemPathQuery* query, bool hex_encode_non_ascii_chars)
|
||||
{
|
||||
ImGuiTextBuffer* buf = &query->ResultPathBuf;
|
||||
buf->resize(0);
|
||||
for (int stack_n = 0; stack_n < query->Results.Size; stack_n++)
|
||||
{
|
||||
char level_desc[256];
|
||||
DebugItemPathQuery_FormatLevelInfo(query, stack_n, false, level_desc, IM_ARRAYSIZE(level_desc));
|
||||
buf->append(stack_n == 0 ? "//" : "/");
|
||||
for (const char* p = level_desc; *p != 0; )
|
||||
{
|
||||
unsigned int c;
|
||||
const char* p_next = p + ImTextCharFromUtf8(&c, p, NULL);
|
||||
if (c == '/')
|
||||
buf->append("\\");
|
||||
if (c < 256 || !hex_encode_non_ascii_chars)
|
||||
buf->append(p, p_next);
|
||||
else for (; p < p_next; p++)
|
||||
buf->appendf("\\x%02x", (unsigned char)*p);
|
||||
p = p_next;
|
||||
}
|
||||
}
|
||||
return buf->c_str();
|
||||
}
|
||||
|
||||
// ID Stack Tool: Display UI
|
||||
void ImGui::ShowIDStackToolWindow(bool* p_open)
|
||||
{
|
||||
@@ -23873,34 +23909,15 @@ void ImGui::ShowIDStackToolWindow(bool* p_open)
|
||||
return;
|
||||
}
|
||||
|
||||
// Display hovered/active status
|
||||
ImGuiDebugItemPathQuery* query = &g.DebugItemPathQuery;
|
||||
ImGuiIDStackTool* tool = &g.DebugIDStackTool;
|
||||
|
||||
// Build and display path
|
||||
tool->ResultTempBuf.resize(0);
|
||||
for (int stack_n = 0; stack_n < tool->Results.Size; stack_n++)
|
||||
{
|
||||
char level_desc[256];
|
||||
StackToolFormatLevelInfo(tool, stack_n, false, level_desc, IM_ARRAYSIZE(level_desc));
|
||||
tool->ResultTempBuf.append(stack_n == 0 ? "//" : "/");
|
||||
for (const char* p = level_desc; *p != 0; )
|
||||
{
|
||||
unsigned int c;
|
||||
const char* p_next = p + ImTextCharFromUtf8(&c, p, NULL);
|
||||
if (c == '/')
|
||||
tool->ResultTempBuf.append("\\");
|
||||
if (c < 256 || !tool->OptHexEncodeNonAsciiChars)
|
||||
tool->ResultTempBuf.append(p, p_next);
|
||||
else for (; p < p_next; p++)
|
||||
tool->ResultTempBuf.appendf("\\x%02x", (unsigned char)*p);
|
||||
p = p_next;
|
||||
}
|
||||
}
|
||||
Text("0x%08X", tool->QueryMainId);
|
||||
tool->LastActiveFrame = g.FrameCount;
|
||||
const char* result_path = DebugItemPathQuery_GetResultAsPath(query, tool->OptHexEncodeNonAsciiChars);
|
||||
Text("0x%08X", query->MainID);
|
||||
SameLine();
|
||||
MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.");
|
||||
|
||||
// CTRL+C to copy path
|
||||
// Ctrl+C to copy path
|
||||
const float time_since_copy = (float)g.Time - tool->CopyToClipboardLastTime;
|
||||
PushStyleVarY(ImGuiStyleVar_FramePadding, 0.0f);
|
||||
Checkbox("Hex-encode non-ASCII", &tool->OptHexEncodeNonAsciiChars);
|
||||
@@ -23912,36 +23929,34 @@ void ImGui::ShowIDStackToolWindow(bool* p_open)
|
||||
if (tool->OptCopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
|
||||
{
|
||||
tool->CopyToClipboardLastTime = (float)g.Time;
|
||||
SetClipboardText(tool->ResultTempBuf.c_str());
|
||||
SetClipboardText(result_path);
|
||||
}
|
||||
|
||||
Text("- Path \"%s\"", tool->ResultTempBuf.c_str());
|
||||
Text("- Path \"%s\"", query->Complete ? result_path : "");
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
Text("- Label \"%s\"", tool->QueryMainId ? ImGuiTestEngine_FindItemDebugLabel(&g, tool->QueryMainId) : "");
|
||||
Text("- Label \"%s\"", query->MainID ? ImGuiTestEngine_FindItemDebugLabel(&g, query->MainID) : "");
|
||||
#endif
|
||||
|
||||
Separator();
|
||||
|
||||
// Display decorated stack
|
||||
tool->LastActiveFrame = g.FrameCount;
|
||||
if (tool->Results.Size > 0 && BeginTable("##table", 3, ImGuiTableFlags_Borders))
|
||||
if (query->Results.Size > 0 && BeginTable("##table", 3, ImGuiTableFlags_Borders))
|
||||
{
|
||||
const float id_width = CalcTextSize("0xDDDDDDDD").x;
|
||||
TableSetupColumn("Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
|
||||
TableSetupColumn("PushID", ImGuiTableColumnFlags_WidthStretch);
|
||||
TableSetupColumn("Result", ImGuiTableColumnFlags_WidthFixed, id_width);
|
||||
TableHeadersRow();
|
||||
for (int n = 0; n < tool->Results.Size; n++)
|
||||
for (int n = 0; n < query->Results.Size; n++)
|
||||
{
|
||||
ImGuiStackLevelInfo* info = &tool->Results[n];
|
||||
ImGuiStackLevelInfo* info = &query->Results[n];
|
||||
TableNextColumn();
|
||||
Text("0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
|
||||
Text("0x%08X", (n > 0) ? query->Results[n - 1].ID : 0);
|
||||
TableNextColumn();
|
||||
StackToolFormatLevelInfo(tool, n, true, g.TempBuffer.Data, g.TempBuffer.Size);
|
||||
DebugItemPathQuery_FormatLevelInfo(query, n, true, g.TempBuffer.Data, g.TempBuffer.Size);
|
||||
TextUnformatted(g.TempBuffer.Data);
|
||||
TableNextColumn();
|
||||
Text("0x%08X", info->ID);
|
||||
if (n == tool->Results.Size - 1)
|
||||
if (n == query->Results.Size - 1)
|
||||
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
|
||||
}
|
||||
EndTable();
|
||||
|
||||
Reference in New Issue
Block a user