Merge branch 'master' into docking

# Conflicts:
#	examples/imgui_impl_glfw.cpp
#	examples/imgui_impl_win32.cpp
#	imgui.cpp
#	imgui_internal.h
This commit is contained in:
omar 2019-05-13 19:23:18 +02:00
commit 4158cba1ff
15 changed files with 386 additions and 263 deletions

View File

@ -33,13 +33,25 @@ HOW TO UPDATE?
-----------------------------------------------------------------------
Breaking Changes:
- IO: changed AddInputCharacter(unsigned short c) signature to AddInputCharacter(unsigned int c).
- Renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
Other Changes:
- Columns: Fixed Separator from creating an extraneous draw command. (#125)
- Columns: Fixed Selectable with SpanAllColumns flag from creating an extraneous draw command. (#125)
- Separator: Revert 1.70 "Declare its thickness (1.0f) to the layout" change. It's not incorrect
but it breaks existing some layout patterns. Will return back to it when we expose Separator flags.
- Fixed InputFloatX, SliderFloatX, DragFloatX functions erroneously reporting IsItemEdited() multiple
times when the text input doesn't match the formatted output value (e.g. input "1" shows "1.000").
It wasn't much of a problem because we typically use the return value instead of IsItemEdited() here.
- Fixed uses of IsItemDeactivated(), IsItemDeactivatedAfterEdit() on multi-components widgets and
after EndGroup(). (#2550, #1875)
- Scrollbar: Very minor bounding box adjustment to cope with various border size.
- ImFontAtlas: FreeType: Added RasterizerFlags::Monochrome flag to disable font anti-aliasing. (#2545)
Combine with RasterizerFlags::MonoHinting for best results.
- Examples/Backends: Don't filter characters under 0x10000 before calling io.AddInputCharacter(),
the filtering is done in io.AddInputCharacter() itself. This is in prevision for fuller Unicode
support. (#2538, #2541)
-----------------------------------------------------------------------

View File

@ -15,6 +15,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-05-11: Inputs: Don't filter character value from ALLEGRO_EVENT_KEY_CHAR before calling AddInputCharacter().
// 2019-04-30: Renderer: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2018-11-30: Platform: Added touchscreen support.
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
@ -353,8 +354,7 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT *ev)
return true;
case ALLEGRO_EVENT_KEY_CHAR:
if (ev->keyboard.display == g_Display)
if (ev->keyboard.unichar > 0 && ev->keyboard.unichar < 0x10000)
io.AddInputCharacter((unsigned short)ev->keyboard.unichar);
io.AddInputCharacter((unsigned int)ev->keyboard.unichar);
return true;
case ALLEGRO_EVENT_KEY_DOWN:
case ALLEGRO_EVENT_KEY_UP:

View File

@ -17,6 +17,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
@ -131,8 +132,7 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
g_PrevUserCallbackChar(window, c);
ImGuiIO& io = ImGui::GetIO();
if (c > 0 && c < 0x10000)
io.AddInputCharacter((unsigned short)c);
io.AddInputCharacter(c);
}
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)

View File

@ -118,7 +118,7 @@ void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y)
//printf("char_down_func %d '%c'\n", c, c);
ImGuiIO& io = ImGui::GetIO();
if (c >= 32)
io.AddInputCharacter((unsigned short)c);
io.AddInputCharacter((unsigned int)c);
// Store letters in KeysDown[] array as both uppercase and lowercase + Handle GLUT translating CTRL+A..CTRL+Z as 1..26.
// This is a hacky mess but GLUT is unable to distinguish e.g. a TAB key from CTRL+I so this is probably the best we can do here.

View File

@ -12,6 +12,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
@ -166,8 +167,7 @@ int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
if ((e->m_Char > 0 && e->m_Char < 0x10000))
io.AddInputCharacter((unsigned short)e->m_Char);
io.AddInputCharacter((unsigned int)e->m_Char);
return 0;
}

View File

@ -13,6 +13,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-07-07: Initial version.
@ -190,8 +191,8 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
for (int i = 0; i < len; i++)
{
int c = [str characterAtIndex:i];
if (c < 0xF700 && !io.KeyCtrl)
io.AddInputCharacter((unsigned short)c);
if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF))
io.AddInputCharacter((unsigned int)c);
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed
int key = mapCharacterToKey(c);

View File

@ -20,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
@ -361,8 +362,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
return 0;
case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacter((unsigned short)wParam);
io.AddInputCharacter((unsigned int)wParam);
return 0;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())

196
imgui.cpp
View File

@ -380,6 +380,8 @@ CODE
- 2018/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- 2019/05/13 (1.71) - renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
- 2019/05/11 (1.71) - changed io.AddInputCharacter(unsigned short c) signature to io.AddInputCharacter(unsigned int c).
- 2019/04/29 (1.70) - improved ImDrawList thick strokes (>1.0f) preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, they will appear thicker now.
- 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete).
- 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete).
@ -1289,9 +1291,10 @@ ImGuiIO::ImGuiIO()
// Pass in translated ASCII characters for text input.
// - with glfw you can get those from the callback set in glfwSetCharCallback()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
void ImGuiIO::AddInputCharacter(ImWchar c)
void ImGuiIO::AddInputCharacter(unsigned int c)
{
InputQueueCharacters.push_back(c);
if (c > 0 && c < 0x10000)
InputQueueCharacters.push_back((ImWchar)c);
}
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
@ -1300,7 +1303,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
{
unsigned int c = 0;
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
if (c > 0 && c <= 0xFFFF)
if (c > 0 && c < 0x10000)
InputQueueCharacters.push_back((ImWchar)c);
}
}
@ -2734,8 +2737,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
if (g.ActiveIdIsJustActivated)
{
g.ActiveIdTimer = 0.0f;
g.ActiveIdHasBeenPressed = false;
g.ActiveIdHasBeenEdited = false;
g.ActiveIdHasBeenPressedBefore = false;
g.ActiveIdHasBeenEditedBefore = false;
if (id != 0)
{
g.LastActiveId = id;
@ -2747,6 +2750,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.ActiveIdBlockNavInputFlags = 0;
g.ActiveIdAllowOverlap = false;
g.ActiveIdWindow = window;
g.ActiveIdHasBeenEditedThisFrame = false;
if (id)
{
g.ActiveIdIsAlive = id;
@ -2814,7 +2818,8 @@ void ImGui::MarkItemEdited(ImGuiID id)
IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out.
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
g.ActiveIdHasBeenEdited = true;
g.ActiveIdHasBeenEditedThisFrame = true;
g.ActiveIdHasBeenEditedBefore = true;
g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
}
@ -2852,10 +2857,11 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
return;
// Always align ourselves on pixel boundaries
const float line_height = ImMax(window->DC.CurrentLineSize.y, size.y);
const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
const float line_height = ImMax(window->DC.CurrLineSize.y, size.y);
const float text_base_offset = ImMax(window->DC.CurrLineTextBaseOffset, text_offset_y);
//if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y;
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y);
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
@ -2864,7 +2870,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
window->DC.PrevLineSize.y = line_height;
window->DC.PrevLineTextBaseOffset = text_base_offset;
window->DC.CurrentLineSize.y = window->DC.CurrentLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize.y = window->DC.CurrLineTextBaseOffset = 0.0f;
// Horizontal layout mode
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
@ -2901,6 +2907,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
window->DC.LastItemId = id;
window->DC.LastItemRect = bb;
window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (id != 0)
@ -3704,8 +3711,9 @@ void ImGui::NewFrame()
g.LastActiveIdTimer += g.IO.DeltaTime;
g.ActiveIdPreviousFrame = g.ActiveId;
g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
g.ActiveIdPreviousFrameHasBeenEdited = g.ActiveIdHasBeenEdited;
g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
g.ActiveIdIsAlive = 0;
g.ActiveIdHasBeenEditedThisFrame = false;
g.ActiveIdPreviousFrameIsAlive = false;
g.ActiveIdIsJustActivated = false;
if (g.TempInputTextId != 0 && g.ActiveId != g.TempInputTextId)
@ -4644,13 +4652,15 @@ bool ImGui::IsItemDeactivated()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDeactivated)
return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
}
bool ImGui::IsItemDeactivatedAfterEdit()
{
ImGuiContext& g = *GImGui;
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEdited || (g.ActiveId == 0 && g.ActiveIdHasBeenEdited));
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore));
}
bool ImGui::IsItemFocused()
@ -4970,7 +4980,7 @@ static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
{
ImGuiContext& g = *GImGui;
if (g.NextWindowData.SizeConstraintCond != 0)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
{
// Using -1,-1 on either X/Y axis to preserve the current size.
ImRect cr = g.NextWindowData.SizeConstraintRect;
@ -5350,7 +5360,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
{
// Adjust alpha. For docking
float alpha = 1.0f;
if (g.NextWindowData.BgAlphaCond != 0)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha)
alpha = g.NextWindowData.BgAlphaVal;
if (is_docking_transparent_payload)
alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
@ -5359,7 +5369,6 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
}
window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
}
g.NextWindowData.BgAlphaCond = 0;
// Title bar
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
@ -5513,7 +5522,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const bool window_is_fallback = (g.CurrentWindowStack.Size == 0);
if (window_just_created)
{
ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
ImVec2 size_on_first_use = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) ? g.NextWindowData.SizeVal : 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);
}
@ -5557,7 +5566,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Docking
// (NB: during the frame dock nodes are created, it is possible that (window->DockIsActive == false) even though (window->DockNode->Windows.Size > 1)
IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL); // Cannot be both
if (g.NextWindowData.DockCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasDock)
SetWindowDock(window, g.NextWindowData.DockId, g.NextWindowData.DockCond);
if (first_begin_of_the_frame)
{
@ -5594,7 +5603,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Process SetNextWindow***() calls
bool window_pos_set_by_api = false;
bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
if (g.NextWindowData.PosCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos)
{
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
@ -5610,13 +5619,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
}
}
if (g.NextWindowData.SizeCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)
{
window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
}
if (g.NextWindowData.ContentSizeCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
{
// Adjust passed "client size" to become a "window size"
window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal;
@ -5627,10 +5636,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
}
window->WindowClass = g.NextWindowData.WindowClass;
if (g.NextWindowData.CollapsedCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasWindowClass)
window->WindowClass = g.NextWindowData.WindowClass;
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
if (g.NextWindowData.FocusCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
FocusWindow(window);
if (window->Appearing)
SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
@ -6030,8 +6040,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.CursorPos = window->DC.CursorStartPos;
window->DC.CursorPosPrevLine = window->DC.CursorPos;
window->DC.CursorMaxPos = window->DC.CursorStartPos;
window->DC.CurrentLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.NavHideHighlightOneFrame = false;
window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
@ -6151,7 +6161,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->WriteAccessed = false;
window->BeginCount++;
g.NextWindowData.Clear();
g.NextWindowData.ClearFlags();
// When we are about to select this tab (which will only be visible on the _next frame_), flag it with a non-zero HiddenFramesCannotSkipItems.
// This will have the important effect of actually returning true in Begin() and not setting SkipItems, allowing an earlier submission of the window contents.
@ -6368,20 +6378,24 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
void ImGui::SetNextItemWidth(float item_width)
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.NextItemWidth = item_width;
ImGuiContext& g = *GImGui;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
g.NextItemData.Width = item_width;
}
void ImGui::PushItemWidth(float item_width)
{
ImGuiWindow* window = GetCurrentWindow();
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
}
void ImGui::PushMultiItemsWidths(int components, float w_full)
{
ImGuiWindow* window = GetCurrentWindow();
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiStyle& style = GImGui->Style;
const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
@ -6389,6 +6403,7 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
for (int i = 0; i < components-1; i++)
window->DC.ItemWidthStack.push_back(w_item_one);
window->DC.ItemWidth = window->DC.ItemWidthStack.back();
g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
}
void ImGui::PopItemWidth()
@ -6398,21 +6413,17 @@ void ImGui::PopItemWidth()
window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
}
// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(),
// Then consume the
float ImGui::GetNextItemWidth()
// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth().
// The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags()
float ImGui::CalcItemWidth()
{
ImGuiWindow* window = GImGui->CurrentWindow;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
float w;
if (window->DC.NextItemWidth != FLT_MAX)
{
w = window->DC.NextItemWidth;
window->DC.NextItemWidth = FLT_MAX;
}
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
w = g.NextItemData.Width;
else
{
w = window->DC.ItemWidth;
}
if (w < 0.0f)
{
float region_max_x = GetWorkRectMax().x;
@ -6422,21 +6433,10 @@ float ImGui::GetNextItemWidth()
return w;
}
// Calculate item width *without* popping/consuming NextItemWidth if it was set.
// (rarely used, which is why we avoid calling this from GetNextItemWidth() and instead do a backup/restore here)
float ImGui::CalcItemWidth()
{
ImGuiWindow* window = GImGui->CurrentWindow;
float backup_next_item_width = window->DC.NextItemWidth;
float w = GetNextItemWidth();
window->DC.NextItemWidth = backup_next_item_width;
return w;
}
// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == GetNextItemWidth().
// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth().
// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical.
// Note that only CalcItemWidth() is publicly exposed.
// The 4.0f here may be changed to match GetNextItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable)
// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable)
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h)
{
ImGuiWindow* window = GImGui->CurrentWindow;
@ -6991,6 +6991,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
g.NextWindowData.PosVal = pos;
g.NextWindowData.PosPivotVal = pivot;
g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
@ -7010,6 +7011,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
g.NextWindowData.SizeVal = size;
g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
}
@ -7017,7 +7019,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.SizeConstraintCond = ImGuiCond_Always;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
g.NextWindowData.SizeCallback = custom_callback;
g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
@ -7026,14 +7028,15 @@ void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& s
void ImGui::SetNextWindowContentSize(const ImVec2& size)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value.
g.NextWindowData.ContentSizeCond = ImGuiCond_Always;
}
void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed;
g.NextWindowData.CollapsedVal = collapsed;
g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
}
@ -7041,26 +7044,27 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
void ImGui::SetNextWindowFocus()
{
ImGuiContext& g = *GImGui;
g.NextWindowData.FocusCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
}
void ImGui::SetNextWindowBgAlpha(float alpha)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha;
g.NextWindowData.BgAlphaVal = alpha;
g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
}
void ImGui::SetNextWindowViewport(ImGuiID id)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.ViewportCond = ImGuiCond_Always;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasViewport;
g.NextWindowData.ViewportId = id;
}
void ImGui::SetNextWindowDockID(ImGuiID id, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasDock;
g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always;
g.NextWindowData.DockId = id;
}
@ -7068,6 +7072,7 @@ void ImGui::SetNextWindowDockID(ImGuiID id, ImGuiCond cond)
void ImGui::SetNextWindowClass(const ImGuiWindowClass* window_class)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasWindowClass;
g.NextWindowData.WindowClass = *window_class;
}
@ -7420,16 +7425,16 @@ void ImGui::BeginGroup()
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupIndent = window->DC.Indent;
group_data.BackupGroupOffset = window->DC.GroupOffset;
group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.AdvanceCursor = true;
group_data.EmitItem = true;
window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
window->DC.Indent = window->DC.GroupOffset;
window->DC.CursorMaxPos = window->DC.CursorPos;
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX; // To enforce Log carriage return
}
@ -7442,36 +7447,49 @@ void ImGui::EndGroup()
ImGuiGroupData& group_data = window->DC.GroupStack.back();
ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
group_bb.Max = ImMax(group_bb.Min, group_bb.Max);
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
window->DC.CursorPos = group_data.BackupCursorPos;
window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
window->DC.Indent = group_data.BackupIndent;
window->DC.GroupOffset = group_data.BackupGroupOffset;
window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
window->DC.CurrLineSize = group_data.BackupCurrLineSize;
window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX; // To enforce Log carriage return
if (group_data.AdvanceCursor)
if (!group_data.EmitItem)
{
window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
ItemSize(group_bb.GetSize(), 0.0f);
ItemAdd(group_bb, 0);
window->DC.GroupStack.pop_back();
return;
}
window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
ItemSize(group_bb.GetSize(), 0.0f);
ItemAdd(group_bb, 0);
// If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
// It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
// (and if you grep for LastItemId you'll notice it is only used in that context.
if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
// Also if you grep for LastItemId you'll notice it is only used in that context.
// (The tests not symmetrical because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
const bool group_contains_prev_active_id = !group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive;
if (group_contains_curr_active_id)
window->DC.LastItemId = g.ActiveId;
else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
else if (group_contains_prev_active_id)
window->DC.LastItemId = g.ActiveIdPreviousFrame;
window->DC.LastItemRect = group_bb;
window->DC.GroupStack.pop_back();
// Forward Edited flag
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
// Forward Deactivated flag
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated;
window->DC.GroupStack.pop_back();
//window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
}
@ -7499,8 +7517,8 @@ void ImGui::SameLine(float offset_from_start_x, float spacing_w)
window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
}
window->DC.CurrentLineSize = window->DC.PrevLineSize;
window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
window->DC.CurrLineSize = window->DC.PrevLineSize;
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
}
void ImGui::Indent(float indent_w)
@ -7777,7 +7795,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
ImGuiContext& g = *GImGui;
if (!IsPopupOpen(id))
{
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
@ -7799,7 +7817,7 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
ImGuiContext& g = *GImGui;
if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
{
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDocking;
@ -7815,13 +7833,13 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla
const ImGuiID id = window->GetID(name);
if (!IsPopupOpen(id))
{
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
return false;
}
// Center modal windows by default
// FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
if (g.NextWindowData.PosCond == 0)
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
SetNextWindowPos(window->Viewport->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDocking;
@ -9105,8 +9123,8 @@ void ImGui::NextColumn()
}
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->DC.CursorPos.y = columns->LineMinY;
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrentLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = 0.0f;
PushColumnClipRect(columns->Current);
PushItemWidth(GetColumnWidth() * 0.65f); // FIXME-COLUMNS: Move on columns setup
@ -10589,7 +10607,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
window->ViewportId = 0;
}
if (!g.NextWindowData.ViewportCond)
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport) == 0)
{
// By default inherit from parent window
if (window->Viewport == NULL && window->ParentWindow)
@ -10605,7 +10623,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
}
bool lock_viewport = false;
if (g.NextWindowData.ViewportCond)
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport)
{
// Code explicitly request a viewport
window->Viewport = (ImGuiViewportP*)FindViewportByID(g.NextWindowData.ViewportId);
@ -14286,7 +14304,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
continue;
}
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()),
"Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
if (show_drawcmd_clip_rects && fg_draw_list && ImGui::IsItemHovered())
{
ImRect clip_rect = pcmd->ClipRect;
@ -14387,7 +14407,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
static void NodeViewport(ImGuiViewportP* viewport)
{
ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once);
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode((void*)(intptr_t)viewport->ID, "Viewport #%d, ID: 0x%08X, Parent: 0x%08X, Window: \"%s\"", viewport->Idx, viewport->ID, viewport->ParentViewportId, viewport->Window ? viewport->Window->Name : "N/A"))
{
ImGuiWindowFlags flags = viewport->Flags;
@ -14522,7 +14542,7 @@ void ImGui::ShowDockingDebug()
static void NodeDockNode(ImGuiDockNode* node, const char* label)
{
ImGuiContext& g = *GImGui;
ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once);
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
bool open;
if (node->Windows.Size > 0)
open = ImGui::TreeNode((void*)(intptr_t)node->ID, "%s 0x%04X%s: %d windows (vis: '%s')", label, node->ID, node->IsVisible ? "" : " (hidden)", node->Windows.Size, node->VisibleWindow ? node->VisibleWindow->Name : "NULL");

12
imgui.h
View File

@ -506,9 +506,9 @@ namespace ImGui
IMGUI_API void TreePop(); // ~ Unindent()+PopId()
IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing()
IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode
IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop().
IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header
IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
// Widgets: Selectables
// - A selectable highlights when hovered, and can display another color when selected.
@ -804,7 +804,8 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
// [Internal]
ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline()
ImGuiInputTextFlags_Multiline = 1 << 20, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_NoMarkEdited = 1 << 21 // For internal use by functions using InputText() before reformatting data
};
// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*()
@ -1244,7 +1245,7 @@ enum ImGuiMouseCursor_
#endif
};
// Enumateration for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions
// Enumateration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions
// Represent a condition.
// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
enum ImGuiCond_
@ -1481,7 +1482,7 @@ struct ImGuiIO
float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame().
// Functions
IMGUI_API void AddInputCharacter(ImWchar c); // Queue new character input
IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string
IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually
@ -1621,6 +1622,9 @@ struct ImGuiWindowClass
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{
// OBSOLETED in 1.71 (from May 2019)
static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); }
// OBSOLETED in 1.70 (from May 2019)
static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }
// OBSOLETED in 1.69 (from Mar 2019)

View File

@ -623,13 +623,20 @@ static void ShowDemoWindowWidgets()
if (ImGui::TreeNode("Basic trees"))
{
for (int i = 0; i < 5; i++)
{
// Use SetNextItemOpen() so set the default state of a node to be open.
// We could also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
if (i == 0)
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
{
ImGui::Text("blah blah");
ImGui::SameLine();
if (ImGui::SmallButton("button")) { };
if (ImGui::SmallButton("button")) {};
ImGui::TreePop();
}
}
ImGui::TreePop();
}
@ -1588,10 +1595,11 @@ static void ShowDemoWindowWidgets()
ImGui::RadioButton("Checkbox", &item_type, 2);
ImGui::RadioButton("SliderFloat", &item_type, 3);
ImGui::RadioButton("InputText", &item_type, 4);
ImGui::RadioButton("ColorEdit4", &item_type, 5);
ImGui::RadioButton("MenuItem", &item_type, 6);
ImGui::RadioButton("TreeNode (w/ double-click)", &item_type, 7);
ImGui::RadioButton("ListBox", &item_type, 8);
ImGui::RadioButton("InputFloat3", &item_type, 5);
ImGui::RadioButton("ColorEdit4", &item_type, 6);
ImGui::RadioButton("MenuItem", &item_type, 7);
ImGui::RadioButton("TreeNode (w/ double-click)", &item_type, 8);
ImGui::RadioButton("ListBox", &item_type, 9);
ImGui::Separator();
bool ret = false;
if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
@ -1599,10 +1607,11 @@ static void ShowDemoWindowWidgets()
if (item_type == 2) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox
if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item
if (item_type == 4) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing)
if (item_type == 5) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
if (item_type == 6) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
if (item_type == 7) { ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
if (item_type == 8) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
if (item_type == 5) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
if (item_type == 6) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
if (item_type == 7) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
if (item_type == 8) { ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
if (item_type == 9) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
ImGui::BulletText(
"Return value = %d\n"
"IsItemFocused() = %d\n"
@ -1683,6 +1692,9 @@ static void ShowDemoWindowWidgets()
if (embed_all_inside_a_child_window)
ImGui::EndChild();
static char dummy_str[] = "This is a dummy field to be able to tab-out of the widgets above.";
ImGui::InputText("dummy", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
// Calling IsItemHovered() after begin returns the hovered status of the title bar.
// This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window.
// This will also work when docked into a Tab (the Tab replace the Title Bar and guarantee the same properties).

View File

@ -74,7 +74,8 @@ struct ImGuiInputTextState; // Internal state of the currently focused/e
struct ImGuiItemHoveredDataBackup; // Backup and restore IsItemHovered() internal data
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
struct ImGuiNavMoveResult; // Result of a directional navigation move query result
struct ImGuiNextWindowData; // Storage for SetNexWindow** functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
struct ImGuiNextItemData; // Storage for SetNextItem** functions
struct ImGuiPopupData; // Storage for current popup stack
struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file
struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it
@ -85,18 +86,20 @@ struct ImGuiWindowTempData; // Temporary storage for one window (that's
struct ImGuiWindowSettings; // Storage for window settings stored in .ini file (we keep one of those even if the actual window wasn't instanced during this session)
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
typedef int ImGuiDataAuthority; // -> enum ImGuiDataAuthority_ // Enum: for storing the source authority (dock node vs window) of a field
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for ButtonEx(), ButtonBehavior()
typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior()
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: for GetNavInputAmount2d()
typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for Separator() - internal
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for SliderBehavior()
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
typedef int ImGuiDataAuthority; // -> enum ImGuiDataAuthority_ // Enum: for storing the source authority (dock node vs window) of a field
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for ButtonEx(), ButtonBehavior()
typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior()
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: for GetNavInputAmount2d()
typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
typedef int ImGuiNextItemDataFlags; // -> enum ImGuiNextItemDataFlags_ // Flags: for SetNextItemXXX() functions
typedef int ImGuiNextWindowDataFlags; // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions
typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for SeparatorEx()
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for SliderBehavior()
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
//-------------------------------------------------------------------------
// STB libraries includes
@ -386,7 +389,9 @@ enum ImGuiItemStatusFlags_
ImGuiItemStatusFlags_HoveredRect = 1 << 0,
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1,
ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
ImGuiItemStatusFlags_ToggledSelection = 1 << 3 // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues.
ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues.
ImGuiItemStatusFlags_HasDeactivated = 1 << 4, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
ImGuiItemStatusFlags_Deactivated = 1 << 5 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
#ifdef IMGUI_ENABLE_TEST_ENGINE
, // [imgui-test only]
@ -587,11 +592,11 @@ struct ImGuiGroupData
ImVec2 BackupCursorMaxPos;
ImVec1 BackupIndent;
ImVec1 BackupGroupOffset;
ImVec2 BackupCurrentLineSize;
float BackupCurrentLineTextBaseOffset;
ImVec2 BackupCurrLineSize;
float BackupCurrLineTextBaseOffset;
ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdPreviousFrameIsAlive;
bool AdvanceCursor;
bool EmitItem;
};
// Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper.
@ -793,52 +798,64 @@ struct ImGuiNavMoveResult
void Clear() { ID = SelectScopeId = 0; Window = NULL; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); }
};
enum ImGuiNextWindowDataFlags_
{
ImGuiNextWindowDataFlags_None = 0,
ImGuiNextWindowDataFlags_HasPos = 1 << 0,
ImGuiNextWindowDataFlags_HasSize = 1 << 1,
ImGuiNextWindowDataFlags_HasContentSize = 1 << 2,
ImGuiNextWindowDataFlags_HasCollapsed = 1 << 3,
ImGuiNextWindowDataFlags_HasSizeConstraint = 1 << 4,
ImGuiNextWindowDataFlags_HasFocus = 1 << 5,
ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6,
ImGuiNextWindowDataFlags_HasViewport = 1 << 7,
ImGuiNextWindowDataFlags_HasDock = 1 << 8,
ImGuiNextWindowDataFlags_HasWindowClass = 1 << 9
};
// Storage for SetNexWindow** functions
struct ImGuiNextWindowData
{
ImGuiCond PosCond;
ImGuiCond SizeCond;
ImGuiCond ContentSizeCond;
ImGuiCond CollapsedCond;
ImGuiCond SizeConstraintCond;
ImGuiCond FocusCond;
ImGuiCond BgAlphaCond;
ImGuiCond ViewportCond;
ImGuiCond DockCond;
ImVec2 PosVal;
ImVec2 PosPivotVal;
ImVec2 SizeVal;
ImVec2 ContentSizeVal;
bool PosUndock;
bool CollapsedVal;
ImRect SizeConstraintRect;
ImGuiSizeCallback SizeCallback;
void* SizeCallbackUserData;
float BgAlphaVal;
ImGuiID ViewportId;
ImGuiID DockId;
ImGuiWindowClass WindowClass;
ImVec2 MenuBarOffsetMinVal; // This is not exposed publicly, so we don't clear it.
ImGuiNextWindowDataFlags Flags;
ImGuiCond PosCond;
ImGuiCond SizeCond;
ImGuiCond CollapsedCond;
ImGuiCond DockCond;
ImVec2 PosVal;
ImVec2 PosPivotVal;
ImVec2 SizeVal;
ImVec2 ContentSizeVal;
bool PosUndock;
bool CollapsedVal;
ImRect SizeConstraintRect;
ImGuiSizeCallback SizeCallback;
void* SizeCallbackUserData;
float BgAlphaVal;
ImGuiID ViewportId;
ImGuiID DockId;
ImGuiWindowClass WindowClass;
ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it.
ImGuiNextWindowData()
{
PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = ViewportCond = DockCond = 0;
PosVal = PosPivotVal = SizeVal = ImVec2(0.0f, 0.0f);
ContentSizeVal = ImVec2(0.0f, 0.0f);
PosUndock = CollapsedVal = false;
SizeConstraintRect = ImRect();
SizeCallback = NULL;
SizeCallbackUserData = NULL;
BgAlphaVal = FLT_MAX;
ViewportId = DockId = 0;
MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
}
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
};
void Clear()
{
PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = ViewportCond = DockCond = 0;
WindowClass = ImGuiWindowClass();
}
enum ImGuiNextItemDataFlags_
{
ImGuiNextItemDataFlags_None = 0,
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
ImGuiNextItemDataFlags_HasOpen = 1 << 1
};
struct ImGuiNextItemData
{
ImGuiNextItemDataFlags Flags;
float Width; // Set by SetNextItemWidth().
bool OpenVal; // Set by SetNextItemOpen() function.
ImGuiCond OpenCond;
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); }
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; }
};
//-----------------------------------------------------------------------------
@ -951,12 +968,13 @@ struct ImGuiContext
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
ImDrawListSharedData DrawListSharedData;
double Time;
int FrameCount;
int FrameCountEnded;
int FrameCountPlatformEnded;
int FrameCountRendered;
// Windows state
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
ImVector<ImGuiWindow*> WindowsFocusOrder; // Windows, sorted in focus order, back to front
ImVector<ImGuiWindow*> WindowsSortBuffer;
@ -967,39 +985,45 @@ struct ImGuiContext
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
// Item/widgets state and tracking information
ImGuiID HoveredId; // Hovered widget
bool HoveredIdAllowOverlap;
ImGuiID HoveredIdPreviousFrame;
float HoveredIdTimer; // Measure contiguous hovering time
float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdPreviousFrame;
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
float ActiveIdTimer;
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
bool ActiveIdHasBeenPressed; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
bool ActiveIdHasBeenEdited; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdPreviousFrameIsAlive;
bool ActiveIdPreviousFrameHasBeenEdited;
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdHasBeenEditedThisFrame;
int ActiveIdAllowNavDirFlags; // Active widget allows using directional navigation (e.g. can activate a button and move away from it)
int ActiveIdBlockNavInputFlags;
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow;
ImGuiWindow* ActiveIdPreviousFrameWindow;
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
ImGuiID ActiveIdPreviousFrame;
bool ActiveIdPreviousFrameIsAlive;
bool ActiveIdPreviousFrameHasBeenEditedBefore;
ImGuiWindow* ActiveIdPreviousFrameWindow;
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
ImVec2 LastValidMousePos;
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
// Next window/item data
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions
// Shared stacks
ImVector<ImGuiColorMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions
ImGuiCond NextTreeNodeOpenCond;
// Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData.
@ -1087,6 +1111,7 @@ struct ImGuiContext
ImVector<ImGuiTabBarSortItem> TabSortByWidthBuffer;
// Widget state
ImVec2 LastValidMousePos;
ImGuiInputTextState InputTextState;
ImFont InputTextPasswordFont;
ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
@ -1148,40 +1173,42 @@ struct ImGuiContext
FontSize = FontBaseSize = 0.0f;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f;
FrameCount = 0;
FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
WindowsActiveCount = 0;
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
MovingWindow = NULL;
HoveredId = 0;
HoveredIdAllowOverlap = false;
HoveredIdPreviousFrame = 0;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ActiveId = 0;
ActiveIdPreviousFrame = 0;
ActiveIdIsAlive = 0;
ActiveIdTimer = 0.0f;
ActiveIdIsJustActivated = false;
ActiveIdAllowOverlap = false;
ActiveIdHasBeenPressed = false;
ActiveIdHasBeenEdited = false;
ActiveIdPreviousFrameIsAlive = false;
ActiveIdPreviousFrameHasBeenEdited = false;
ActiveIdHasBeenPressedBefore = false;
ActiveIdHasBeenEditedBefore = false;
ActiveIdHasBeenEditedThisFrame = false;
ActiveIdAllowNavDirFlags = 0x00;
ActiveIdBlockNavInputFlags = 0x00;
ActiveIdClickOffset = ImVec2(-1,-1);
ActiveIdWindow = ActiveIdPreviousFrameWindow = NULL;
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None;
ActiveIdPreviousFrame = 0;
ActiveIdPreviousFrameIsAlive = false;
ActiveIdPreviousFrameHasBeenEditedBefore = false;
ActiveIdPreviousFrameWindow = NULL;
LastActiveId = 0;
LastActiveIdTimer = 0.0f;
LastValidMousePos = ImVec2(0.0f, 0.0f);
MovingWindow = NULL;
NextTreeNodeOpenVal = false;
NextTreeNodeOpenCond = 0;
CurrentViewport = NULL;
MouseViewport = MouseLastHoveredViewport = NULL;
@ -1234,6 +1261,7 @@ struct ImGuiContext
CurrentTabBar = NULL;
LastValidMousePos = ImVec2(0.0f, 0.0f);
TempInputTextId = 0;
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
DragCurrentAccumDirty = false;
@ -1280,9 +1308,9 @@ struct IMGUI_API ImGuiWindowTempData
ImVec2 CursorPosPrevLine;
ImVec2 CursorStartPos; // Initial position in client area with padding
ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Turned into window->SizeContents at the beginning of next frame
ImVec2 CurrentLineSize;
float CurrentLineTextBaseOffset;
ImVec2 CurrLineSize;
ImVec2 PrevLineSize;
float CurrLineTextBaseOffset;
float PrevLineTextBaseOffset;
int TreeDepth;
ImU32 TreeStoreMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary.
@ -1308,7 +1336,6 @@ struct IMGUI_API ImGuiWindowTempData
// 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]
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
float NextItemWidth;
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
ImVector<ImGuiItemFlags>ItemFlagsStack;
ImVector<float> ItemWidthStack;
@ -1324,8 +1351,8 @@ struct IMGUI_API ImGuiWindowTempData
ImGuiWindowTempData()
{
CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);
CurrentLineSize = PrevLineSize = ImVec2(0.0f, 0.0f);
CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
CurrLineSize = PrevLineSize = ImVec2(0.0f, 0.0f);
CurrLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
TreeDepth = 0;
TreeStoreMayJumpToParentOnPop = 0x00;
LastItemId = 0;
@ -1344,7 +1371,6 @@ struct IMGUI_API ImGuiWindowTempData
ItemFlags = ImGuiItemFlags_Default_;
ItemWidth = 0.0f;
NextItemWidth = +FLT_MAX;
TextWrapPos = -1.0f;
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
@ -1636,7 +1662,6 @@ namespace ImGui
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
IMGUI_API float GetNextItemWidth();
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full);
@ -1783,7 +1808,7 @@ namespace ImGui
IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb);
IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f);
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging
IMGUI_API void TreePushOverrideID(ImGuiID id);
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.

View File

@ -139,7 +139,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
if (text_end == NULL)
text_end = text + strlen(text); // FIXME-OPT
const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
const float wrap_pos_x = window->DC.TextWrapPos;
const bool wrap_enabled = (wrap_pos_x >= 0.0f);
if (text_end - text > 2000 && !wrap_enabled)
@ -320,7 +320,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const float w = GetNextItemWidth();
const float w = CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
@ -358,8 +358,8 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
const char* text_begin = g.TempBuffer;
const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
const float text_base_offset_y = ImMax(0.0f, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding
ItemSize(bb);
if (!ItemAdd(bb, 0))
@ -564,7 +564,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if (g.ActiveId == id)
{
if (pressed)
g.ActiveIdHasBeenPressed = true;
g.ActiveIdHasBeenPressedBefore = true;
if (g.ActiveIdSource == ImGuiInputSource_Mouse)
{
if (g.ActiveIdIsJustActivated)
@ -612,8 +612,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
const ImVec2 label_size = CalcTextSize(label, NULL, true);
ImVec2 pos = window->DC.CursorPos;
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y;
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
const ImRect bb(pos, pos + size);
@ -1122,7 +1122,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
const ImGuiStyle& style = g.Style;
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, GetNextItemWidth(), g.FontSize + style.FramePadding.y*2.0f);
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f);
ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, 0))
@ -1156,7 +1156,7 @@ void ImGui::Bullet()
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
ItemSize(bb);
if (!ItemAdd(bb, 0))
@ -1210,7 +1210,7 @@ void ImGui::NewLine()
ImGuiContext& g = *GImGui;
const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
window->DC.LayoutType = ImGuiLayoutType_Vertical;
if (window->DC.CurrentLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
ItemSize(ImVec2(0,0));
else
ItemSize(ImVec2(0.0f, g.FontSize));
@ -1224,8 +1224,8 @@ void ImGui::AlignTextToFramePadding()
return;
ImGuiContext& g = *GImGui;
window->DC.CurrentLineSize.y = ImMax(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y);
}
// Horizontal/vertical separating line
@ -1244,7 +1244,7 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
{
// Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
float y1 = window->DC.CursorPos.y;
float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y;
float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y;
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2));
ItemSize(ImVec2(thickness_layout, 0.0f));
if (!ItemAdd(bb, 0))
@ -1381,8 +1381,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
{
// Always consume the SetNextWindowSizeConstraint() call in our early return paths
ImGuiContext& g = *GImGui;
ImGuiCond backup_next_window_size_constraint = g.NextWindowData.SizeConstraintCond;
g.NextWindowData.SizeConstraintCond = 0;
bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0;
g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
@ -1395,7 +1395,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float expected_w = GetNextItemWidth();
const float expected_w = CalcItemWidth();
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;
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));
@ -1434,9 +1434,9 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
if (!popup_open)
return false;
if (backup_next_window_size_constraint)
if (has_window_size_constraint)
{
g.NextWindowData.SizeConstraintCond = backup_next_window_size_constraint;
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
}
else
@ -1526,7 +1526,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
items_getter(data, *current_item, &preview_value);
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond)
if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint))
SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
@ -2022,8 +2022,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const float w = GetNextItemWidth();
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));
@ -2095,7 +2094,7 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int
bool value_changed = false;
BeginGroup();
PushID(label);
PushMultiItemsWidths(components, GetNextItemWidth());
PushMultiItemsWidths(components, CalcItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++)
{
@ -2142,7 +2141,7 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu
ImGuiContext& g = *GImGui;
PushID(label);
BeginGroup();
PushMultiItemsWidths(2, GetNextItemWidth());
PushMultiItemsWidths(2, CalcItemWidth());
bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power);
PopItemWidth();
@ -2187,7 +2186,7 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_
ImGuiContext& g = *GImGui;
PushID(label);
BeginGroup();
PushMultiItemsWidths(2, GetNextItemWidth());
PushMultiItemsWidths(2, CalcItemWidth());
bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format);
PopItemWidth();
@ -2465,7 +2464,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const float w = GetNextItemWidth();
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));
@ -2543,7 +2542,7 @@ bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, i
bool value_changed = false;
BeginGroup();
PushID(label);
PushMultiItemsWidths(components, GetNextItemWidth());
PushMultiItemsWidths(components, CalcItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++)
{
@ -2792,7 +2791,8 @@ bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label,
ImStrTrimBlanks(data_buf);
g.CurrentWindow->DC.CursorPos = bb.Min;
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited;
flags |= ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
bool value_changed = InputTextEx(label, NULL, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
if (init)
{
@ -2801,7 +2801,11 @@ bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label,
g.TempInputTextId = g.ActiveId;
}
if (value_changed)
return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL);
{
value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL);
if (value_changed)
MarkItemEdited(id);
}
return false;
}
@ -2824,6 +2828,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
flags |= ImGuiInputTextFlags_CharsDecimal;
flags |= ImGuiInputTextFlags_AutoSelectAll;
flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselve by comparing the actual data rather than the string.
if (step != NULL)
{
@ -2831,7 +2836,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
PushID(label);
SetNextItemWidth(ImMax(1.0f, GetNextItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format);
@ -2865,6 +2870,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format);
}
if (value_changed)
MarkItemEdited(window->DC.LastItemId);
return value_changed;
}
@ -2879,7 +2886,7 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in
bool value_changed = false;
BeginGroup();
PushID(label);
PushMultiItemsWidths(components, GetNextItemWidth());
PushMultiItemsWidths(components, CalcItemWidth());
size_t type_size = GDataTypeInfo[data_type].Size;
for (int i = 0; i < components; i++)
{
@ -3329,7 +3336,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
BeginGroup();
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
ImVec2 size = CalcItemSize(size_arg, GetNextItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
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));
@ -4047,7 +4054,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
if (value_changed)
if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
MarkItemEdited(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
@ -4090,8 +4097,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
const ImGuiStyle& style = g.Style;
const float square_sz = GetFrameHeight();
const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
const float w_items_all = GetNextItemWidth() - w_extra;
const float w_items_all = CalcItemWidth() - w_extra;
const char* label_display_end = FindRenderedTextEnd(label);
g.NextItemData.ClearFlags();
BeginGroup();
PushID(label);
@ -4371,6 +4379,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImGuiStyle& style = g.Style;
ImGuiIO& io = g.IO;
const float width = CalcItemWidth();
g.NextItemData.ClearFlags();
PushID(label);
BeginGroup();
@ -4397,7 +4408,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 picker_pos = window->DC.CursorPos;
float square_sz = GetFrameHeight();
float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
float sv_picker_size = ImMax(bars_width * 1, GetNextItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);
@ -4940,7 +4951,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
// - TreePop()
// - TreeAdvanceToLabelPos()
// - GetTreeNodeToLabelSpacing()
// - SetNextTreeNodeOpen()
// - SetNextItemOpen()
// - CollapsingHeader()
//-------------------------------------------------------------------------
@ -5034,17 +5045,17 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
if (flags & ImGuiTreeNodeFlags_Leaf)
return true;
// We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions)
// We only write to the tree storage if the user clicks (or explicitly use the SetNextItemOpen function)
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStorage* storage = window->DC.StateStorage;
bool is_open;
if (g.NextTreeNodeOpenCond != 0)
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
{
if (g.NextTreeNodeOpenCond & ImGuiCond_Always)
if (g.NextItemData.OpenCond & ImGuiCond_Always)
{
is_open = g.NextTreeNodeOpenVal;
is_open = g.NextItemData.OpenVal;
storage->SetInt(id, is_open);
}
else
@ -5053,7 +5064,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
const int stored_value = storage->GetInt(id, -1);
if (stored_value == -1)
{
is_open = g.NextTreeNodeOpenVal;
is_open = g.NextItemData.OpenVal;
storage->SetInt(id, is_open);
}
else
@ -5061,7 +5072,6 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
is_open = stored_value != 0;
}
}
g.NextTreeNodeOpenCond = 0;
}
else
{
@ -5092,8 +5102,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const ImVec2 label_size = CalcTextSize(label, label_end, false);
// We vertically grow up to current line height up the typical widget height.
const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
const float frame_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
const float text_base_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(GetWorkRectMax().x, window->DC.CursorPos.y + frame_height));
if (display_frame)
{
@ -5290,13 +5300,15 @@ float ImGui::GetTreeNodeToLabelSpacing()
return g.FontSize + (g.Style.FramePadding.x * 2.0f);
}
void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond)
// Set next TreeNode/CollapsingHeader open state.
void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems)
return;
g.NextTreeNodeOpenVal = is_open;
g.NextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen;
g.NextItemData.OpenVal = is_open;
g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always;
}
// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).
@ -5360,7 +5372,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
ImVec2 label_size = CalcTextSize(label, NULL, true);
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
ImVec2 pos = window->DC.CursorPos;
pos.y += window->DC.CurrentLineTextBaseOffset;
pos.y += window->DC.CurrLineTextBaseOffset;
ImRect bb_inner(pos, pos + size);
ItemSize(size);
@ -5486,20 +5498,22 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
// Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an non-visible label e.g. "##empty"
bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiStyle& style = GetStyle();
const ImGuiStyle& style = g.Style;
const ImGuiID id = GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
// Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
ImVec2 size = CalcItemSize(size_arg, GetNextItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y);
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y);
ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy.
g.NextItemData.ClearFlags();
if (!IsRectVisible(bb.Min, bb.Max))
{
@ -5612,7 +5626,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
const ImVec2 label_size = CalcTextSize(label, NULL, true);
if (frame_size.x == 0.0f)
frame_size.x = GetNextItemWidth();
frame_size.x = CalcItemWidth();
if (frame_size.y == 0.0f)
frame_size.y = label_size.y + (style.FramePadding.y * 2);
@ -5939,7 +5953,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().AdvanceCursor = false;
window->DC.GroupStack.back().EmitItem = false;
EndGroup(); // Restore position on layer 0
window->DC.LayoutType = ImGuiLayoutType_Vertical;
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;

View File

@ -120,6 +120,7 @@ struct FreeTypeTest
WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting);
WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold);
WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique);
WantRebuild |= ImGui::CheckboxFlags("Monochrome", &FontsFlags, ImGuiFreeType::Monochrome);
}
ImGui::End();
}

View File

@ -12,6 +12,7 @@
// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX.
// - v0.60: (2019/01/10) re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
// - v0.61: (2019/01/15) added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
// - v0.62: (2019/02/09) added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
// Gamma Correct Blending:
// FreeType assumes blending in linear space rather than gamma space.
@ -109,6 +110,7 @@ namespace
FT_Face Face;
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
FT_Int32 LoadFlags;
FT_Render_Mode RenderMode;
};
// From SDL_ttf: Handy routines for converting from fixed point
@ -142,6 +144,11 @@ namespace
else
LoadFlags |= FT_LOAD_TARGET_NORMAL;
if (UserFlags & ImGuiFreeType::Monochrome)
RenderMode = FT_RENDER_MODE_MONO;
else
RenderMode = FT_RENDER_MODE_NORMAL;
return true;
}
@ -208,7 +215,7 @@ namespace
const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info)
{
FT_GlyphSlot slot = Face->glyph;
FT_Error error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
FT_Error error = FT_Render_Glyph(slot, RenderMode);
if (error != 0)
return NULL;
@ -230,16 +237,42 @@ namespace
const uint8_t* src = ft_bitmap->buffer;
const uint32_t src_pitch = ft_bitmap->pitch;
if (multiply_table == NULL)
switch (ft_bitmap->pixel_mode)
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
memcpy(dst, src, w);
}
else
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
for (uint32_t x = 0; x < w; x++)
dst[x] = multiply_table[src[x]];
case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel.
{
if (multiply_table == NULL)
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
memcpy(dst, src, w);
}
else
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
for (uint32_t x = 0; x < w; x++)
dst[x] = multiply_table[src[x]];
}
break;
}
case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
{
uint8_t color0 = multiply_table ? multiply_table[0] : 0;
uint8_t color1 = multiply_table ? multiply_table[255] : 255;
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
{
uint8_t bits = 0;
const uint8_t* bits_ptr = src;
for (uint32_t x = 0; x < w; x++, bits <<= 1)
{
if ((x & 7) == 0)
bits = *bits_ptr++;
dst[x] = (bits & 0x80) ? color1 : color0;
}
}
break;
}
default:
IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
}
}
}

View File

@ -24,7 +24,8 @@ namespace ImGuiFreeType
LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
Bold = 1 << 5, // Styling: Should we artificially embolden the font?
Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style?
Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
Monochrome = 1 << 7 // Disable anti-aliasing. Combine this with MonoHinting for best results!
};
IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);