|
@@ -75,6 +75,7 @@ CODE
|
|
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
|
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
|
// [SECTION] INPUTS
|
|
// [SECTION] INPUTS
|
|
// [SECTION] ERROR CHECKING
|
|
// [SECTION] ERROR CHECKING
|
|
|
|
+// [SECTION] ITEM SUBMISSION
|
|
// [SECTION] LAYOUT
|
|
// [SECTION] LAYOUT
|
|
// [SECTION] SCROLLING
|
|
// [SECTION] SCROLLING
|
|
// [SECTION] TOOLTIPS
|
|
// [SECTION] TOOLTIPS
|
|
@@ -3672,6 +3673,14 @@ void ImGui::Initialize()
|
|
g.ViewportCreatedCount++;
|
|
g.ViewportCreatedCount++;
|
|
g.PlatformIO.Viewports.push_back(g.Viewports[0]);
|
|
g.PlatformIO.Viewports.push_back(g.Viewports[0]);
|
|
|
|
|
|
|
|
+ // Build KeysMayBeCharInput[] lookup table (1 bool per named key)
|
|
|
|
+ for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
|
|
|
|
+ if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) || (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9)
|
|
|
|
+ || key == ImGuiKey_Tab || key == ImGuiKey_Space || key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period
|
|
|
|
+ || key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal || key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent
|
|
|
|
+ || key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply || key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual)
|
|
|
|
+ g.KeysMayBeCharInput.SetBit(key);
|
|
|
|
+
|
|
#ifdef IMGUI_HAS_DOCK
|
|
#ifdef IMGUI_HAS_DOCK
|
|
// Initialize Docking
|
|
// Initialize Docking
|
|
DockContextInitialize(&g);
|
|
DockContextInitialize(&g);
|
|
@@ -4007,17 +4016,6 @@ ImGuiID ImGui::GetHoveredID()
|
|
return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
|
|
return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
|
|
}
|
|
}
|
|
|
|
|
|
-// This is called by ItemAdd().
|
|
|
|
-// Code not using ItemAdd() may need to call this manually otherwise ActiveId will be cleared. In IMGUI_VERSION_NUM < 18717 this was called by GetID().
|
|
|
|
-void ImGui::KeepAliveID(ImGuiID id)
|
|
|
|
-{
|
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
|
- if (g.ActiveId == id)
|
|
|
|
- g.ActiveIdIsAlive = id;
|
|
|
|
- if (g.ActiveIdPreviousFrame == id)
|
|
|
|
- g.ActiveIdPreviousFrameIsAlive = true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void ImGui::MarkItemEdited(ImGuiID id)
|
|
void ImGui::MarkItemEdited(ImGuiID id)
|
|
{
|
|
{
|
|
// This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
|
|
// This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
|
|
@@ -4238,17 +4236,19 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
if (id != 0)
|
|
if (id != 0)
|
|
{
|
|
{
|
|
// [DEBUG] Item Picker tool!
|
|
// [DEBUG] Item Picker tool!
|
|
- // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
|
|
|
|
- // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
|
|
|
|
- // items if we performed the test in ItemAdd(), but that would incur a small runtime cost.
|
|
|
|
|
|
+ // We perform the check here because reaching is path is rare (1~ time a frame),
|
|
|
|
+ // making the cost of this tool near-zero! We could get better call-stack and support picking non-hovered
|
|
|
|
+ // items if we performed the test in ItemAdd(), but that would incur a bigger runtime cost.
|
|
if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
|
|
if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
|
|
GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
|
|
GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
|
|
if (g.DebugItemPickerBreakId == id)
|
|
if (g.DebugItemPickerBreakId == id)
|
|
IM_DEBUG_BREAK();
|
|
IM_DEBUG_BREAK();
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
if (g.NavDisableMouseHover)
|
|
if (g.NavDisableMouseHover)
|
|
return false;
|
|
return false;
|
|
@@ -4980,6 +4980,7 @@ void ImGui::NewFrame()
|
|
DockContextNewFrameUpdateDocking(&g);
|
|
DockContextNewFrameUpdateDocking(&g);
|
|
|
|
|
|
// [DEBUG] Update debug features
|
|
// [DEBUG] Update debug features
|
|
|
|
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
UpdateDebugToolItemPicker();
|
|
UpdateDebugToolItemPicker();
|
|
UpdateDebugToolStackQueries();
|
|
UpdateDebugToolStackQueries();
|
|
UpdateDebugToolFlashStyleColor();
|
|
UpdateDebugToolFlashStyleColor();
|
|
@@ -4994,6 +4995,7 @@ void ImGui::NewFrame()
|
|
g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags;
|
|
g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags;
|
|
g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
|
|
g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
// Create implicit/fallback window - which we will only render it if the user has added something to it.
|
|
// Create implicit/fallback window - which we will only render it if the user has added something to it.
|
|
// We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
|
|
// We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
|
|
@@ -5005,10 +5007,12 @@ void ImGui::NewFrame()
|
|
|
|
|
|
// [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack,
|
|
// [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack,
|
|
// allowing to validate correct Begin/End behavior in user code.
|
|
// allowing to validate correct Begin/End behavior in user code.
|
|
|
|
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
if (g.IO.ConfigDebugBeginReturnValueLoop)
|
|
if (g.IO.ConfigDebugBeginReturnValueLoop)
|
|
g.DebugBeginReturnValueCullDepth = (g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((g.DebugBeginReturnValueCullDepth + ((g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
|
|
g.DebugBeginReturnValueCullDepth = (g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((g.DebugBeginReturnValueCullDepth + ((g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
|
|
else
|
|
else
|
|
g.DebugBeginReturnValueCullDepth = -1;
|
|
g.DebugBeginReturnValueCullDepth = -1;
|
|
|
|
+#endif
|
|
|
|
|
|
CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
|
|
CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
|
|
}
|
|
}
|
|
@@ -7588,12 +7592,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
// [DEBUG] io.ConfigDebugBeginReturnValue override return value to test Begin/End and BeginChild/EndChild behaviors.
|
|
// [DEBUG] io.ConfigDebugBeginReturnValue override return value to test Begin/End and BeginChild/EndChild behaviors.
|
|
// (The implicit fallback window is NOT automatically ended allowing it to always be able to receive commands without crashing)
|
|
// (The implicit fallback window is NOT automatically ended allowing it to always be able to receive commands without crashing)
|
|
- if (!window->IsFallbackWindow && ((g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (g.IO.ConfigDebugBeginReturnValueLoop && g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size)))
|
|
|
|
- {
|
|
|
|
- if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; }
|
|
|
|
- if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; }
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
|
|
+ if (!window->IsFallbackWindow)
|
|
|
|
+ if ((g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (g.IO.ConfigDebugBeginReturnValueLoop && g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size))
|
|
|
|
+ {
|
|
|
|
+ if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; }
|
|
|
|
+ if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
|
|
return !window->SkipItems;
|
|
return !window->SkipItems;
|
|
}
|
|
}
|
|
@@ -8438,7 +8445,7 @@ void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
g.NavFocusScopeId = focus_scope_id;
|
|
g.NavFocusScopeId = focus_scope_id;
|
|
- g.NavFocusScopePath.resize(0); // Invalidate
|
|
|
|
|
|
+ g.NavFocusRoute.resize(0); // Invalidate
|
|
if (focus_scope_id == 0)
|
|
if (focus_scope_id == 0)
|
|
return;
|
|
return;
|
|
IM_ASSERT(g.NavWindow != NULL);
|
|
IM_ASSERT(g.NavWindow != NULL);
|
|
@@ -8448,17 +8455,17 @@ void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
|
|
{
|
|
{
|
|
// Top of focus stack contains local focus scopes inside current window
|
|
// Top of focus stack contains local focus scopes inside current window
|
|
for (int n = g.FocusScopeStack.Size - 1; n >= 0 && g.FocusScopeStack.Data[n].WindowID == g.CurrentWindow->ID; n--)
|
|
for (int n = g.FocusScopeStack.Size - 1; n >= 0 && g.FocusScopeStack.Data[n].WindowID == g.CurrentWindow->ID; n--)
|
|
- g.NavFocusScopePath.push_back(g.FocusScopeStack.Data[n]);
|
|
|
|
|
|
+ g.NavFocusRoute.push_back(g.FocusScopeStack.Data[n]);
|
|
}
|
|
}
|
|
else if (focus_scope_id == g.NavWindow->NavRootFocusScopeId)
|
|
else if (focus_scope_id == g.NavWindow->NavRootFocusScopeId)
|
|
- g.NavFocusScopePath.push_back({ focus_scope_id, g.NavWindow->ID });
|
|
|
|
|
|
+ g.NavFocusRoute.push_back({ focus_scope_id, g.NavWindow->ID });
|
|
else
|
|
else
|
|
return;
|
|
return;
|
|
|
|
|
|
// Then follow on manually set ParentWindowForFocusRoute field (#6798)
|
|
// Then follow on manually set ParentWindowForFocusRoute field (#6798)
|
|
for (ImGuiWindow* window = g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute)
|
|
for (ImGuiWindow* window = g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute)
|
|
- g.NavFocusScopePath.push_back({ window->NavRootFocusScopeId, window->ID });
|
|
|
|
- IM_ASSERT(g.NavFocusScopePath.Size < 100); // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3
|
|
|
|
|
|
+ g.NavFocusRoute.push_back({ window->NavRootFocusScopeId, window->ID });
|
|
|
|
+ IM_ASSERT(g.NavFocusRoute.Size < 100); // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3
|
|
}
|
|
}
|
|
|
|
|
|
// Focus = move navigation cursor, set scrolling, set focus window.
|
|
// Focus = move navigation cursor, set scrolling, set focus window.
|
|
@@ -8922,13 +8929,11 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable;
|
|
ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable;
|
|
ImGuiKeyRoutingData* routing_data;
|
|
ImGuiKeyRoutingData* routing_data;
|
|
- if (key_chord & ImGuiMod_Shortcut)
|
|
|
|
- key_chord = ConvertShortcutMod(key_chord);
|
|
|
|
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
if (key == ImGuiKey_None)
|
|
if (key == ImGuiKey_None)
|
|
key = ConvertSingleModFlagToKey(&g, mods);
|
|
key = ConvertSingleModFlagToKey(&g, mods);
|
|
- IM_ASSERT(IsNamedKey(key));
|
|
|
|
|
|
+ IM_ASSERT(IsNamedKey(key) && (key_chord & ImGuiMod_Shortcut) == 0); // Please call ConvertShortcutMod() in calling function.
|
|
|
|
|
|
// Get (in the majority of case, the linked list will have one element so this should be 2 reads.
|
|
// Get (in the majority of case, the linked list will have one element so this should be 2 reads.
|
|
// Subsequent elements will be contiguous in memory as list is sorted/rebuilt in NewFrame).
|
|
// Subsequent elements will be contiguous in memory as list is sorted/rebuilt in NewFrame).
|
|
@@ -8977,8 +8982,8 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput
|
|
// This essentially follow the window->ParentWindowForFocusRoute chain.
|
|
// This essentially follow the window->ParentWindowForFocusRoute chain.
|
|
if (focus_scope_id == 0)
|
|
if (focus_scope_id == 0)
|
|
return 255;
|
|
return 255;
|
|
- for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusScopePath.Size; index_in_focus_path++)
|
|
|
|
- if (g.NavFocusScopePath.Data[index_in_focus_path].ID == focus_scope_id)
|
|
|
|
|
|
+ for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++)
|
|
|
|
+ if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
|
|
return 3 + index_in_focus_path;
|
|
return 3 + index_in_focus_path;
|
|
|
|
|
|
return 255;
|
|
return 255;
|
|
@@ -8992,6 +8997,24 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// We need this to filter some Shortcut() routes when an item e.g. an InputText() is active
|
|
|
|
+// e.g. ImGuiKey_G won't be considered a shortcut when item is active, but ImGuiMod|ImGuiKey_G can be.
|
|
|
|
+static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord)
|
|
|
|
+{
|
|
|
|
+ // Mimic 'ignore_char_inputs' logic in InputText()
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+
|
|
|
|
+ // When the right mods are pressed it cannot be a char input so we won't filter the shortcut out.
|
|
|
|
+ ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
|
|
+ const bool ignore_char_inputs = ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Super));
|
|
|
|
+ if (ignore_char_inputs)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ // Return true for A-Z, 0-9 and other keys associated to char inputs. Other keys such as F1-F12 won't be filtered.
|
|
|
|
+ ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
|
|
+ return g.KeysMayBeCharInput.TestBit(key);
|
|
|
|
+}
|
|
|
|
+
|
|
// Request a desired route for an input chord (key + mods).
|
|
// Request a desired route for an input chord (key + mods).
|
|
// Return true if the route is available this frame.
|
|
// Return true if the route is available this frame.
|
|
// - Routes and key ownership are attributed at the beginning of next frame based on best score and mod state.
|
|
// - Routes and key ownership are attributed at the beginning of next frame based on best score and mod state.
|
|
@@ -9006,14 +9029,17 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI
|
|
flags |= ImGuiInputFlags_RouteGlobalHigh; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut()
|
|
flags |= ImGuiInputFlags_RouteGlobalHigh; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut()
|
|
else
|
|
else
|
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used
|
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used
|
|
|
|
+ if (key_chord & ImGuiMod_Shortcut)
|
|
|
|
+ key_chord = ConvertShortcutMod(key_chord);
|
|
|
|
|
|
// [DEBUG] Debug break requested by user
|
|
// [DEBUG] Debug break requested by user
|
|
- if (g.DebugBreakInShortcutRouting != 0 && g.DebugBreakInShortcutRouting == ConvertShortcutMod(key_chord))
|
|
|
|
|
|
+ if (g.DebugBreakInShortcutRouting == key_chord)
|
|
IM_DEBUG_BREAK();
|
|
IM_DEBUG_BREAK();
|
|
|
|
|
|
if (flags & ImGuiInputFlags_RouteUnlessBgFocused)
|
|
if (flags & ImGuiInputFlags_RouteUnlessBgFocused)
|
|
if (g.NavWindow == NULL)
|
|
if (g.NavWindow == NULL)
|
|
return false;
|
|
return false;
|
|
|
|
+
|
|
// Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this?
|
|
// Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this?
|
|
if (flags & ImGuiInputFlags_RouteAlways)
|
|
if (flags & ImGuiInputFlags_RouteAlways)
|
|
{
|
|
{
|
|
@@ -9021,6 +9047,18 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Specific culling for shortcuts with no modifiers when there's an active id.
|
|
|
|
+ // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active.
|
|
|
|
+ // but Shortcut(Ctrl+G) should generally trigger when InputText() is active.
|
|
|
|
+ // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active.
|
|
|
|
+ // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined)
|
|
|
|
+ if ((flags & ImGuiInputFlags_RouteFocused) && (g.ActiveId != 0 && g.ActiveId != owner_id))
|
|
|
|
+ if (g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord))
|
|
|
|
+ {
|
|
|
|
+ IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags);
|
|
const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags);
|
|
IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score);
|
|
IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score);
|
|
if (score == 255)
|
|
if (score == 255)
|
|
@@ -9048,6 +9086,8 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI
|
|
bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
|
|
bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
|
|
{
|
|
{
|
|
const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
|
|
const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
|
|
|
|
+ if (key_chord & ImGuiMod_Shortcut)
|
|
|
|
+ key_chord = ConvertShortcutMod(key_chord);
|
|
ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); // FIXME: Could avoid creating entry.
|
|
ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); // FIXME: Could avoid creating entry.
|
|
return routing_data->RoutingCurr == routing_id;
|
|
return routing_data->RoutingCurr == routing_id;
|
|
}
|
|
}
|
|
@@ -10016,7 +10056,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
|
|
|
|
|
|
// Default repeat behavior for Shortcut()
|
|
// Default repeat behavior for Shortcut()
|
|
// So e.g. pressing Ctrl+W and releasing Ctrl while holding W will not trigger the W shortcut.
|
|
// So e.g. pressing Ctrl+W and releasing Ctrl while holding W will not trigger the W shortcut.
|
|
- if ((flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
|
|
|
|
|
|
+ if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
|
|
flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
|
|
flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
|
|
|
|
|
|
if (!IsKeyChordPressed(key_chord, owner_id, flags))
|
|
if (!IsKeyChordPressed(key_chord, owner_id, flags))
|
|
@@ -10341,77 +10381,21 @@ void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
|
|
IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!");
|
|
IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!");
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
-// [SECTION] LAYOUT
|
|
|
|
|
|
+// [SECTION] ITEM SUBMISSION
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
-// - ItemSize()
|
|
|
|
|
|
+// - KeepAliveID()
|
|
// - ItemAdd()
|
|
// - ItemAdd()
|
|
-// - SameLine()
|
|
|
|
-// - GetCursorScreenPos()
|
|
|
|
-// - SetCursorScreenPos()
|
|
|
|
-// - GetCursorPos(), GetCursorPosX(), GetCursorPosY()
|
|
|
|
-// - SetCursorPos(), SetCursorPosX(), SetCursorPosY()
|
|
|
|
-// - GetCursorStartPos()
|
|
|
|
-// - Indent()
|
|
|
|
-// - Unindent()
|
|
|
|
-// - SetNextItemWidth()
|
|
|
|
-// - PushItemWidth()
|
|
|
|
-// - PushMultiItemsWidths()
|
|
|
|
-// - PopItemWidth()
|
|
|
|
-// - CalcItemWidth()
|
|
|
|
-// - CalcItemSize()
|
|
|
|
-// - GetTextLineHeight()
|
|
|
|
-// - GetTextLineHeightWithSpacing()
|
|
|
|
-// - GetFrameHeight()
|
|
|
|
-// - GetFrameHeightWithSpacing()
|
|
|
|
-// - GetContentRegionMax()
|
|
|
|
-// - GetContentRegionMaxAbs() [Internal]
|
|
|
|
-// - GetContentRegionAvail(),
|
|
|
|
-// - GetWindowContentRegionMin(), GetWindowContentRegionMax()
|
|
|
|
-// - BeginGroup()
|
|
|
|
-// - EndGroup()
|
|
|
|
-// Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
-// Advance cursor given item size for layout.
|
|
|
|
-// Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
|
|
|
|
-// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
|
|
|
|
-// THIS IS IN THE PERFORMANCE CRITICAL PATH.
|
|
|
|
-void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
|
|
|
|
|
|
+// Code not using ItemAdd() may need to call this manually otherwise ActiveId will be cleared. In IMGUI_VERSION_NUM < 18717 this was called by GetID().
|
|
|
|
+void ImGui::KeepAliveID(ImGuiID id)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
- ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
- if (window->SkipItems)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- // We increase the height in this function to accommodate for baseline offset.
|
|
|
|
- // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor,
|
|
|
|
- // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect.
|
|
|
|
- const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
|
|
|
|
-
|
|
|
|
- const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
|
|
|
|
- const float line_height = ImMax(window->DC.CurrLineSize.y, /*ImMax(*/window->DC.CursorPos.y - line_y1/*, 0.0f)*/ + size.y + offset_to_match_baseline_y);
|
|
|
|
-
|
|
|
|
- // Always align ourselves on pixel boundaries
|
|
|
|
- //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
|
|
|
|
- window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
|
|
|
|
- window->DC.CursorPosPrevLine.y = line_y1;
|
|
|
|
- window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line
|
|
|
|
- window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y); // Next line
|
|
|
|
- window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
|
|
|
|
- window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
|
|
|
|
- //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
|
|
|
|
-
|
|
|
|
- window->DC.PrevLineSize.y = line_height;
|
|
|
|
- window->DC.CurrLineSize.y = 0.0f;
|
|
|
|
- window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
|
|
|
|
- window->DC.CurrLineTextBaseOffset = 0.0f;
|
|
|
|
- window->DC.IsSameLine = window->DC.IsSetPos = false;
|
|
|
|
-
|
|
|
|
- // Horizontal layout mode
|
|
|
|
- if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
|
|
|
- SameLine();
|
|
|
|
|
|
+ if (g.ActiveId == id)
|
|
|
|
+ g.ActiveIdIsAlive = id;
|
|
|
|
+ if (g.ActiveIdPreviousFrame == id)
|
|
|
|
+ g.ActiveIdPreviousFrameIsAlive = true;
|
|
}
|
|
}
|
|
|
|
|
|
// Declare item bounding box for clipping and interaction.
|
|
// Declare item bounding box for clipping and interaction.
|
|
@@ -10502,6 +10486,78 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
+// [SECTION] LAYOUT
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
+// - ItemSize()
|
|
|
|
+// - SameLine()
|
|
|
|
+// - GetCursorScreenPos()
|
|
|
|
+// - SetCursorScreenPos()
|
|
|
|
+// - GetCursorPos(), GetCursorPosX(), GetCursorPosY()
|
|
|
|
+// - SetCursorPos(), SetCursorPosX(), SetCursorPosY()
|
|
|
|
+// - GetCursorStartPos()
|
|
|
|
+// - Indent()
|
|
|
|
+// - Unindent()
|
|
|
|
+// - SetNextItemWidth()
|
|
|
|
+// - PushItemWidth()
|
|
|
|
+// - PushMultiItemsWidths()
|
|
|
|
+// - PopItemWidth()
|
|
|
|
+// - CalcItemWidth()
|
|
|
|
+// - CalcItemSize()
|
|
|
|
+// - GetTextLineHeight()
|
|
|
|
+// - GetTextLineHeightWithSpacing()
|
|
|
|
+// - GetFrameHeight()
|
|
|
|
+// - GetFrameHeightWithSpacing()
|
|
|
|
+// - GetContentRegionMax()
|
|
|
|
+// - GetContentRegionMaxAbs() [Internal]
|
|
|
|
+// - GetContentRegionAvail(),
|
|
|
|
+// - GetWindowContentRegionMin(), GetWindowContentRegionMax()
|
|
|
|
+// - BeginGroup()
|
|
|
|
+// - EndGroup()
|
|
|
|
+// Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns.
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+// Advance cursor given item size for layout.
|
|
|
|
+// Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
|
|
|
|
+// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
|
|
|
|
+// THIS IS IN THE PERFORMANCE CRITICAL PATH.
|
|
|
|
+void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
+ if (window->SkipItems)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ // We increase the height in this function to accommodate for baseline offset.
|
|
|
|
+ // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor,
|
|
|
|
+ // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect.
|
|
|
|
+ const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
|
|
|
|
+
|
|
|
|
+ const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
|
|
|
|
+ const float line_height = ImMax(window->DC.CurrLineSize.y, /*ImMax(*/window->DC.CursorPos.y - line_y1/*, 0.0f)*/ + size.y + offset_to_match_baseline_y);
|
|
|
|
+
|
|
|
|
+ // Always align ourselves on pixel boundaries
|
|
|
|
+ //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
|
|
|
|
+ window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
|
|
|
|
+ window->DC.CursorPosPrevLine.y = line_y1;
|
|
|
|
+ window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line
|
|
|
|
+ window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y); // Next line
|
|
|
|
+ window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
|
|
|
|
+ window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
|
|
|
|
+ //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
|
|
|
|
+
|
|
|
|
+ window->DC.PrevLineSize.y = line_height;
|
|
|
|
+ window->DC.CurrLineSize.y = 0.0f;
|
|
|
|
+ window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
|
|
|
|
+ window->DC.CurrLineTextBaseOffset = 0.0f;
|
|
|
|
+ window->DC.IsSameLine = window->DC.IsSetPos = false;
|
|
|
|
+
|
|
|
|
+ // Horizontal layout mode
|
|
|
|
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
|
|
|
+ SameLine();
|
|
|
|
+}
|
|
|
|
+
|
|
// Gets back to previous line and continue with horizontal layout
|
|
// Gets back to previous line and continue with horizontal layout
|
|
// offset_from_start_x == 0 : follow right after previous item
|
|
// offset_from_start_x == 0 : follow right after previous item
|
|
// offset_from_start_x != 0 : align to specified x position (relative to window/group left)
|
|
// offset_from_start_x != 0 : align to specified x position (relative to window/group left)
|
|
@@ -20211,10 +20267,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
Text("NavActivateFlags: %04X", g.NavActivateFlags);
|
|
Text("NavActivateFlags: %04X", g.NavActivateFlags);
|
|
Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
|
|
Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
|
|
Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
|
|
Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
|
|
- Text("NavFocusScopePath[] = ");
|
|
|
|
- for (int path_n = g.NavFocusScopePath.Size - 1; path_n >= 0; path_n--)
|
|
|
|
|
|
+ Text("NavFocusRoute[] = ");
|
|
|
|
+ for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
|
|
{
|
|
{
|
|
- const ImGuiFocusScopeData& focus_scope = g.NavFocusScopePath[path_n];
|
|
|
|
|
|
+ const ImGuiFocusScopeData& focus_scope = g.NavFocusRoute[path_n];
|
|
SameLine(0.0f, 0.0f);
|
|
SameLine(0.0f, 0.0f);
|
|
Text("0x%08X/", focus_scope.ID);
|
|
Text("0x%08X/", focus_scope.ID);
|
|
SetItemTooltip("In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name);
|
|
SetItemTooltip("In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name);
|
|
@@ -21323,9 +21379,6 @@ void ImGui::DebugLogV(const char*, va_list) {}
|
|
void ImGui::ShowDebugLogWindow(bool*) {}
|
|
void ImGui::ShowDebugLogWindow(bool*) {}
|
|
void ImGui::ShowIDStackToolWindow(bool*) {}
|
|
void ImGui::ShowIDStackToolWindow(bool*) {}
|
|
void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
|
|
void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
|
|
-void ImGui::UpdateDebugToolItemPicker() {}
|
|
|
|
-void ImGui::UpdateDebugToolStackQueries() {}
|
|
|
|
-void ImGui::UpdateDebugToolFlashStyleColor() {}
|
|
|
|
|
|
|
|
#endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
#endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
|
|
|