|
|
@@ -1390,10 +1390,10 @@ static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::
|
|
|
{
|
|
|
ImVector<ImGuiStorage::Pair>::iterator first = data.begin();
|
|
|
ImVector<ImGuiStorage::Pair>::iterator last = data.end();
|
|
|
- int count = (int)(last - first);
|
|
|
+ size_t count = (size_t)(last - first);
|
|
|
while (count > 0)
|
|
|
{
|
|
|
- int count2 = count / 2;
|
|
|
+ size_t count2 = count >> 1;
|
|
|
ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
|
|
|
if (mid->key < key)
|
|
|
{
|
|
|
@@ -2467,6 +2467,7 @@ void ImGui::Shutdown()
|
|
|
g.WindowsSortBuffer.clear();
|
|
|
g.CurrentWindow = NULL;
|
|
|
g.CurrentWindowStack.clear();
|
|
|
+ g.WindowsById.Clear();
|
|
|
g.NavWindow = NULL;
|
|
|
g.HoveredWindow = NULL;
|
|
|
g.HoveredRootWindow = NULL;
|
|
|
@@ -3110,6 +3111,7 @@ void ImGui::RenderTriangle(ImVec2 p_min, ImGuiDir dir, float scale)
|
|
|
case ImGuiDir_Left:
|
|
|
r = -r; // ...fall through, no break!
|
|
|
case ImGuiDir_Right:
|
|
|
+ center.x -= r * 0.25f;
|
|
|
a = ImVec2(1,0) * r;
|
|
|
b = ImVec2(-0.500f,+0.866f) * r;
|
|
|
c = ImVec2(-0.500f,-0.866f) * r;
|
|
|
@@ -3924,13 +3926,9 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size,
|
|
|
|
|
|
ImGuiWindow* ImGui::FindWindowByName(const char* name)
|
|
|
{
|
|
|
- // FIXME-OPT: Store sorted hashes -> pointers so we can do a bissection in a contiguous block
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiID id = ImHash(name, 0);
|
|
|
- for (int i = 0; i < g.Windows.Size; i++)
|
|
|
- if (g.Windows[i]->ID == id)
|
|
|
- return g.Windows[i];
|
|
|
- return NULL;
|
|
|
+ return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id);
|
|
|
}
|
|
|
|
|
|
static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)
|
|
|
@@ -3941,6 +3939,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
|
|
ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow));
|
|
|
IM_PLACEMENT_NEW(window) ImGuiWindow(name);
|
|
|
window->Flags = flags;
|
|
|
+ g.WindowsById.SetVoidPtr(window->ID, window);
|
|
|
|
|
|
if (flags & ImGuiWindowFlags_NoSavedSettings)
|
|
|
{
|
|
|
@@ -4043,7 +4042,7 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window)
|
|
|
if (size_auto_fit_after_constraint.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar))
|
|
|
size_auto_fit.y += style.ScrollbarSize;
|
|
|
if (size_auto_fit_after_constraint.y < window->SizeContents.y && !(flags & ImGuiWindowFlags_NoScrollbar))
|
|
|
- size_auto_fit.x += style.ScrollbarSize * 2.0f;
|
|
|
+ size_auto_fit.x += style.ScrollbarSize;
|
|
|
size_auto_fit.y = ImMax(size_auto_fit.y - style.ItemSpacing.y, 0.0f);
|
|
|
}
|
|
|
return size_auto_fit;
|
|
|
@@ -4113,12 +4112,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
else
|
|
|
flags = window->Flags;
|
|
|
|
|
|
+ // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
|
|
|
+ ImGuiWindow* parent_window = first_begin_of_the_frame ? (!g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow;
|
|
|
+ IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
|
|
|
+
|
|
|
// Add to stack
|
|
|
- ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL;
|
|
|
g.CurrentWindowStack.push_back(window);
|
|
|
SetCurrentWindow(window);
|
|
|
CheckStacksSize(window, true);
|
|
|
- IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
|
|
|
|
|
|
bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
|
|
|
if (flags & ImGuiWindowFlags_Popup)
|
|
|
@@ -4185,21 +4186,17 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
g.SetNextWindowFocus = false;
|
|
|
}
|
|
|
|
|
|
- // Update known root window (if we are a child window, otherwise window == window->RootWindow)
|
|
|
- int root_idx, root_non_popup_idx;
|
|
|
- for (root_idx = g.CurrentWindowStack.Size - 1; root_idx > 0; root_idx--)
|
|
|
- if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow))
|
|
|
- break;
|
|
|
- for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--)
|
|
|
- if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (g.CurrentWindowStack[root_non_popup_idx]->Flags & ImGuiWindowFlags_Modal))
|
|
|
- break;
|
|
|
- window->ParentWindow = parent_window;
|
|
|
- window->RootWindow = g.CurrentWindowStack[root_idx];
|
|
|
- window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
|
|
-
|
|
|
// When reusing window again multiple times a frame, just append content (don't need to setup again)
|
|
|
if (first_begin_of_the_frame)
|
|
|
{
|
|
|
+ // Initialize
|
|
|
+ window->ParentWindow = parent_window;
|
|
|
+ window->RootWindow = !(flags & ImGuiWindowFlags_ChildWindow) ? window : parent_window->RootWindow;
|
|
|
+ window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
|
|
+ //window->RootNavWindow = window;
|
|
|
+ //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened)
|
|
|
+ // window->RootNavWindow = window->RootNavWindow->ParentWindow;
|
|
|
+
|
|
|
window->Active = true;
|
|
|
window->OrderWithinParent = 0;
|
|
|
window->BeginCount = 0;
|
|
|
@@ -4243,10 +4240,21 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
// SIZE
|
|
|
|
|
|
- // Save contents size from last frame for auto-fitting (unless explicitly specified)
|
|
|
+ // Update contents size from last frame for auto-fitting (unless explicitly specified)
|
|
|
window->SizeContents.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x));
|
|
|
window->SizeContents.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y));
|
|
|
|
|
|
+ // Update scrollbar status based on the Size that was effective during last frame (and not the upcoming Size which we are updating below), so that user code consuming exactly the available size won't trigger scrollbars when e.g. manually resizing.
|
|
|
+ if (!window->Collapsed)
|
|
|
+ {
|
|
|
+ window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
|
|
+ window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
|
|
+ if (window->ScrollbarX && !window->ScrollbarY)
|
|
|
+ window->ScrollbarY = (window->SizeContents.y > window->Size.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
|
|
+ window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
|
|
+ window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
|
|
|
+ }
|
|
|
+
|
|
|
// Hide popup/tooltip window when first appearing while we measure size (because we recycle them)
|
|
|
if (window->HiddenFrames > 0)
|
|
|
window->HiddenFrames--;
|
|
|
@@ -4262,7 +4270,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
}
|
|
|
|
|
|
// Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects.
|
|
|
- window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding;
|
|
|
+ window->WindowPadding = style.WindowPadding;
|
|
|
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup)))
|
|
|
+ window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
|
|
|
|
|
|
// Calculate auto-fit size, handle automatic resize
|
|
|
const ImVec2 size_auto_fit = CalcSizeAutoFit(window);
|
|
|
@@ -4395,7 +4405,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
// Manual resize
|
|
|
// Using the FlattenChilds button flag, we make the resize button accessible even if we are hovering over a child window
|
|
|
const ImVec2 br = window->Rect().GetBR();
|
|
|
- const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br);
|
|
|
+ const ImRect resize_rect(br - ImFloor(ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f)), br);
|
|
|
const ImGuiID resize_id = window->GetID("#RESIZE");
|
|
|
bool hovered, held;
|
|
|
ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds);
|
|
|
@@ -4413,7 +4423,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
else if (held)
|
|
|
{
|
|
|
// We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
|
|
|
- size_target = (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos;
|
|
|
+ size_target = (g.IO.MousePos - g.ActiveIdClickOffset - window->Pos) + resize_rect.GetSize();
|
|
|
}
|
|
|
|
|
|
if (size_target.x != FLT_MAX && size_target.y != FLT_MAX)
|
|
|
@@ -4425,14 +4435,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
title_bar_rect = window->TitleBarRect();
|
|
|
}
|
|
|
|
|
|
- // Scrollbars
|
|
|
- window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
|
|
- window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
|
|
- if (window->ScrollbarX && !window->ScrollbarY)
|
|
|
- window->ScrollbarY = (window->SizeContents.y > window->Size.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
|
|
- window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
|
|
- window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
|
|
|
-
|
|
|
// Window background, Default Alpha
|
|
|
ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
|
|
|
window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight);
|
|
|
@@ -5289,8 +5291,7 @@ bool ImGui::IsWindowAppearing()
|
|
|
|
|
|
void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
|
|
|
{
|
|
|
- ImGuiWindow* window = FindWindowByName(name);
|
|
|
- if (window)
|
|
|
+ if (ImGuiWindow* window = FindWindowByName(name))
|
|
|
SetWindowCollapsed(window, collapsed, cond);
|
|
|
}
|
|
|
|
|
|
@@ -5829,6 +5830,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|
|
if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window)
|
|
|
g.HoveredWindow = backup_hovered_window;
|
|
|
|
|
|
+ // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.
|
|
|
+ if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
|
|
|
+ hovered = false;
|
|
|
+
|
|
|
if (hovered)
|
|
|
{
|
|
|
if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
|
|
|
@@ -5848,11 +5853,15 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|
|
{
|
|
|
pressed = true;
|
|
|
if (flags & ImGuiButtonFlags_NoHoldingActiveID)
|
|
|
+ {
|
|
|
ClearActiveID();
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
SetActiveID(id, window); // Hold on ID
|
|
|
+ g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
|
|
|
+ }
|
|
|
FocusWindow(window);
|
|
|
- g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
|
|
|
}
|
|
|
if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0])
|
|
|
{
|
|
|
@@ -5884,10 +5893,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.
|
|
|
- if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
|
|
|
- hovered = pressed = held = false;
|
|
|
-
|
|
|
if (out_hovered) *out_hovered = hovered;
|
|
|
if (out_held) *out_held = held;
|
|
|
|
|
|
@@ -9102,7 +9107,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
|
|
|
PopStyleColor();
|
|
|
}
|
|
|
if (selected)
|
|
|
- RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * (0.20f+0.200f), g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
|
|
|
+ RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
|
|
|
}
|
|
|
return pressed;
|
|
|
}
|
|
|
@@ -9221,7 +9226,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
|
|
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
|
|
|
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
|
|
|
if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
|
|
|
- RenderTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), ImGuiDir_Right);
|
|
|
+ RenderTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right);
|
|
|
if (!enabled) PopStyleColor();
|
|
|
}
|
|
|
|
|
|
@@ -10463,8 +10468,8 @@ void ImGui::EndColumns()
|
|
|
{
|
|
|
float x = window->Pos.x + GetColumnOffset(i);
|
|
|
const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i);
|
|
|
- const float column_w = 4.0f; // Width for interaction
|
|
|
- const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2));
|
|
|
+ const float column_hw = 4.0f; // Half-width for interaction
|
|
|
+ const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2));
|
|
|
if (IsClippedEx(column_rect, column_id, false))
|
|
|
continue;
|
|
|
|
|
|
@@ -10475,7 +10480,7 @@ void ImGui::EndColumns()
|
|
|
if (hovered || held)
|
|
|
g.MouseCursor = ImGuiMouseCursor_ResizeEW;
|
|
|
if (held && g.ActiveIdIsJustActivated)
|
|
|
- g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset().
|
|
|
+ g.ActiveIdClickOffset.x -= column_hw; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset().
|
|
|
if (held)
|
|
|
dragging_column = i;
|
|
|
}
|