Internals: ItemFlags is a shared resource as advertised. Fix Begin/PushItemFlags/End sequence (mostly for consistency)

This commit is contained in:
ocornut 2021-04-30 19:31:30 +02:00
parent 10a1c5b021
commit 9b90639577
4 changed files with 31 additions and 32 deletions

View File

@ -3176,7 +3176,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return false; return false;
// Test if the item is disabled // Test if the item is disabled
if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) if ((g.CurrentItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false; return false;
// Special handling for calling after Begin() which represent the title bar or tab. // Special handling for calling after Begin() which represent the title bar or tab.
@ -3202,7 +3202,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
return false; return false;
if (g.NavDisableMouseHover) if (g.NavDisableMouseHover)
return false; return false;
if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (window->DC.ItemFlags & ImGuiItemFlags_Disabled)) if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (g.CurrentItemFlags & ImGuiItemFlags_Disabled))
{ {
g.HoveredIdDisabled = true; g.HoveredIdDisabled = true;
return false; return false;
@ -3254,7 +3254,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
// Increment counters // Increment counters
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; const bool is_tab_stop = (g.CurrentItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
window->DC.FocusCounterRegular++; window->DC.FocusCounterRegular++;
if (is_tab_stop) if (is_tab_stop)
window->DC.FocusCounterTabStop++; window->DC.FocusCounterTabStop++;
@ -5613,8 +5613,8 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None); const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
// Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer) // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
// Layout buttons // Layout buttons
@ -5651,7 +5651,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
*p_open = false; *p_open = false;
window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.ItemFlags = item_flags_backup; g.CurrentItemFlags = item_flags_backup;
// Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
// FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code.. // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code..
@ -6297,7 +6297,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
// Pull/inherit current state // Pull/inherit current state
window->DC.ItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack g.CurrentItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595 window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
@ -6539,24 +6539,22 @@ void ImGui::PopFont()
void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiItemFlags item_flags = g.CurrentItemFlags;
ImGuiItemFlags item_flags = window->DC.ItemFlags;
IM_ASSERT(item_flags == g.ItemFlagsStack.back()); IM_ASSERT(item_flags == g.ItemFlagsStack.back());
if (enabled) if (enabled)
item_flags |= option; item_flags |= option;
else else
item_flags &= ~option; item_flags &= ~option;
window->DC.ItemFlags = item_flags; g.CurrentItemFlags = item_flags;
g.ItemFlagsStack.push_back(item_flags); g.ItemFlagsStack.push_back(item_flags);
} }
void ImGui::PopItemFlag() void ImGui::PopItemFlag()
{ {
ImGuiContext& g = *GImGui; 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. 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(); g.ItemFlagsStack.pop_back();
window->DC.ItemFlags = g.ItemFlagsStack.back(); g.CurrentItemFlags = g.ItemFlagsStack.back();
} }
// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system. // FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
@ -8780,7 +8778,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
//if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
// return; // return;
const ImGuiItemFlags item_flags = window->DC.ItemFlags; const ImGuiItemFlags item_flags = g.CurrentItemFlags;
const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
// Process Init Request // Process Init Request

View File

@ -61,7 +61,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.83 WIP" #define IMGUI_VERSION "1.83 WIP"
#define IMGUI_VERSION_NUM 18206 #define IMGUI_VERSION_NUM 18207
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE

View File

@ -1346,6 +1346,7 @@ struct ImGuiContext
float WheelingWindowTimer; float WheelingWindowTimer;
// Item/widgets state and tracking information // Item/widgets state and tracking information
ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame; ImGuiID HoveredIdPreviousFrame;
bool HoveredIdAllowOverlap; bool HoveredIdAllowOverlap;
@ -1574,6 +1575,7 @@ struct ImGuiContext
WheelingWindow = NULL; WheelingWindow = NULL;
WheelingWindowTimer = 0.0f; WheelingWindowTimer = 0.0f;
CurrentItemFlags = ImGuiItemFlags_None;
HoveredId = HoveredIdPreviousFrame = 0; HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false; HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;
@ -1750,7 +1752,6 @@ struct IMGUI_API ImGuiWindowTempData
// Local parameters stacks // 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. // 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; // == g.ItemFlagsStack.back()
float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window). float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window).
float TextWrapPos; // Current text wrap pos. float TextWrapPos; // Current text wrap pos.
ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth) ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth)
@ -2286,7 +2287,7 @@ namespace ImGui
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; } inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; }
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.ItemFlags; } inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.CurrentItemFlags; }
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void ClearActiveID(); IMGUI_API void ClearActiveID();

View File

@ -688,7 +688,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
if (!ItemAdd(bb, id)) if (!ItemAdd(bb, id))
return false; return false;
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat; flags |= ImGuiButtonFlags_Repeat;
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
@ -764,7 +764,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
if (!ItemAdd(bb, id)) if (!ItemAdd(bb, id))
return false; return false;
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat; flags |= ImGuiButtonFlags_Repeat;
bool hovered, held; bool hovered, held;
@ -1099,7 +1099,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
RenderNavHighlight(total_bb, id); RenderNavHighlight(total_bb, id);
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); 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); ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
bool mixed_value = (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) != 0; bool mixed_value = (g.CurrentItemFlags & ImGuiItemFlags_MixedValue) != 0;
if (mixed_value) if (mixed_value)
{ {
// Undocumented tristate/mixed/indeterminate checkbox (#2644) // Undocumented tristate/mixed/indeterminate checkbox (#2644)
@ -1131,11 +1131,11 @@ bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
bool pressed; bool pressed;
if (!all_on && any_on) if (!all_on && any_on)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiContext& g = *GImGui;
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_MixedValue; g.CurrentItemFlags |= ImGuiItemFlags_MixedValue;
pressed = Checkbox(label, &all_on); pressed = Checkbox(label, &all_on);
window->DC.ItemFlags = backup_item_flags; g.CurrentItemFlags = backup_item_flags;
} }
else else
{ {
@ -1433,10 +1433,10 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; g.CurrentItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
bool item_add = ItemAdd(bb, id); bool item_add = ItemAdd(bb, id);
window->DC.ItemFlags = item_flags_backup; g.CurrentItemFlags = item_flags_backup;
if (!item_add) if (!item_add)
return false; return false;
@ -2277,7 +2277,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
} }
if (g.ActiveId != id) if (g.ActiveId != id)
return false; return false;
if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
return false; return false;
switch (data_type) switch (data_type)
@ -2884,7 +2884,7 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
return false; return false;
switch (data_type) switch (data_type)
@ -6070,10 +6070,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
bool item_add; bool item_add;
if (flags & ImGuiSelectableFlags_Disabled) if (flags & ImGuiSelectableFlags_Disabled)
{ {
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; g.CurrentItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
item_add = ItemAdd(bb, id); item_add = ItemAdd(bb, id);
window->DC.ItemFlags = backup_item_flags; g.CurrentItemFlags = backup_item_flags;
} }
else else
{ {
@ -6151,7 +6151,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
// Automatically close popups // Automatically close popups
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup)) if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
CloseCurrentPopup(); CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);