mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-14 17:07:01 +00:00
Made ItemFlagsStack and GroupStack shared stacks.
This commit is contained in:
parent
12ba6f4606
commit
6e94013a3d
@ -68,6 +68,9 @@ Other Changes:
|
||||
- InputText: Fixed updating cursor/selection position when a callback altered the buffer in a way
|
||||
where the byte count is unchanged but the decoded character count changes. (#3587) [@gqw]
|
||||
- Metrics: Fixed mishandling of ImDrawCmd::VtxOffset in wireframe mesh renderer.
|
||||
- Misc: Made the ItemFlags stack shared, so effectively the ButtonRepeat/AllowKeyboardFocus states
|
||||
(and others exposed in internals such as PushItemFlag) are inherited by stacked Begin/End pairs,
|
||||
vs previously a non-child stacked Begin() would reset those flags back to zero for the stacked window.
|
||||
- Misc: Replaced UTF-8 decoder with one based on branchless one by Christopher Wellons. [@rokups]
|
||||
Super minor fix handling incomplete UTF-8 contents: if input does not contain enough bytes, decoder
|
||||
returns IM_UNICODE_CODEPOINT_INVALID and consume remaining bytes (vs old decoded consumed only 1 byte).
|
||||
|
77
imgui.cpp
77
imgui.cpp
@ -872,7 +872,7 @@ static int FindWindowFocusIndex(ImGuiWindow* window);
|
||||
// Error Checking
|
||||
static void ErrorCheckNewFrameSanityChecks();
|
||||
static void ErrorCheckEndFrameSanityChecks();
|
||||
static void ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write);
|
||||
static void ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool begin);
|
||||
|
||||
// Misc
|
||||
static void UpdateSettings();
|
||||
@ -2892,6 +2892,13 @@ static void SetCurrentWindow(ImGuiWindow* window)
|
||||
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
|
||||
}
|
||||
|
||||
void ImGui::GcCompactTransientMiscBuffers()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.ItemFlagsStack.clear();
|
||||
g.GroupStack.clear();
|
||||
}
|
||||
|
||||
// Free up/compact internal window buffers, we can use this when a window becomes unused.
|
||||
// This is currently unused by the library, but you may call this yourself for easy GC.
|
||||
// Not freed:
|
||||
@ -2906,10 +2913,8 @@ void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
|
||||
window->IDStack.clear();
|
||||
window->DrawList->_ClearFreeMemory();
|
||||
window->DC.ChildWindows.clear();
|
||||
window->DC.ItemFlagsStack.clear();
|
||||
window->DC.ItemWidthStack.clear();
|
||||
window->DC.TextWrapPosStack.clear();
|
||||
window->DC.GroupStack.clear();
|
||||
}
|
||||
|
||||
void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
|
||||
@ -3858,6 +3863,8 @@ void ImGui::NewFrame()
|
||||
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
|
||||
GcCompactTransientWindowBuffers(window);
|
||||
}
|
||||
if (g.GcCompactAll)
|
||||
GcCompactTransientMiscBuffers();
|
||||
g.GcCompactAll = false;
|
||||
|
||||
// Closing the focused window restore focus to the first active root window in descending z-order
|
||||
@ -3868,6 +3875,9 @@ void ImGui::NewFrame()
|
||||
// But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
|
||||
g.CurrentWindowStack.resize(0);
|
||||
g.BeginPopupStack.resize(0);
|
||||
g.ItemFlagsStack.resize(0);
|
||||
g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_);
|
||||
g.GroupStack.resize(0);
|
||||
ClosePopupsOverWindow(g.NavWindow, false);
|
||||
|
||||
// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack.
|
||||
@ -5978,13 +5988,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
|
||||
window->DC.ItemWidth = window->ItemWidthDefault;
|
||||
window->DC.TextWrapPos = -1.0f; // disabled
|
||||
window->DC.ItemFlagsStack.resize(0);
|
||||
window->DC.ItemWidthStack.resize(0);
|
||||
window->DC.TextWrapPosStack.resize(0);
|
||||
window->DC.GroupStack.resize(0);
|
||||
window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
|
||||
if (parent_window)
|
||||
window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
|
||||
|
||||
if (window->AutoFitFramesX > 0)
|
||||
window->AutoFitFramesX--;
|
||||
@ -6029,7 +6034,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
SetCurrentWindow(window);
|
||||
}
|
||||
|
||||
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // -V595
|
||||
// Pull/inherit current state
|
||||
window->DC.ItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack
|
||||
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595
|
||||
|
||||
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
|
||||
|
||||
@ -6257,19 +6264,25 @@ void ImGui::PopFont()
|
||||
|
||||
void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiItemFlags item_flags = window->DC.ItemFlags;
|
||||
IM_ASSERT(item_flags == g.ItemFlagsStack.back());
|
||||
if (enabled)
|
||||
window->DC.ItemFlags |= option;
|
||||
item_flags |= option;
|
||||
else
|
||||
window->DC.ItemFlags &= ~option;
|
||||
window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
|
||||
item_flags &= ~option;
|
||||
window->DC.ItemFlags = item_flags;
|
||||
g.ItemFlagsStack.push_back(item_flags);
|
||||
}
|
||||
|
||||
void ImGui::PopItemFlag()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->DC.ItemFlagsStack.pop_back();
|
||||
window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack.
|
||||
g.ItemFlagsStack.pop_back();
|
||||
window->DC.ItemFlags = g.ItemFlagsStack.back();
|
||||
}
|
||||
|
||||
// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
|
||||
@ -6886,27 +6899,29 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
|
||||
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
|
||||
}
|
||||
}
|
||||
|
||||
IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
|
||||
}
|
||||
|
||||
// Save and compare stack sizes on Begin()/End() to detect usage errors
|
||||
// Begin() calls this with write=true
|
||||
// End() calls this with write=false
|
||||
static void ImGui::ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write)
|
||||
static void ImGui::ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool begin)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
short* p = &window->DC.StackSizesBackup[0];
|
||||
|
||||
// Window stacks
|
||||
// NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
|
||||
{ int n = window->IDStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "PushID/PopID or TreeNode/TreePop Mismatch!"); p++; } // Too few or too many PopID()/TreePop()
|
||||
{ int n = window->DC.GroupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginGroup/EndGroup Mismatch!"); p++; } // Too few or too many EndGroup()
|
||||
// NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
|
||||
{ IM_ASSERT(window->IDStack.Size == 1 && "PushID/PopID or TreeNode/TreePop Mismatch!"); } // Too few or too many PopID()/TreePop();
|
||||
|
||||
// Global stacks
|
||||
// For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
|
||||
{ int n = g.BeginPopupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch!"); p++; }// Too few or too many EndMenu()/EndPopup()
|
||||
{ int n = g.ColorModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleColor/PopStyleColor Mismatch!"); p++; } // Too few or too many PopStyleColor()
|
||||
{ int n = g.StyleModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleVar/PopStyleVar Mismatch!"); p++; } // Too few or too many PopStyleVar()
|
||||
{ int n = g.FontStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushFont/PopFont Mismatch!"); p++; } // Too few or too many PopFont()
|
||||
{ int n = g.GroupStack.Size; if (begin) *p = (short)n; else IM_ASSERT(*p == n && "BeginGroup/EndGroup Mismatch!"); p++; } // Too few or too many EndGroup()
|
||||
{ int n = g.BeginPopupStack.Size; if (begin) *p = (short)n; else IM_ASSERT(*p == n && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch!"); p++; }// Too few or too many EndMenu()/EndPopup()
|
||||
{ int n = g.ColorModifiers.Size; if (begin) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleColor/PopStyleColor Mismatch!"); p++; } // Too few or too many PopStyleColor()
|
||||
{ int n = g.StyleModifiers.Size; if (begin) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleVar/PopStyleVar Mismatch!"); p++; } // Too few or too many PopStyleVar()
|
||||
{ int n = g.FontStack.Size; if (begin) *p = (short)n; else IM_ASSERT(*p >= n && "PushFont/PopFont Mismatch!"); p++; } // Too few or too many PopFont()
|
||||
IM_ASSERT(p == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
|
||||
}
|
||||
|
||||
@ -7310,8 +7325,9 @@ void ImGui::BeginGroup()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
|
||||
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
||||
g.GroupStack.resize(g.GroupStack.Size + 1);
|
||||
ImGuiGroupData& group_data = g.GroupStack.back();
|
||||
group_data.WindowID = window->ID;
|
||||
group_data.BackupCursorPos = window->DC.CursorPos;
|
||||
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
|
||||
group_data.BackupIndent = window->DC.Indent;
|
||||
@ -7334,9 +7350,10 @@ void ImGui::EndGroup()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_ASSERT(window->DC.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls
|
||||
IM_ASSERT(g.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls
|
||||
|
||||
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
||||
ImGuiGroupData& group_data = g.GroupStack.back();
|
||||
IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window?
|
||||
|
||||
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
|
||||
|
||||
@ -7351,7 +7368,7 @@ void ImGui::EndGroup()
|
||||
|
||||
if (!group_data.EmitItem)
|
||||
{
|
||||
window->DC.GroupStack.pop_back();
|
||||
g.GroupStack.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7380,7 +7397,7 @@ void ImGui::EndGroup()
|
||||
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
|
||||
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated;
|
||||
|
||||
window->DC.GroupStack.pop_back();
|
||||
g.GroupStack.pop_back();
|
||||
//window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
|
||||
}
|
||||
|
||||
|
8
imgui.h
8
imgui.h
@ -358,6 +358,10 @@ namespace ImGui
|
||||
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val);
|
||||
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val);
|
||||
IMGUI_API void PopStyleVar(int count = 1);
|
||||
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
|
||||
IMGUI_API void PopAllowKeyboardFocus();
|
||||
IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
|
||||
IMGUI_API void PopButtonRepeat();
|
||||
IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in.
|
||||
IMGUI_API ImFont* GetFont(); // get current font
|
||||
IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied
|
||||
@ -373,10 +377,6 @@ namespace ImGui
|
||||
IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions.
|
||||
IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // push word-wrapping position for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space
|
||||
IMGUI_API void PopTextWrapPos();
|
||||
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
|
||||
IMGUI_API void PopAllowKeyboardFocus();
|
||||
IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
|
||||
IMGUI_API void PopButtonRepeat();
|
||||
|
||||
// Cursor / Layout
|
||||
// - By "cursor" we mean the current output position.
|
||||
|
@ -826,6 +826,7 @@ struct ImGuiStyleMod
|
||||
// Stacked storage data for BeginGroup()/EndGroup()
|
||||
struct ImGuiGroupData
|
||||
{
|
||||
ImGuiID WindowID;
|
||||
ImVec2 BackupCursorPos;
|
||||
ImVec2 BackupCursorMaxPos;
|
||||
ImVec1 BackupIndent;
|
||||
@ -1208,6 +1209,8 @@ struct ImGuiContext
|
||||
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
|
||||
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
|
||||
ImVector<ImGuiID> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope()
|
||||
ImVector<ImGuiItemFlags>ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag()
|
||||
ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup()
|
||||
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
|
||||
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
|
||||
|
||||
@ -1553,14 +1556,12 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
|
||||
// Local parameters stacks
|
||||
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
|
||||
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
|
||||
ImGuiItemFlags ItemFlags; // == g.ItemFlagsStack.back()
|
||||
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
|
||||
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
|
||||
ImVector<ImGuiItemFlags>ItemFlagsStack;
|
||||
ImVector<float> ItemWidthStack;
|
||||
ImVector<float> TextWrapPosStack;
|
||||
ImVector<ImGuiGroupData>GroupStack;
|
||||
short StackSizesBackup[6]; // Store size of various stacks for asserting
|
||||
short StackSizesBackup[5]; // Store size of various stacks for asserting
|
||||
};
|
||||
|
||||
// Storage for one window
|
||||
@ -1849,6 +1850,7 @@ namespace ImGui
|
||||
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; }
|
||||
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
|
||||
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
|
||||
inline ImGuiItemFlags GetItemsFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.ItemFlags; }
|
||||
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
|
||||
IMGUI_API void ClearActiveID();
|
||||
@ -2045,6 +2047,7 @@ namespace ImGui
|
||||
IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp);
|
||||
|
||||
// Garbage collection
|
||||
IMGUI_API void GcCompactTransientMiscBuffers();
|
||||
IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window);
|
||||
IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window);
|
||||
|
||||
|
@ -1346,7 +1346,9 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
|
||||
// Horizontal Separator
|
||||
float x1 = window->Pos.x;
|
||||
float x2 = window->Pos.x + window->Size.x;
|
||||
if (!window->DC.GroupStack.empty())
|
||||
|
||||
// FIXME-WORKRECT: old hack (#205) until we decide of consistent behavior with WorkRect/Indent and Separator
|
||||
if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID)
|
||||
x1 += window->DC.Indent.x;
|
||||
|
||||
ImGuiColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
|
||||
@ -6500,7 +6502,7 @@ void ImGui::EndMenuBar()
|
||||
PopClipRect();
|
||||
PopID();
|
||||
window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
|
||||
window->DC.GroupStack.back().EmitItem = false;
|
||||
g.GroupStack.back().EmitItem = false;
|
||||
EndGroup(); // Restore position on layer 0
|
||||
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
||||
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
|
||||
|
Loading…
Reference in New Issue
Block a user