Updated ImGui.
This commit is contained in:
Родитель
9e00fad8b3
Коммит
c6d99b4809
|
@ -661,7 +661,6 @@ static ImRect GetVisibleRect();
|
|||
static void CloseInactivePopups(ImGuiWindow* ref_window);
|
||||
static void ClosePopupToLevel(int remaining);
|
||||
static ImGuiWindow* GetFrontMostModalRootWindow();
|
||||
static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& rect_to_avoid);
|
||||
|
||||
static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data);
|
||||
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
|
||||
|
@ -2031,26 +2030,35 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id)
|
|||
bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
// Test for bounding box overlap, as updated as ItemAdd()
|
||||
if (!window->DC.LastItemRectHoveredRect)
|
||||
return false;
|
||||
IM_ASSERT((flags & ImGuiHoveredFlags_FlattenChilds) == 0); // Flags not supported by this function
|
||||
|
||||
// Test if we are hovering the right window (our window could be behind another window)
|
||||
// [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself.
|
||||
// Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
|
||||
//if (g.HoveredWindow != window)
|
||||
// return false;
|
||||
if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
|
||||
return false;
|
||||
|
||||
// Test if another item is active (e.g. being dragged)
|
||||
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
|
||||
return false;
|
||||
|
||||
// Test if interactions on this window are blocked by an active popup or modal
|
||||
if (!IsWindowContentHoverable(window, flags))
|
||||
return false;
|
||||
|
||||
// Test if the item is disabled
|
||||
if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
|
||||
return false;
|
||||
// Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten.
|
||||
|
||||
// Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case.
|
||||
if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
|
||||
return false;
|
||||
return true;
|
||||
|
@ -2445,9 +2453,10 @@ void ImGui::NewFrame()
|
|||
}
|
||||
else if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse))
|
||||
{
|
||||
// Scroll
|
||||
const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5;
|
||||
SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * window->CalcFontSize() * scroll_lines);
|
||||
// Mouse wheel Scrolling
|
||||
float scroll_amount = 5 * window->CalcFontSize();
|
||||
scroll_amount = (float)(int)ImMin(scroll_amount, (window->ContentsRegionRect.GetHeight() + window->WindowPadding.y * 2.0f) * 0.67f);
|
||||
SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * scroll_amount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2764,8 +2773,6 @@ static int ChildWindowComparer(const void* lhs, const void* rhs)
|
|||
return d;
|
||||
if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
|
||||
return d;
|
||||
if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox))
|
||||
return d;
|
||||
return (a->OrderWithinParent - b->OrderWithinParent);
|
||||
}
|
||||
|
||||
|
@ -3636,17 +3643,17 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_
|
|||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
char window_name[16];
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip%02d", g.TooltipOverrideCount);
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
|
||||
if (override_previous_tooltip)
|
||||
if (ImGuiWindow* window = ImGui::FindWindowByName(window_name))
|
||||
if (ImGuiWindow* window = FindWindowByName(window_name))
|
||||
if (window->Active)
|
||||
{
|
||||
// Hide previous tooltips. We can't easily "reset" the content of a window so we create a new one.
|
||||
window->HiddenFrames = 1;
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip%02d", ++g.TooltipOverrideCount);
|
||||
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
|
||||
}
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
|
||||
ImGui::Begin(window_name, NULL, flags | extra_flags);
|
||||
Begin(window_name, NULL, flags | extra_flags);
|
||||
}
|
||||
|
||||
void ImGui::SetTooltipV(const char* fmt, va_list args)
|
||||
|
@ -3684,7 +3691,7 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing)
|
|||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
int current_stack_size = g.CurrentPopupStack.Size;
|
||||
ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here)
|
||||
ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##Menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here)
|
||||
if (g.OpenPopupStack.Size < current_stack_size + 1)
|
||||
g.OpenPopupStack.push_back(popup_ref);
|
||||
else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id)
|
||||
|
@ -3798,9 +3805,9 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
|
|||
|
||||
char name[20];
|
||||
if (flags & ImGuiWindowFlags_ChildMenu)
|
||||
ImFormatString(name, IM_ARRAYSIZE(name), "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth
|
||||
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth
|
||||
else
|
||||
ImFormatString(name, IM_ARRAYSIZE(name), "##popup_%08x", id); // Not recycling, so we can close/open during the same frame
|
||||
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
|
||||
|
||||
bool is_open = Begin(name, NULL, flags);
|
||||
if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
|
||||
|
@ -3925,7 +3932,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
|
|||
|
||||
const ImVec2 content_avail = ImGui::GetContentRegionAvail();
|
||||
ImVec2 size = ImFloor(size_arg);
|
||||
const int auto_fit_axises = ((size.x == 0.0f) ? 0x01 : 0x00) | ((size.y == 0.0f) ? 0x02 : 0x00);
|
||||
const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
|
||||
if (size.x <= 0.0f)
|
||||
size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues)
|
||||
if (size.y <= 0.0f)
|
||||
|
@ -3967,7 +3974,7 @@ void ImGui::EndChild()
|
|||
ImGuiWindow* window = GetCurrentWindow();
|
||||
|
||||
IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss
|
||||
if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
|
||||
if (window->BeginCount > 1)
|
||||
{
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -3975,9 +3982,9 @@ void ImGui::EndChild()
|
|||
{
|
||||
// When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting.
|
||||
ImVec2 sz = GetWindowSize();
|
||||
if (window->AutoFitChildAxises & 0x01) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
|
||||
if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
|
||||
sz.x = ImMax(4.0f, sz.x);
|
||||
if (window->AutoFitChildAxises & 0x02)
|
||||
if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
|
||||
sz.y = ImMax(4.0f, sz.y);
|
||||
ImGui::End();
|
||||
|
||||
|
@ -4022,7 +4029,13 @@ static void CheckStacksSize(ImGuiWindow* window, bool write)
|
|||
IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
|
||||
}
|
||||
|
||||
static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_avoid)
|
||||
enum ImGuiPopupPositionPolicy
|
||||
{
|
||||
ImGuiPopupPositionPolicy_Default,
|
||||
ImGuiPopupPositionPolicy_ComboBox
|
||||
};
|
||||
|
||||
static ImVec2 FindBestWindowPosForPopup(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy = ImGuiPopupPositionPolicy_Default)
|
||||
{
|
||||
const ImGuiStyle& style = GImGui->Style;
|
||||
|
||||
|
@ -4031,21 +4044,42 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size,
|
|||
ImVec2 safe_padding = style.DisplaySafeAreaPadding;
|
||||
ImRect r_outer(GetVisibleRect());
|
||||
r_outer.Expand(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? -safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? -safe_padding.y : 0.0f));
|
||||
ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size);
|
||||
ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
|
||||
//GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255));
|
||||
//GImGui->OverlayDrawList.AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255));
|
||||
|
||||
// Combo Box policy (we want a connecting edge)
|
||||
if (policy == ImGuiPopupPositionPolicy_ComboBox)
|
||||
{
|
||||
const ImGuiDir dir_prefered_order[ImGuiDir_Count_] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
|
||||
for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_Count_; n++)
|
||||
{
|
||||
const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
|
||||
if (n != -1 && dir == *last_dir) // Already tried this direction?
|
||||
continue;
|
||||
ImVec2 pos;
|
||||
if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default)
|
||||
if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right
|
||||
if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left
|
||||
if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left
|
||||
if (!r_outer.Contains(ImRect(pos, pos + size)))
|
||||
continue;
|
||||
*last_dir = dir;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
// Default popup policy
|
||||
const ImGuiDir dir_prefered_order[ImGuiDir_Count_] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
|
||||
for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_Count_; n++)
|
||||
{
|
||||
const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
|
||||
if (n != -1 && dir == *last_dir) // Already tried this direction?
|
||||
continue;
|
||||
float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
|
||||
if (avail_w < size.x)
|
||||
continue;
|
||||
float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
|
||||
if (avail_h < size.y)
|
||||
if (avail_w < size.x || avail_h < size.y)
|
||||
continue;
|
||||
|
||||
ImVec2 pos;
|
||||
pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
|
||||
pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
|
||||
|
@ -4055,7 +4089,7 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size,
|
|||
|
||||
// Fallback, try to keep within display
|
||||
*last_dir = ImGuiDir_None;
|
||||
ImVec2 pos = base_pos;
|
||||
ImVec2 pos = ref_pos;
|
||||
pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
|
||||
pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
|
||||
return pos;
|
||||
|
@ -4126,7 +4160,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
|||
return window;
|
||||
}
|
||||
|
||||
static ImVec2 CalcSizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size)
|
||||
static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.SetNextWindowSizeConstraint)
|
||||
|
@ -4146,6 +4180,8 @@ static ImVec2 CalcSizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size)
|
|||
new_size = data.DesiredSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Minimum size
|
||||
if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
|
||||
{
|
||||
new_size = ImMax(new_size, g.Style.WindowMinSize);
|
||||
|
@ -4154,7 +4190,15 @@ static ImVec2 CalcSizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size)
|
|||
return new_size;
|
||||
}
|
||||
|
||||
static ImVec2 CalcSizeAutoFit(ImGuiWindow* window)
|
||||
static ImVec2 CalcSizeContents(ImGuiWindow* window)
|
||||
{
|
||||
ImVec2 sz;
|
||||
sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x));
|
||||
sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y));
|
||||
return sz + window->WindowPadding;
|
||||
}
|
||||
|
||||
static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
|
@ -4163,16 +4207,16 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window)
|
|||
if ((flags & ImGuiWindowFlags_Tooltip) != 0)
|
||||
{
|
||||
// Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.
|
||||
size_auto_fit = window->SizeContents;
|
||||
size_auto_fit = size_contents;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handling case of auto fit window not fitting on the screen (on either axis): we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding.
|
||||
size_auto_fit = ImClamp(window->SizeContents, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding));
|
||||
ImVec2 size_auto_fit_after_constraint = CalcSizeFullWithConstraint(window, size_auto_fit);
|
||||
if (size_auto_fit_after_constraint.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar))
|
||||
// When the window cannot fit all contents (either because of constraints, either because screen is too small): we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding.
|
||||
size_auto_fit = ImClamp(size_contents, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding));
|
||||
ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit);
|
||||
if (size_auto_fit_after_constraint.x < size_contents.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))
|
||||
if (size_auto_fit_after_constraint.y < size_contents.y && !(flags & ImGuiWindowFlags_NoScrollbar))
|
||||
size_auto_fit.x += style.ScrollbarSize;
|
||||
}
|
||||
return size_auto_fit;
|
||||
|
@ -4220,7 +4264,7 @@ static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& co
|
|||
ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left
|
||||
ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right
|
||||
ImVec2 size_expected = pos_max - pos_min;
|
||||
ImVec2 size_constrained = CalcSizeFullWithConstraint(window, size_expected);
|
||||
ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected);
|
||||
*out_pos = pos_min;
|
||||
if (corner_norm.x == 0.0f)
|
||||
out_pos->x -= (size_constrained.x - size_expected.x);
|
||||
|
@ -4275,13 +4319,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
||||
|
||||
// Find or create
|
||||
bool window_is_new = false;
|
||||
ImGuiWindow* window = FindWindowByName(name);
|
||||
if (!window)
|
||||
{
|
||||
ImVec2 size_on_first_use = (g.SetNextWindowSizeCond != 0) ? g.SetNextWindowSizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
|
||||
window = CreateNewWindow(name, size_on_first_use, flags);
|
||||
window_is_new = true;
|
||||
}
|
||||
|
||||
const int current_frame = g.FrameCount;
|
||||
|
@ -4322,7 +4364,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
}
|
||||
|
||||
// Process SetNextWindow***() calls
|
||||
bool window_pos_set_by_api = false, window_size_set_by_api = false;
|
||||
bool window_pos_set_by_api = false;
|
||||
bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
|
||||
if (g.SetNextWindowPosCond)
|
||||
{
|
||||
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0;
|
||||
|
@ -4342,7 +4385,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
}
|
||||
if (g.SetNextWindowSizeCond)
|
||||
{
|
||||
window_size_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0;
|
||||
window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0 && (g.SetNextWindowSizeVal.x > 0.0f);
|
||||
window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0 && (g.SetNextWindowSizeVal.y > 0.0f);
|
||||
SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond);
|
||||
g.SetNextWindowSizeCond = 0;
|
||||
}
|
||||
|
@ -4390,7 +4434,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
window->DrawList->Clear();
|
||||
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
||||
ImRect fullscreen_rect(GetVisibleRect());
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup)))
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))
|
||||
PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);
|
||||
else
|
||||
PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true);
|
||||
|
@ -4423,11 +4467,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
// SIZE
|
||||
|
||||
// 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));
|
||||
window->SizeContents += window->WindowPadding;
|
||||
window->SizeContents = CalcSizeContents(window);
|
||||
|
||||
// Hide popup/tooltip window when first appearing while we measure size (because we recycle them)
|
||||
// Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
|
||||
if (window->HiddenFrames > 0)
|
||||
window->HiddenFrames--;
|
||||
if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_just_activated_by_user)
|
||||
|
@ -4435,8 +4477,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
window->HiddenFrames = 1;
|
||||
if (flags & ImGuiWindowFlags_AlwaysAutoResize)
|
||||
{
|
||||
if (!window_size_set_by_api)
|
||||
window->Size = window->SizeFull = ImVec2(0.f, 0.f);
|
||||
if (!window_size_x_set_by_api)
|
||||
window->Size.x = window->SizeFull.x = 0.f;
|
||||
if (!window_size_y_set_by_api)
|
||||
window->Size.y = window->SizeFull.y = 0.f;
|
||||
window->SizeContents = ImVec2(0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
@ -4445,46 +4489,40 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
||||
window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
|
||||
window->WindowPadding = style.WindowPadding;
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
|
||||
window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
|
||||
const float window_rounding = window->WindowRounding;
|
||||
const float window_border_size = window->WindowBorderSize;
|
||||
|
||||
// Calculate auto-fit size, handle automatic resize
|
||||
const ImVec2 size_auto_fit = CalcSizeAutoFit(window);
|
||||
ImVec2 size_for_scrollbars_visibility = window->SizeFullAtLastBegin;
|
||||
if (window->Collapsed)
|
||||
const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
|
||||
ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
|
||||
if (flags & ImGuiWindowFlags_AlwaysAutoResize && !window->Collapsed)
|
||||
{
|
||||
// We still process initial auto-fit on collapsed windows to get a window width,
|
||||
// But otherwise we don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
|
||||
if (window->AutoFitFramesX > 0)
|
||||
window->SizeFull.x = size_for_scrollbars_visibility.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
|
||||
if (window->AutoFitFramesY > 0)
|
||||
window->SizeFull.y = size_for_scrollbars_visibility.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
|
||||
// Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
|
||||
if (!window_size_x_set_by_api)
|
||||
window->SizeFull.x = size_full_modified.x = size_auto_fit.x;
|
||||
if (!window_size_y_set_by_api)
|
||||
window->SizeFull.y = size_full_modified.y = size_auto_fit.y;
|
||||
}
|
||||
else if (!window_size_set_by_api)
|
||||
else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
|
||||
{
|
||||
if (flags & ImGuiWindowFlags_AlwaysAutoResize)
|
||||
{
|
||||
window->SizeFull = size_for_scrollbars_visibility = size_auto_fit;
|
||||
}
|
||||
else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
|
||||
{
|
||||
// Auto-fit only grows during the first few frames
|
||||
if (window->AutoFitFramesX > 0)
|
||||
window->SizeFull.x = size_for_scrollbars_visibility.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
|
||||
if (window->AutoFitFramesY > 0)
|
||||
window->SizeFull.y = size_for_scrollbars_visibility.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
|
||||
// Auto-fit only grows during the first few frames
|
||||
// We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
|
||||
if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
|
||||
window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
|
||||
if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
|
||||
window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
|
||||
if (!window->Collapsed)
|
||||
MarkIniSettingsDirty(window);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply minimum/maximum window size constraints and final size
|
||||
window->SizeFull = CalcSizeFullWithConstraint(window, window->SizeFull);
|
||||
window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull);
|
||||
window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull;
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))
|
||||
{
|
||||
IM_ASSERT(window_size_set_by_api); // Submitted by BeginChild()
|
||||
IM_ASSERT(window_size_x_set_by_api && window_size_x_set_by_api); // Submitted by BeginChild()
|
||||
window->Size = window->SizeFull;
|
||||
}
|
||||
|
||||
|
@ -4493,10 +4531,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
// Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size).
|
||||
if (!window->Collapsed)
|
||||
{
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_for_scrollbars_visibility.y) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_for_scrollbars_visibility.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
// When reading the current size we need to read it after size constraints have been applied
|
||||
float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x;
|
||||
float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y;
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (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 > size_for_scrollbars_visibility.y + style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars + style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
||||
}
|
||||
|
||||
|
@ -4528,12 +4569,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight());
|
||||
else
|
||||
rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);
|
||||
window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
|
||||
window->PosFloat = FindBestWindowPosForPopup(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
|
||||
}
|
||||
else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
|
||||
{
|
||||
ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1);
|
||||
window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
|
||||
window->PosFloat = FindBestWindowPosForPopup(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
|
||||
}
|
||||
|
||||
// Position tooltip (always follows mouse)
|
||||
|
@ -4541,7 +4582,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
{
|
||||
ImVec2 ref_pos = g.IO.MousePos;
|
||||
ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Store boxes in mouse cursor data? Scale? Center on cursor hit-point?
|
||||
window->PosFloat = FindBestPopupWindowPos(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
|
||||
window->PosFloat = FindBestWindowPosForPopup(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
|
||||
if (window->AutoPosLastDirection == ImGuiDir_None)
|
||||
window->PosFloat = ref_pos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.
|
||||
}
|
||||
|
@ -4627,7 +4668,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||
if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
|
||||
{
|
||||
// Manual auto-fit when double-clicking
|
||||
size_target = CalcSizeFullWithConstraint(window, size_auto_fit);
|
||||
size_target = CalcSizeAfterConstraint(window, size_auto_fit);
|
||||
ClearActiveID();
|
||||
}
|
||||
else if (held)
|
||||
|
@ -9030,6 +9071,154 @@ bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_fla
|
|||
return InputIntN(label, v, 4, extra_flags);
|
||||
}
|
||||
|
||||
static float CalcMaxPopupHeightFromItemCount(int items_count)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (items_count <= 0)
|
||||
return FLT_MAX;
|
||||
return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
|
||||
}
|
||||
|
||||
bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
|
||||
{
|
||||
// Always consume the SetNextWindowSizeConstraint() call in our early return paths
|
||||
ImGuiContext& g = *GImGui;
|
||||
bool backup_has_next_window_size_constraint = g.SetNextWindowSizeConstraint;
|
||||
g.SetNextWindowSizeConstraint = false;
|
||||
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const float w = CalcItemWidth();
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id))
|
||||
return false;
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
|
||||
bool popup_open = IsPopupOpen(id);
|
||||
|
||||
const float arrow_size = SmallSquareSize();
|
||||
const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING
|
||||
RenderTriangle(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down);
|
||||
if (preview_value != NULL)
|
||||
RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
|
||||
if (pressed && !popup_open)
|
||||
{
|
||||
OpenPopupEx(id, false);
|
||||
popup_open = true;
|
||||
}
|
||||
|
||||
if (!popup_open)
|
||||
return false;
|
||||
|
||||
if (backup_has_next_window_size_constraint)
|
||||
{
|
||||
g.SetNextWindowSizeConstraint = true;
|
||||
g.SetNextWindowSizeConstraintRect.Min.x = ImMax(g.SetNextWindowSizeConstraintRect.Min.x, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flags & ImGuiComboFlags_HeightMask_) == 0)
|
||||
flags |= ImGuiComboFlags_HeightRegular;
|
||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one
|
||||
int popup_max_height_in_items = -1;
|
||||
if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
|
||||
else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
|
||||
else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
|
||||
SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
|
||||
}
|
||||
|
||||
char name[16];
|
||||
ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth
|
||||
|
||||
// Peak into expected window size so we can position it
|
||||
if (ImGuiWindow* popup_window = FindWindowByName(name))
|
||||
{
|
||||
ImVec2 size_contents = CalcSizeContents(popup_window);
|
||||
ImVec2 size_expected = CalcSizeAfterConstraint(popup_window, CalcSizeAutoFit(popup_window, size_contents));
|
||||
if (flags & ImGuiComboFlags_PopupAlignLeft)
|
||||
popup_window->AutoPosLastDirection = ImGuiDir_Left;
|
||||
ImVec2 pos = FindBestWindowPosForPopup(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
|
||||
SetNextWindowPos(pos);
|
||||
}
|
||||
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
|
||||
if (!Begin(name, NULL, window_flags))
|
||||
{
|
||||
EndPopup();
|
||||
IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
|
||||
return false;
|
||||
}
|
||||
|
||||
// Horizontally align ourselves with the framed text
|
||||
if (style.FramePadding.x != style.WindowPadding.x)
|
||||
Indent(style.FramePadding.x - style.WindowPadding.x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui::EndCombo()
|
||||
{
|
||||
const ImGuiStyle& style = GImGui->Style;
|
||||
if (style.FramePadding.x != style.WindowPadding.x)
|
||||
Unindent(style.FramePadding.x - style.WindowPadding.x);
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
// Combo box function.
|
||||
bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
const char* preview_text = NULL;
|
||||
if (*current_item >= 0 && *current_item < items_count)
|
||||
items_getter(data, *current_item, &preview_text);
|
||||
|
||||
if (popup_max_height_in_items != -1 && !g.SetNextWindowSizeConstraint)
|
||||
{
|
||||
float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items);
|
||||
SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height));
|
||||
}
|
||||
if (!BeginCombo(label, preview_text, 0))
|
||||
return false;
|
||||
|
||||
// Display items
|
||||
// FIXME-OPT: Use clipper
|
||||
bool value_changed = false;
|
||||
for (int i = 0; i < items_count; i++)
|
||||
{
|
||||
PushID((void*)(intptr_t)i);
|
||||
const bool item_selected = (i == *current_item);
|
||||
const char* item_text;
|
||||
if (!items_getter(data, i, &item_text))
|
||||
item_text = "*Unknown item*";
|
||||
if (Selectable(item_text, item_selected))
|
||||
{
|
||||
value_changed = true;
|
||||
*current_item = i;
|
||||
}
|
||||
if (item_selected && IsWindowAppearing())
|
||||
SetScrollHere();
|
||||
PopID();
|
||||
}
|
||||
|
||||
EndCombo();
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
|
||||
{
|
||||
const char* const* items = (const char* const*)data;
|
||||
|
@ -9079,129 +9268,6 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa
|
|||
return value_changed;
|
||||
}
|
||||
|
||||
bool ImGui::BeginCombo(const char* label, const char* preview_value, ImVec2 popup_size)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const float w = CalcItemWidth();
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id))
|
||||
return false;
|
||||
|
||||
const float arrow_size = SmallSquareSize();
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
|
||||
|
||||
bool popup_open = IsPopupOpen(id);
|
||||
|
||||
const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING
|
||||
RenderTriangle(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down);
|
||||
|
||||
if (preview_value != NULL)
|
||||
RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
|
||||
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
|
||||
if (pressed && !popup_open)
|
||||
{
|
||||
OpenPopupEx(id, false);
|
||||
popup_open = true;
|
||||
}
|
||||
|
||||
if (!popup_open)
|
||||
return false;
|
||||
|
||||
if (popup_size.x == 0.0f)
|
||||
popup_size.x = w;
|
||||
|
||||
float popup_y1 = frame_bb.Max.y;
|
||||
float popup_y2 = ImClamp(popup_y1 + popup_size.y, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y);
|
||||
if ((popup_y2 - popup_y1) < ImMin(popup_size.y, frame_bb.Min.y - style.DisplaySafeAreaPadding.y))
|
||||
{
|
||||
// Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement)
|
||||
popup_y1 = ImClamp(frame_bb.Min.y - popup_size.y, style.DisplaySafeAreaPadding.y, frame_bb.Min.y);
|
||||
popup_y2 = frame_bb.Min.y;
|
||||
SetNextWindowPos(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FrameBorderSize), ImGuiCond_Always, ImVec2(0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Position our combo below
|
||||
SetNextWindowPos(ImVec2(frame_bb.Min.x, frame_bb.Max.y - style.FrameBorderSize), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
|
||||
}
|
||||
SetNextWindowSize(ImVec2(popup_size.x, popup_y2 - popup_y1), ImGuiCond_Appearing);
|
||||
PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
|
||||
|
||||
if (!BeginPopupEx(id, ImGuiWindowFlags_ComboBox))
|
||||
{
|
||||
IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
|
||||
return false;
|
||||
}
|
||||
Spacing();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui::EndCombo()
|
||||
{
|
||||
EndPopup();
|
||||
PopStyleVar();
|
||||
}
|
||||
|
||||
// Combo box function.
|
||||
bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
const char* preview_text = NULL;
|
||||
if (*current_item >= 0 && *current_item < items_count)
|
||||
items_getter(data, *current_item, &preview_text);
|
||||
|
||||
// Size default to hold ~7 items
|
||||
if (height_in_items < 0)
|
||||
height_in_items = 7;
|
||||
float popup_height = (g.FontSize + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3);
|
||||
|
||||
if (!BeginCombo(label, preview_text, ImVec2(0.0f, popup_height)))
|
||||
return false;
|
||||
|
||||
// Display items
|
||||
// FIXME-OPT: Use clipper
|
||||
bool value_changed = false;
|
||||
for (int i = 0; i < items_count; i++)
|
||||
{
|
||||
PushID((void*)(intptr_t)i);
|
||||
const bool item_selected = (i == *current_item);
|
||||
const char* item_text;
|
||||
if (!items_getter(data, i, &item_text))
|
||||
item_text = "*Unknown item*";
|
||||
if (Selectable(item_text, item_selected))
|
||||
{
|
||||
value_changed = true;
|
||||
*current_item = i;
|
||||
}
|
||||
if (item_selected && IsWindowAppearing())
|
||||
SetScrollHere();
|
||||
PopID();
|
||||
}
|
||||
|
||||
EndCombo();
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
// Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image.
|
||||
// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID.
|
||||
bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
|
||||
|
@ -9520,7 +9586,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
|||
|
||||
bool pressed;
|
||||
bool menu_is_open = IsPopupOpen(id);
|
||||
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus"));
|
||||
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##Menus"));
|
||||
ImGuiWindow* backed_nav_window = g.NavWindow;
|
||||
if (menuset_is_open)
|
||||
g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
|
||||
|
@ -10900,7 +10966,7 @@ void ImGui::Indent(float indent_w)
|
|||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->DC.IndentX += (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing;
|
||||
window->DC.IndentX += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
|
||||
window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX;
|
||||
}
|
||||
|
||||
|
@ -10908,7 +10974,7 @@ void ImGui::Unindent(float indent_w)
|
|||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->DC.IndentX -= (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing;
|
||||
window->DC.IndentX -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
|
||||
window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,8 +218,8 @@ namespace ImGui
|
|||
IMGUI_API void NewLine(); // undo a SameLine()
|
||||
IMGUI_API void Spacing(); // add vertical spacing
|
||||
IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size
|
||||
IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if >0
|
||||
IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if >0
|
||||
IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if != 0
|
||||
IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if != 0
|
||||
IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
|
||||
IMGUI_API void EndGroup();
|
||||
IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position
|
||||
|
@ -517,12 +517,11 @@ enum ImGuiWindowFlags_
|
|||
ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // (WIP) Enable resize from any corners and borders. Your back-end needs to honor the different values of io.MouseCursor set by imgui.
|
||||
|
||||
// [Internal]
|
||||
ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild()
|
||||
ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox()
|
||||
ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip()
|
||||
ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup()
|
||||
ImGuiWindowFlags_Modal = 1 << 26, // Don't use! For internal use by BeginPopupModal()
|
||||
ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu()
|
||||
ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild()
|
||||
ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip()
|
||||
ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup()
|
||||
ImGuiWindowFlags_Modal = 1 << 27, // Don't use! For internal use by BeginPopupModal()
|
||||
ImGuiWindowFlags_ChildMenu = 1 << 28 // Don't use! For internal use by BeginMenu()
|
||||
};
|
||||
|
||||
// Flags for ImGui::InputText()
|
||||
|
|
|
@ -318,7 +318,7 @@ void ImGui::ShowTestWindow(bool* p_open)
|
|||
static int item = 1;
|
||||
ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo)
|
||||
|
||||
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" };
|
||||
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO", "PPPP", "QQQQQQQQQQ", "RRR", "SSSS" };
|
||||
static int item2 = -1;
|
||||
ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that.
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior()
|
|||
typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_
|
||||
typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_
|
||||
typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_
|
||||
typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// STB libraries
|
||||
|
@ -209,6 +210,18 @@ enum ImGuiSelectableFlagsPrivate_
|
|||
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6
|
||||
};
|
||||
|
||||
enum ImGuiComboFlags_
|
||||
{
|
||||
ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default
|
||||
|
||||
// If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo()
|
||||
ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible
|
||||
ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default)
|
||||
ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible
|
||||
ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible
|
||||
ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest
|
||||
};
|
||||
|
||||
enum ImGuiSeparatorFlags_
|
||||
{
|
||||
ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
|
||||
|
@ -847,7 +860,7 @@ namespace ImGui
|
|||
IMGUI_API void PushColumnClipRect(int column_index = -1);
|
||||
|
||||
// FIXME-WIP: New Combo API
|
||||
IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImVec2 popup_size = ImVec2(0.0f,0.0f));
|
||||
IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
|
||||
IMGUI_API void EndCombo();
|
||||
|
||||
// NB: All position are in absolute pixels coordinates (never using window coordinates internally)
|
||||
|
|
Загрузка…
Ссылка в новой задаче