From 47e875314baa100f1632cf46fbf469d1efa94a9c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 May 2015 11:32:39 +0100 Subject: [PATCH 01/34] Plot: overlay label clipped within frame when bigger than frame --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 6825a91c7..1ce3a88eb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5951,7 +5951,7 @@ static void Plot(ImGuiPlotType plot_type, const char* label, float (*values_gett // Text overlay if (overlay_text) - RenderText(ImVec2(inner_bb.GetCenter().x - ImGui::CalcTextSize(overlay_text, NULL, true).x*0.5f, frame_bb.Min.y + style.FramePadding.y), overlay_text); + RenderTextClipped(ImVec2(ImMax(inner_bb.Min.x, inner_bb.GetCenter().x - ImGui::CalcTextSize(overlay_text, NULL, true).x*0.5f), frame_bb.Min.y + style.FramePadding.y), overlay_text, NULL, NULL, frame_bb.Max); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); } From a3a10d4a3c17ae48c6dc32919a25d3d419ba7a6c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 May 2015 12:17:53 +0100 Subject: [PATCH 02/34] Popup have borders by default #197 attenuated border alpha in default theme --- imgui.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1ce3a88eb..e951d6116 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -575,7 +575,7 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); + Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); @@ -2877,8 +2877,9 @@ void ImGui::BeginPopup(bool* p_opened) IM_ASSERT(p_opened != NULL); // Must provide a bool at the moment ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGuiWindowFlags flags = ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Popup", p_opened, flags); + ImGuiWindowFlags flags = ImGuiWindowFlags_Popup|ImGuiWindowFlags_ShowBorders|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; + float alpha = 1.0f; + ImGui::Begin("##Popup", p_opened, ImVec2(0.0f, 0.0f), alpha, flags); } void ImGui::EndPopup() From 0ca7926b94f8cd49ae3899109a2102032b9a6b62 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 May 2015 13:04:43 +0100 Subject: [PATCH 03/34] Popup auto-border doesn't spread to its childs #197 --- imgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index e951d6116..c7f14579f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2874,12 +2874,16 @@ void ImGui::EndTooltip() void ImGui::BeginPopup(bool* p_opened) { + ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(p_opened != NULL); // Must provide a bool at the moment ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGuiWindowFlags flags = ImGuiWindowFlags_Popup|ImGuiWindowFlags_ShowBorders|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; float alpha = 1.0f; ImGui::Begin("##Popup", p_opened, ImVec2(0.0f, 0.0f), alpha, flags); + + if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) + GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; } void ImGui::EndPopup() @@ -2922,7 +2926,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, bool ret = ImGui::Begin(title, NULL, size, alpha, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; + GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; return ret; } From b1b23d6ca9b960955fdb234ccc29cbf2db0f813d Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 May 2015 13:52:53 +0100 Subject: [PATCH 04/34] Autofit cancel out one worth of vertical spacing for correct symmetry (group and tooltip already do that) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index c7f14579f..3aef30b90 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3239,6 +3239,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding)); if (size_auto_fit.y < window->SizeContents.y + style.AutoFitPadding.y) size_auto_fit.x += style.ScrollbarWidth; + size_auto_fit.y -= style.ItemSpacing.y; } // Handle automatic resize From e7ffcea33d7d8b34f4208b79e7b149cd583acc75 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 May 2015 14:26:47 +0100 Subject: [PATCH 05/34] Removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). --- imgui.cpp | 14 +++++++------- imgui.h | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3aef30b90..006aaf5d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -136,6 +136,7 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. + - 2015/05/03 (1.39) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function (will obsolete). - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. @@ -563,7 +564,6 @@ ImGuiStyle::ImGuiStyle() ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - AutoFitPadding = ImVec2(8,8); // Extra space after auto-fit (double-clicking on resize grip) WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns @@ -2954,9 +2954,9 @@ void ImGui::EndChild() ImGuiState& g = *GImGui; ImVec2 sz = ImGui::GetWindowSize(); if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX) - sz.x = ImMax(g.Style.WindowMinSize.x, sz.x - g.Style.AutoFitPadding.x); + sz.x = ImMax(g.Style.WindowMinSize.x, sz.x - g.Style.WindowPadding.x); if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) - sz.y = ImMax(g.Style.WindowMinSize.y, sz.y - g.Style.AutoFitPadding.y); + sz.y = ImMax(g.Style.WindowMinSize.y, sz.y - g.Style.WindowPadding.y); ImGui::End(); @@ -3236,8 +3236,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } else { - size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding)); - if (size_auto_fit.y < window->SizeContents.y + style.AutoFitPadding.y) + size_auto_fit = ImClamp(window->SizeContents + style.WindowPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.WindowPadding)); + if (size_auto_fit.y < window->SizeContents.y + style.WindowPadding.y) size_auto_fit.x += style.ScrollbarWidth; size_auto_fit.y -= style.ItemSpacing.y; } @@ -7059,12 +7059,12 @@ bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg) const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const float w = ImMax(label_size.x, window->Pos.x + ImGui::GetContentRegionMax().x - style.AutoFitPadding.x - window->DC.CursorPos.x); + const float w = ImMax(label_size.x, window->Pos.x + ImGui::GetContentRegionMax().x - style.WindowPadding.x - window->DC.CursorPos.x); const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : w, size_arg.y != 0.0f ? size_arg.y : label_size.y); ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(bb); if (size_arg.x == 0.0f) - bb.Max.x += style.AutoFitPadding.x; + bb.Max.x += style.WindowPadding.x; // Selectables are meant to be tightly packed together. So for both rendering and collision we extend to compensate for spacing. ImRect bb_with_spacing = bb; diff --git a/imgui.h b/imgui.h index 2357dd402..567fb0da6 100644 --- a/imgui.h +++ b/imgui.h @@ -598,7 +598,6 @@ struct ImGuiStyle ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - ImVec2 AutoFitPadding; // Extra space after auto-fit (double-clicking on resize grip) float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin() float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns From 25d8c1af91225d61205e593d1e3e3dfcba6b220e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 10:48:05 +0100 Subject: [PATCH 06/34] Removed inline marker #210 --- imgui.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 006aaf5d3..662001e78 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7800,8 +7800,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) } } - -inline void ImGui::Indent() +void ImGui::Indent() { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -7809,7 +7808,7 @@ inline void ImGui::Indent() window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; } -inline void ImGui::Unindent() +void ImGui::Unindent() { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); From fbbe7fee531a8b36522a77fe174a80d2e59c47ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 11:24:51 +0100 Subject: [PATCH 07/34] Fix "Debug" window stealing focus/popup #208 #209 @thevaber --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 662001e78..b86405f1a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3160,6 +3160,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // When reusing window again multiple times a frame, just append content (don't need to setup again) const int current_frame = ImGui::GetFrameCount(); const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame); + const bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); if (first_begin_of_the_frame) { window->Active = true; @@ -3179,7 +3180,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ if (first_begin_of_the_frame) { // New windows appears in front - if (!window->WasActive) + if (!window_was_visible) { window->AutoPosLastDirection = -1; From 13c3f11c661e27447d5674c5a7ba164642947028 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 11:36:16 +0100 Subject: [PATCH 08/34] Comments (#209) --- imgui.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b86405f1a..2a2b06165 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2183,24 +2183,24 @@ static void PopClipRect() void ImGui::Render() { ImGuiState& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() const bool first_render_of_the_frame = (g.FrameCountRendered != g.FrameCount); g.FrameCountRendered = g.FrameCount; if (first_render_of_the_frame) { - // Hide implicit window if it hasn't been used + // Hide implicit "Debug" window if it hasn't been used IM_ASSERT(g.CurrentWindowStack.size() == 1); // Mismatched Begin/End if (g.CurrentWindow && !g.CurrentWindow->Accessed) g.CurrentWindow->Active = false; ImGui::End(); + // Click to focus window and start moving (after we're done with all our widgets) if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) { if (g.HoveredRootWindow != NULL) { - // Select window for move/focus when we're done with all our widgets (we use the root window ID here) IM_ASSERT(g.MovedWindow == NULL); g.MovedWindow = g.HoveredWindow; SetActiveId(g.HoveredRootWindow->MoveID); @@ -2227,19 +2227,18 @@ void ImGui::Render() IM_ASSERT(g.Windows.size() == g.WindowsSortBuffer.size()); // we done something wrong g.Windows.swap(g.WindowsSortBuffer); - // Clear data for next frame + // Clear Input data for next frame g.IO.MouseWheel = 0.0f; memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); } // Skip render altogether if alpha is 0.0 - // Note that vertex buffers have been created, so it is best practice that you don't call Begin/End in the first place. + // Note that vertex buffers have been created, so it is best practice that you don't create windows in the first place, or respond to Begin() returning false if (g.Style.Alpha > 0.0f) { // Render tooltip if (g.Tooltip[0]) { - // Use a dummy window to render the tooltip ImGui::BeginTooltip(); ImGui::TextUnformatted(g.Tooltip); ImGui::EndTooltip(); @@ -3160,7 +3159,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // When reusing window again multiple times a frame, just append content (don't need to setup again) const int current_frame = ImGui::GetFrameCount(); const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame); - const bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); + const bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (first_begin_of_the_frame) { window->Active = true; From 85b8967291c321fe2471fdcc21dbda6a658ae775 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 17:06:07 +0100 Subject: [PATCH 09/34] Added RenderCheckMark() helper following the font size Pretty ugly, not sure what's the right way to solve that automatically, better shown as an "icon" so it doesn't have to necessarily look like the font. --- imgui.cpp | 21 ++++++++++++++++++++- imgui.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2a2b06165..a0acc9438 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -501,6 +501,7 @@ static void RenderTextWrapped(ImVec2 pos, const char* text, const char* static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max); static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false); +static void RenderCheckMark(ImVec2 pos); static void SetFont(ImFont* font); static bool ItemAdd(const ImRect& bb, const ImGuiID* id); @@ -2528,6 +2529,22 @@ static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool window->DrawList->AddTriangleFilled(a, b, c, window->Color(ImGuiCol_Text)); } +static void RenderCheckMark(ImVec2 pos) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + float ax = (float)(int)(g.FontSize * 0.307f + 0.5f); // Spacing + float rem_third = (float)(int)((g.FontSize - ax) / 3.0f); + float bx = ax + rem_third; + float cx = ax + rem_third * 3.0f; + float by = (float)(int)(g.Font->BaseLine * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y); + float ay = by - rem_third; + float cy = by - rem_third * 2.0f; + window->DrawList->AddLine(ImVec2(pos.x + ax, pos.y + ay), ImVec2(pos.x + bx, pos.y + by), window->Color(ImGuiCol_Text)); + window->DrawList->AddLine(ImVec2(pos.x + bx, pos.y + by), ImVec2(pos.x + cx, pos.y + cy), window->Color(ImGuiCol_Text)); +} + // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. // CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize) ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) @@ -3003,7 +3020,7 @@ static ImVec2 FindBestWindowPos(const ImVec2& mouse_pos, const ImVec2& size, int } // Fallback - *last_dir = -1; + *last_dir = -1; return mouse_pos + ImVec2(2,2); } @@ -8595,6 +8612,7 @@ bool ImFontAtlas::Build() const float font_scale = stbtt_ScaleForPixelHeight(&data.FontInfo, data.SizePixels); int font_ascent, font_descent, font_line_gap; stbtt_GetFontVMetrics(&data.FontInfo, &font_ascent, &font_descent, &font_line_gap); + data.OutFont->BaseLine = (font_ascent * font_scale); const float uv_scale_x = 1.0f / TexWidth; const float uv_scale_y = 1.0f / TexHeight; @@ -8754,6 +8772,7 @@ void ImFont::Clear() { FontSize = 0.0f; DisplayOffset = ImVec2(-0.5f, 0.5f); + BaseLine = 0.0f; ContainerAtlas = NULL; Glyphs.clear(); FallbackGlyph = NULL; diff --git a/imgui.h b/imgui.h index 567fb0da6..53e6f4630 100644 --- a/imgui.h +++ b/imgui.h @@ -1018,6 +1018,7 @@ struct ImFont signed short XOffset, YOffset; float U0, V0, U1, V1; // Texture coordinates }; + float BaseLine; // Distance from top to bottom of e.g. 'A' [0..FontSize] ImFontAtlas* ContainerAtlas; // What we has been loaded into ImVector Glyphs; const Glyph* FallbackGlyph; // == FindGlyph(FontFallbackChar) From c36172ebef5aeb72e6eee8946dc9703edc953468 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 17:11:32 +0100 Subject: [PATCH 10/34] Tweak RenderCheckMark() --- imgui.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a0acc9438..1b8493b53 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -501,7 +501,7 @@ static void RenderTextWrapped(ImVec2 pos, const char* text, const char* static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max); static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false); -static void RenderCheckMark(ImVec2 pos); +static void RenderCheckMark(ImVec2 pos, ImU32 col); static void SetFont(ImFont* font); static bool ItemAdd(const ImRect& bb, const ImGuiID* id); @@ -2529,20 +2529,23 @@ static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool window->DrawList->AddTriangleFilled(a, b, c, window->Color(ImGuiCol_Text)); } -static void RenderCheckMark(ImVec2 pos) +static void RenderCheckMark(ImVec2 pos, ImU32 col) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - float ax = (float)(int)(g.FontSize * 0.307f + 0.5f); // Spacing - float rem_third = (float)(int)((g.FontSize - ax) / 3.0f); - float bx = ax + rem_third; - float cx = ax + rem_third * 3.0f; - float by = (float)(int)(g.Font->BaseLine * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y); - float ay = by - rem_third; - float cy = by - rem_third * 2.0f; - window->DrawList->AddLine(ImVec2(pos.x + ax, pos.y + ay), ImVec2(pos.x + bx, pos.y + by), window->Color(ImGuiCol_Text)); - window->DrawList->AddLine(ImVec2(pos.x + bx, pos.y + by), ImVec2(pos.x + cx, pos.y + cy), window->Color(ImGuiCol_Text)); + ImVec2 a, b, c; + float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f); + float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f); + a.x = pos.x + start_x; + b.x = a.x + rem_third; + c.x = a.x + rem_third * 3.0f; + b.y = pos.y + (float)(int)(g.Font->BaseLine * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y); + a.y = b.y - rem_third; + c.y = b.y - rem_third * 2.0f; + + window->DrawList->AddLine(a, b, col); + window->DrawList->AddLine(b, c, col); } // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. From f46557d2d65c15933691381c843f117e6c97da9a Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 17:21:48 +0100 Subject: [PATCH 11/34] MenuItem() draft for popups, with Selected option (wip #126) --- imgui.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++----------- imgui.h | 5 ++++ 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1b8493b53..d58be6820 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7220,6 +7220,41 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v return value_changed; } +bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected) +{ + (void)shortcut; // FIXME-MENU: Shortcut are not supported yet. Argument is reserved. + + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImVec2 pos = ImGui::GetCursorScreenPos(); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const float symbol_spacing = (float)(int)(g.FontSize * 1.50f + 0.5f); + const float w = ImMax(label_size.x + symbol_spacing, window->Pos.x + ImGui::GetContentRegionMax().x - window->DC.CursorPos.x); // Feedback to next frame + bool ret = ImGui::Selectable(label, false, ImVec2(w, 0.0f)); + + if (selected) + { + pos.x = window->Pos.x + ImGui::GetContentRegionMax().x - g.FontSize; + RenderCheckMark(pos, window->Color(ImGuiCol_Text)); + } + + return ret; +} + +bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected) +{ + if (ImGui::MenuItem(label, shortcut, p_selected ? *p_selected : false)) + { + if (p_selected) + *p_selected = !*p_selected; + return true; + } + return false; +} + // A little colored square. Return true when clicked. bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_border) { @@ -10007,30 +10042,48 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::TreePop(); } - if (ImGui::TreeNode("Popup")) + if (ImGui::TreeNode("Popup, Menus")) { - static bool popup_open = false; static int selected_fish = -1; - const char* fishes[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; - if (ImGui::Button("Select..")) - popup_open = true; - ImGui::SameLine(); - ImGui::Text(selected_fish == -1 ? "" : fishes[selected_fish]); - if (popup_open) + const char* names[] = { "BreamXYZA", "Haddk", "Mackerel", "Pollock", "Tilefish" }; + static bool toggles[] = { true, false, false, false, false }; + { - ImGui::BeginPopup(&popup_open); - ImGui::Text("Aquarium"); - ImGui::Separator(); - for (int i = 0; i < IM_ARRAYSIZE(fishes); i++) + static bool popup_open = false; + if (ImGui::Button("Select..")) + popup_open = true; + ImGui::SameLine(); + ImGui::Text(selected_fish == -1 ? "" : names[selected_fish]); + if (popup_open) { - if (ImGui::Selectable(fishes[i], false)) + ImGui::BeginPopup(&popup_open); + ImGui::Text("Aquarium"); + ImGui::Separator(); + for (int i = 0; i < IM_ARRAYSIZE(names); i++) { - selected_fish = i; - popup_open = false; + if (ImGui::Selectable(names[i])) + { + selected_fish = i; + popup_open = false; + } } + ImGui::EndPopup(); } - ImGui::EndPopup(); } + { + static bool popup_open = false; + if (ImGui::Button("Toggle..")) + popup_open = true; + if (popup_open) + { + ImGui::BeginPopup(&popup_open); + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + if (ImGui::MenuItem(names[i], "", &toggles[i])) + popup_open = false; + ImGui::EndPopup(); + } + } + ImGui::TreePop(); } diff --git a/imgui.h b/imgui.h index 53e6f4630..4f029fe0b 100644 --- a/imgui.h +++ b/imgui.h @@ -357,6 +357,11 @@ namespace ImGui IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " IMGUI_API void ListBoxFooter(); // terminate the scrolling region + // Widgets: Menus + // FIXME-WIP: v1.39 in development + IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = NULL); // bool enabled = true + IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected); // bool enabled = true + // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare your own within the ImGui namespace!) IMGUI_API void Value(const char* prefix, bool b); IMGUI_API void Value(const char* prefix, int v); From dd2a578012945473312a266bbdd6e22dd21ce0f6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 18:39:23 +0100 Subject: [PATCH 12/34] Added ImGuiSetCond_Appearing to test the hidden->visible transition. --- imgui.cpp | 18 +++++++++++------- imgui.h | 3 ++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d58be6820..7e584d88e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1631,7 +1631,7 @@ ImGuiWindow::ImGuiWindow(const char* name) AutoFitOnlyGrows = false; AutoPosLastDirection = -1; HiddenFrames = 0; - SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver; + SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; LastFrameDrawn = -1; ItemWidthDefault = 0.0f; @@ -3129,6 +3129,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } window->Flags = (ImGuiWindowFlags)flags; + const int current_frame = ImGui::GetFrameCount(); + const bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + // Add to stack g.CurrentWindowStack.push_back(window); SetCurrentWindow(window); @@ -3138,18 +3141,21 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ if (g.SetNextWindowPosCond) { const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this anymore :( need to look into that. + if (!window_was_visible) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; + window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond); window->DC.CursorPos = backup_cursor_pos; - window_pos_set_by_api = true; g.SetNextWindowPosCond = 0; } if (g.SetNextWindowSizeCond) { + if (!window_was_visible) window->SetWindowSizeAllowFlags |= ImGuiSetCond_Appearing; ImGui::SetWindowSize(g.SetNextWindowSizeVal, g.SetNextWindowSizeCond); g.SetNextWindowSizeCond = 0; } if (g.SetNextWindowCollapsedCond) { + if (!window_was_visible) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing; ImGui::SetWindowCollapsed(g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); g.SetNextWindowCollapsedCond = 0; } @@ -3177,9 +3183,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ bg_alpha = style.WindowFillAlphaDefault; // When reusing window again multiple times a frame, just append content (don't need to setup again) - const int current_frame = ImGui::GetFrameCount(); const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame); - const bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (first_begin_of_the_frame) { window->Active = true; @@ -3967,7 +3971,7 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond co // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowPosAllowFlags & cond) == 0) return; - window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver); + window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); // Set const ImVec2 old_pos = window->Pos; @@ -4001,7 +4005,7 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) return; - window->SetWindowSizeAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver); + window->SetWindowSizeAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); // Set if (ImLengthSqr(size) > 0.00001f) @@ -4035,7 +4039,7 @@ static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiSetCond // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) return; - window->SetWindowCollapsedAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver); + window->SetWindowCollapsedAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); // Set window->Collapsed = collapsed; diff --git a/imgui.h b/imgui.h index 4f029fe0b..dc435aab9 100644 --- a/imgui.h +++ b/imgui.h @@ -588,7 +588,8 @@ enum ImGuiSetCond_ { ImGuiSetCond_Always = 1 << 0, // Set the variable ImGuiSetCond_Once = 1 << 1, // Only set the variable on the first call per runtime session - ImGuiSetCond_FirstUseEver = 1 << 2 // Only set the variable if the window doesn't exist in the .ini file + ImGuiSetCond_FirstUseEver = 1 << 2, // Only set the variable if the window doesn't exist in the .ini file + ImGuiSetCond_Appearing = 1 << 3 // Only set the variable if the window is appearing after being inactive (or the first time) }; struct ImGuiStyle From 33e8fb85cf201a08e079a3a0a1340c2d39f8dd54 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 18:43:08 +0100 Subject: [PATCH 13/34] Allow stacking popups, not really useful yet (wip #126) --- imgui.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7e584d88e..9ffaa6f54 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1123,6 +1123,7 @@ struct ImGuiState ImVector WindowsSortBuffer; ImGuiWindow* CurrentWindow; // Being drawn into ImVector CurrentWindowStack; + int CurrentPopupStackSize; ImGuiWindow* FocusedWindow; // Will catch keyboard inputs ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) @@ -1197,6 +1198,7 @@ struct ImGuiState FrameCount = 0; FrameCountRendered = -1; CurrentWindow = NULL; + CurrentPopupStackSize = 0; FocusedWindow = NULL; HoveredWindow = NULL; HoveredRootWindow = NULL; @@ -2893,13 +2895,17 @@ void ImGui::EndTooltip() void ImGui::BeginPopup(bool* p_opened) { + ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(p_opened != NULL); // Must provide a bool at the moment ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGuiWindowFlags flags = ImGuiWindowFlags_Popup|ImGuiWindowFlags_ShowBorders|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; float alpha = 1.0f; - ImGui::Begin("##Popup", p_opened, ImVec2(0.0f, 0.0f), alpha, flags); + + char name[20]; + ImFormatString(name, 20, "##Popup%02d", g.CurrentPopupStackSize++); + ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), alpha, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -2907,7 +2913,10 @@ void ImGui::BeginPopup(bool* p_opened) void ImGui::EndPopup() { + ImGuiState& g = *GImGui; IM_ASSERT(GetCurrentWindow()->Flags & ImGuiWindowFlags_Popup); + IM_ASSERT(g.CurrentPopupStackSize > 0); + g.CurrentPopupStackSize--; ImGui::End(); ImGui::PopStyleVar(); } @@ -3133,6 +3142,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ const bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on // Add to stack + ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL; g.CurrentWindowStack.push_back(window); SetCurrentWindow(window); @@ -3165,9 +3175,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ g.SetNextWindowFocus = false; } - // Find parent - ImGuiWindow* parent_window = (flags & ImGuiWindowFlags_ChildWindow) != 0 ? g.CurrentWindowStack[g.CurrentWindowStack.size()-2] : NULL; - // Update known root window (if we are a child window, otherwise window == window->RootWindow) size_t root_idx = g.CurrentWindowStack.size() - 1; while (root_idx > 0) From debe6522bb6cc25a31cb7e4a46926d9cc31edb4e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2015 19:00:17 +0100 Subject: [PATCH 14/34] Examples: test for tooltip over popup. --- imgui.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 9ffaa6f54..cdab5a644 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10056,7 +10056,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Popup, Menus")) { static int selected_fish = -1; - const char* names[] = { "BreamXYZA", "Haddk", "Mackerel", "Pollock", "Tilefish" }; + const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; static bool toggles[] = { true, false, false, false, false }; { @@ -10091,6 +10091,12 @@ void ImGui::ShowTestWindow(bool* opened) for (int i = 0; i < IM_ARRAYSIZE(names); i++) if (ImGui::MenuItem(names[i], "", &toggles[i])) popup_open = false; + + ImGui::Separator(); + ImGui::Text("Tooltip here"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("I am a tooltip over a popup"); + ImGui::EndPopup(); } } From 9fe654c6e44b1cacfc2adc35fe2b02d39aed59fe Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 9 May 2015 09:59:46 +0100 Subject: [PATCH 15/34] Assert on modifiers stack size mismatch between Begni()/End() pairs #204 Experimenting with this. It's helpful but not happy with the idea of ImGui asserting on that sort of user error. --- imgui.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 1b8493b53..b300e0f2f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1013,6 +1013,7 @@ struct ImGuiDrawContext ImVector GroupStack; ImGuiColorEditMode ColorEditMode; ImGuiStorage* StateStorage; + int StackSizesBackup[5]; // store size of various stacks for asserting float ColumnsStartX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. @@ -1037,6 +1038,7 @@ struct ImGuiDrawContext LastItemHoveredAndUsable = LastItemHoveredRect = false; ColorEditMode = ImGuiColorEditMode_RGB; StateStorage = NULL; + memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); ColumnsStartX = 0.0f; ColumnsOffsetX = 0.0f; @@ -3003,6 +3005,20 @@ void ImGui::EndChildFrame() ImGui::PopStyleColor(); } +// Save and compare stack sizes on Begin()/End() to detect usage errors +static void CheckStacksSize(ImGuiWindow* window, bool write) +{ + // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) + ImGuiState& g = *GImGui; + int* p_backup = &window->DC.StackSizesBackup[0]; + { int current = (int)window->IDStack.size(); if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopID() + { int current = (int)window->DC.GroupStack.size(); if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot EndGroup() + { int current = (int)g.ColorModifiers.size(); if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopStyleColor() + { int current = (int)g.StyleModifiers.size(); if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopStyleVar() + { int current = (int)g.FontStack.size(); if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopFont() + IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); +} + static ImVec2 FindBestWindowPos(const ImVec2& mouse_pos, const ImVec2& size, int* last_dir, const ImRect& r_inner) { const ImGuiStyle& style = GImGui->Style; @@ -3132,6 +3148,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Add to stack g.CurrentWindowStack.push_back(window); SetCurrentWindow(window); + CheckStacksSize(window, true); // Process SetNextWindow***() calls bool window_pos_set_by_api = false; @@ -3599,6 +3616,7 @@ void ImGui::End() // Pop // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin(). + CheckStacksSize(window, false); g.CurrentWindowStack.pop_back(); SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); } From f293bec97c2e0a390b555d16b0ab4e2ba058fe9b Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 9 May 2015 10:13:56 +0100 Subject: [PATCH 16/34] Added style.ScrollbarRounding #212 --- imgui.cpp | 8 +++++--- imgui.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c70229e30..ffa9d146a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -569,7 +569,8 @@ ImGuiStyle::ImGuiStyle() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarWidth = 16.0f; // Width of the vertical scrollbar - GrabMinSize = 10.0f; // Minimum width/height of a slider or scrollbar grab + ScrollbarRounding = 0.0f; // Radius of grab corners rounding for scrollbar + GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. @@ -3698,7 +3699,7 @@ static void Scrollbar(ImGuiWindow* window) // Render const ImU32 grab_col = window->Color(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); - window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm) + grab_h_pixels), grab_col); + window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm) + grab_h_pixels), grab_col, style.ScrollbarRounding); } // Moving window to front of display (which happens to be back of our sorted list) @@ -9707,7 +9708,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("ScrollBarWidth", &style.ScrollbarWidth, 1.0f, 20.0f, "%.0f"); + ImGui::SliderFloat("ScrollbarWidth", &style.ScrollbarWidth, 1.0f, 20.0f, "%.0f"); + ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 16.0f, "%.0f"); ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f"); ImGui::TreePop(); } diff --git a/imgui.h b/imgui.h index dc435aab9..9249a309d 100644 --- a/imgui.h +++ b/imgui.h @@ -608,7 +608,8 @@ struct ImGuiStyle float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarWidth; // Width of the vertical scrollbar - float GrabMinSize; // Minimum width/height of a slider or scrollbar grab + float ScrollbarRounding; // Radius of grab corners for scrollbar + float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. ImVec4 Colors[ImGuiCol_COUNT]; From 6c1084eaa1bd3f671937ff5132433004ed56d045 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 9 May 2015 10:27:03 +0100 Subject: [PATCH 17/34] Shutdown() test for g.IO.Fonts not being NULL to allow workarounds in case of using multiple contexts #207 --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ffa9d146a..00bb582a8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2124,7 +2124,8 @@ void ImGui::Shutdown() ImGui::MemFree(g.LogClipboard); } - g.IO.Fonts->Clear(); + if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. + g.IO.Fonts->Clear(); g.Initialized = false; } From bb2d3a8b41bbb1d08216cc4ad93aab0be75d7d93 Mon Sep 17 00:00:00 2001 From: ghassanpl Date: Sun, 10 May 2015 22:29:24 +0200 Subject: [PATCH 18/34] * make sure letter-key shortcuts have ONLY the control key pressed (fixes bug for AltGr->Ctrl+Alt on windows) --- imgui.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 00bb582a8..253694720 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6525,7 +6525,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT ImGuiTextEditState& edit_state = g.InputTextState; const bool is_ctrl_down = io.KeyCtrl; - const bool is_shift_down = io.KeyShift; + const bool is_shift_down = io.KeyShift; + const bool is_alt_down = io.KeyAlt; const bool focus_requested = window->FocusItemRegister(g.ActiveId == id, (flags & ImGuiInputTextFlags_CallbackCompletion) == 0); // Using completion callback disable keyboard tabbing const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; @@ -6655,10 +6656,10 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT else if (IsKeyPressedMap(ImGuiKey_Backspace)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Enter)) { SetActiveId(0); enter_pressed = true; } else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveId(0); cancel_edit = true; } - else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); } - else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); } - else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); } - else if (is_ctrl_down && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C))) + else if (is_ctrl_down && !is_alt_down && !is_shift_down && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); } + else if (is_ctrl_down && !is_alt_down && !is_shift_down && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); } + else if (is_ctrl_down && !is_alt_down && !is_shift_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); } + else if (is_ctrl_down && !is_alt_down && !is_shift_down && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C))) { // Cut, Copy const bool cut = IsKeyPressedMap(ImGuiKey_X); From 4913668ea4e0618045a48a1efd42650b092a83e8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 May 2015 09:23:29 +0100 Subject: [PATCH 19/34] Fixed implicit conversion of NULL constant to bool (fix #216) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 9249a309d..7bcd30dcf 100644 --- a/imgui.h +++ b/imgui.h @@ -359,7 +359,7 @@ namespace ImGui // Widgets: Menus // FIXME-WIP: v1.39 in development - IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = NULL); // bool enabled = true + IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false); // bool enabled = true IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected); // bool enabled = true // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare your own within the ImGui namespace!) From c2c43928a9a649b27af8f11dce5dd9cdd6d53070 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 May 2015 09:26:53 +0100 Subject: [PATCH 20/34] Untabifiy --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 253694720..231befa4e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6525,8 +6525,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT ImGuiTextEditState& edit_state = g.InputTextState; const bool is_ctrl_down = io.KeyCtrl; - const bool is_shift_down = io.KeyShift; - const bool is_alt_down = io.KeyAlt; + const bool is_shift_down = io.KeyShift; + const bool is_alt_down = io.KeyAlt; const bool focus_requested = window->FocusItemRegister(g.ActiveId == id, (flags & ImGuiInputTextFlags_CallbackCompletion) == 0); // Using completion callback disable keyboard tabbing const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; diff --git a/imgui.h b/imgui.h index 7bcd30dcf..347aaffa0 100644 --- a/imgui.h +++ b/imgui.h @@ -358,7 +358,7 @@ namespace ImGui IMGUI_API void ListBoxFooter(); // terminate the scrolling region // Widgets: Menus - // FIXME-WIP: v1.39 in development + // FIXME-WIP: v1.39 in development IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false); // bool enabled = true IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected); // bool enabled = true From 4a41ce9414f25a6004dd4eebf82337f346aff45e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 May 2015 09:29:10 +0100 Subject: [PATCH 21/34] InputText: make sure Ctrl+V has ONLY the control key pressed (follow up to #214) + tidying --- imgui.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 231befa4e..f8b001300 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6648,6 +6648,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT } const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0); + const bool is_ctrl_only = is_ctrl_down && !is_alt_down && !is_shift_down; if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDRIGHT | k_mask : STB_TEXTEDIT_K_RIGHT | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } @@ -6656,10 +6657,10 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT else if (IsKeyPressedMap(ImGuiKey_Backspace)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Enter)) { SetActiveId(0); enter_pressed = true; } else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveId(0); cancel_edit = true; } - else if (is_ctrl_down && !is_alt_down && !is_shift_down && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); } - else if (is_ctrl_down && !is_alt_down && !is_shift_down && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); } - else if (is_ctrl_down && !is_alt_down && !is_shift_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); } - else if (is_ctrl_down && !is_alt_down && !is_shift_down && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C))) + else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); } + else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); } + else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); } + else if (is_ctrl_only && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C))) { // Cut, Copy const bool cut = IsKeyPressedMap(ImGuiKey_X); @@ -6677,7 +6678,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT if (cut) stb_textedit_cut(&edit_state, &edit_state.StbState); } - else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_V)) + else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_V)) { // Paste if (g.IO.GetClipboardTextFn) From 99a1a85f1ff418e99ec70c4b0d3cb49efffee5c2 Mon Sep 17 00:00:00 2001 From: Stefano Cristiano Date: Mon, 11 May 2015 14:45:49 +0200 Subject: [PATCH 22/34] Example fix PopStyleVar on Vertical Slider to avoid assertion Adding an explicit ImGui::PopStyleVar to avoid assertion in CheckStacksSize --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index f8b001300..0ad046084 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10345,6 +10345,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PopID(); } ImGui::PopID(); + ImGui::PopStyleVar(); ImGui::Indent(); ImGui::TreePop(); From 94b7c9e307e36d7f6f0015d780df2964c024e9e6 Mon Sep 17 00:00:00 2001 From: Emmanuel Durand Date: Mon, 11 May 2015 10:15:22 -0400 Subject: [PATCH 23/34] Input text flags added to InputFloatN and InputIntN --- imgui.cpp | 32 ++++++++++++++++---------------- imgui.h | 12 ++++++------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ca53c4a79..8dc6ac2de 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6703,7 +6703,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT return value_changed; } -static bool InputFloatN(const char* label, float* v, int components, int decimal_precision) +static bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags flags) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -6727,7 +6727,7 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal ImGui::PopItemWidth(); ImGui::PushItemWidth(w_item_last); } - value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision); + value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, flags); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); ImGui::PopID(); } @@ -6741,22 +6741,22 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal return value_changed; } -bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision) +bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags) { - return InputFloatN(label, v, 2, decimal_precision); + return InputFloatN(label, v, 2, decimal_precision, flags); } -bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision) +bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags) { - return InputFloatN(label, v, 3, decimal_precision); + return InputFloatN(label, v, 3, decimal_precision, flags); } -bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision) +bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags) { - return InputFloatN(label, v, 4, decimal_precision); + return InputFloatN(label, v, 4, decimal_precision, flags); } -static bool InputIntN(const char* label, int* v, int components) +static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags flags) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -6780,7 +6780,7 @@ static bool InputIntN(const char* label, int* v, int components) ImGui::PopItemWidth(); ImGui::PushItemWidth(w_item_last); } - value_changed |= ImGui::InputInt("##v", &v[i], 0, 0); + value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, flags); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); ImGui::PopID(); } @@ -6794,19 +6794,19 @@ static bool InputIntN(const char* label, int* v, int components) return value_changed; } -bool ImGui::InputInt2(const char* label, int v[2]) +bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags) { - return InputIntN(label, v, 2); + return InputIntN(label, v, 2, flags); } -bool ImGui::InputInt3(const char* label, int v[3]) +bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags) { - return InputIntN(label, v, 3); + return InputIntN(label, v, 3, flags); } -bool ImGui::InputInt4(const char* label, int v[4]) +bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) { - return InputIntN(label, v, 4); + return InputIntN(label, v, 4, flags); } static bool Items_ArrayGetter(void* data, int idx, const char** out_text) diff --git a/imgui.h b/imgui.h index 4b2416765..ef9560c26 100644 --- a/imgui.h +++ b/imgui.h @@ -329,13 +329,13 @@ namespace ImGui // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1); - IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1); - IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1); + IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2]); - IMGUI_API bool InputInt3(const char* label, int v[3]); - IMGUI_API bool InputInt4(const char* label, int v[4]); + IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); // Widgets: Trees IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop From b3faed610d6f4da89872dd5888e6bae9084d43da Mon Sep 17 00:00:00 2001 From: Emmanuel Durand Date: Mon, 11 May 2015 11:40:08 -0400 Subject: [PATCH 24/34] Renamed flags to extra_flags in last commit --- imgui.cpp | 32 ++++++++++++++++---------------- imgui.h | 12 ++++++------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8dc6ac2de..f0ee8ec2d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6703,7 +6703,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT return value_changed; } -static bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags flags) +static bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -6727,7 +6727,7 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal ImGui::PopItemWidth(); ImGui::PushItemWidth(w_item_last); } - value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, flags); + value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); ImGui::PopID(); } @@ -6741,22 +6741,22 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal return value_changed; } -bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags) +bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) { - return InputFloatN(label, v, 2, decimal_precision, flags); + return InputFloatN(label, v, 2, decimal_precision, extra_flags); } -bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags) +bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) { - return InputFloatN(label, v, 3, decimal_precision, flags); + return InputFloatN(label, v, 3, decimal_precision, extra_flags); } -bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags) +bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) { - return InputFloatN(label, v, 4, decimal_precision, flags); + return InputFloatN(label, v, 4, decimal_precision, extra_flags); } -static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags flags) +static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -6780,7 +6780,7 @@ static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextF ImGui::PopItemWidth(); ImGui::PushItemWidth(w_item_last); } - value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, flags); + value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, extra_flags); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); ImGui::PopID(); } @@ -6794,19 +6794,19 @@ static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextF return value_changed; } -bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags) +bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags) { - return InputIntN(label, v, 2, flags); + return InputIntN(label, v, 2, extra_flags); } -bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags) +bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags) { - return InputIntN(label, v, 3, flags); + return InputIntN(label, v, 3, extra_flags); } -bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) +bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags) { - return InputIntN(label, v, 4, flags); + return InputIntN(label, v, 4, extra_flags); } static bool Items_ArrayGetter(void* data, int idx, const char** out_text) diff --git a/imgui.h b/imgui.h index ef9560c26..d074e4c6a 100644 --- a/imgui.h +++ b/imgui.h @@ -329,13 +329,13 @@ namespace ImGui // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); // Widgets: Trees IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop From 515e0c6122a03dd34b546c31dff426d2e6a3dee8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 May 2015 21:44:50 +0100 Subject: [PATCH 25/34] Cleanup, merged duplicate code into a function --- imgui.cpp | 116 ++++++++++++++++-------------------------------------- imgui.h | 2 +- 2 files changed, 35 insertions(+), 83 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 65e6c39f7..fcb725434 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3737,6 +3737,19 @@ void ImGui::PushItemWidth(float item_width) window->DC.ItemWidth.push_back(item_width == 0.0f ? window->ItemWidthDefault : item_width); } +static void PushMultiItemsWidths(int components, float w_full = 0.0f) +{ + ImGuiWindow* window = GetCurrentWindow(); + const ImGuiStyle& style = GImGui->Style; + if (w_full <= 0.0f) + w_full = ImGui::CalcItemWidth(); + const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); + window->DC.ItemWidth.push_back(w_item_last); + for (int i = 0; i < components-1; i++) + window->DC.ItemWidth.push_back(w_item_one); +} + void ImGui::PopItemWidth() { ImGuiWindow* window = GetCurrentWindow(); @@ -3751,9 +3764,8 @@ float ImGui::CalcItemWidth() { // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well. ImGuiState& g = *GImGui; - w = -w; float width_to_right_edge = window->Pos.x + ImGui::GetContentRegionMax().x - window->DC.CursorPos.x; - w = ImMax(1.0f, width_to_right_edge - w - g.Style.FramePadding.x * 2.0f); + w = ImMax(1.0f, width_to_right_edge + w - g.Style.FramePadding.x * 2.0f); } w = (float)(int)w; return w; @@ -5556,28 +5568,18 @@ static bool SliderFloatN(const char* label, float* v, int components, float v_mi if (window->SkipItems) return false; - const ImGuiStyle& style = g.Style; - const float w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1))); - bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); - ImGui::PushItemWidth(w_item_one); + PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { ImGui::PushID(i); - if (i + 1 == components) - { - ImGui::PopItemWidth(); - ImGui::PushItemWidth(w_item_last); - } value_changed |= ImGui::SliderFloat("##v", &v[i], v_min, v_max, display_format, power); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x); ImGui::PopID(); + ImGui::PopItemWidth(); } - ImGui::PopItemWidth(); ImGui::PopID(); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); @@ -5608,28 +5610,18 @@ static bool SliderIntN(const char* label, int* v, int components, int v_min, int if (window->SkipItems) return false; - const ImGuiStyle& style = g.Style; - const float w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1))); - bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); - ImGui::PushItemWidth(w_item_one); + PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { ImGui::PushID(i); - if (i + 1 == components) - { - ImGui::PopItemWidth(); - ImGui::PushItemWidth(w_item_last); - } value_changed |= ImGui::SliderInt("##v", &v[i], v_min, v_max, display_format); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x); ImGui::PopID(); + ImGui::PopItemWidth(); } - ImGui::PopItemWidth(); ImGui::PopID(); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); @@ -5803,28 +5795,18 @@ static bool DragFloatN(const char* label, float* v, int components, float v_spee if (window->SkipItems) return false; - const ImGuiStyle& style = g.Style; - const float w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1))); - bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); - ImGui::PushItemWidth(w_item_one); + PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { ImGui::PushID(i); - if (i + 1 == components) - { - ImGui::PopItemWidth(); - ImGui::PushItemWidth(w_item_last); - } value_changed |= ImGui::DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x); ImGui::PopID(); + ImGui::PopItemWidth(); } - ImGui::PopItemWidth(); ImGui::PopID(); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); @@ -5866,28 +5848,18 @@ static bool DragIntN(const char* label, int* v, int components, float v_speed, i if (window->SkipItems) return false; - const ImGuiStyle& style = g.Style; - const float w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1))); - bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); - ImGui::PushItemWidth(w_item_one); + PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { ImGui::PushID(i); - if (i + 1 == components) - { - ImGui::PopItemWidth(); - ImGui::PushItemWidth(w_item_last); - } value_changed |= ImGui::DragInt("##v", &v[i], v_speed, v_min, v_max, display_format); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x); ImGui::PopID(); + ImGui::PopItemWidth(); } - ImGui::PopItemWidth(); ImGui::PopID(); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); @@ -6846,31 +6818,21 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal if (window->SkipItems) return false; - const ImGuiStyle& style = g.Style; - const float w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); - bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); - ImGui::PushItemWidth(w_item_one); + PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { ImGui::PushID(i); - if (i + 1 == components) - { - ImGui::PopItemWidth(); - ImGui::PushItemWidth(w_item_last); - } value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x); ImGui::PopID(); + ImGui::PopItemWidth(); } - ImGui::PopItemWidth(); ImGui::PopID(); - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, style.FramePadding.y); + window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); ImGui::EndGroup(); @@ -6899,31 +6861,21 @@ static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextF if (window->SkipItems) return false; - const ImGuiStyle& style = g.Style; - const float w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); - bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); - ImGui::PushItemWidth(w_item_one); + PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { ImGui::PushID(i); - if (i + 1 == components) - { - ImGui::PopItemWidth(); - ImGui::PushItemWidth(w_item_last); - } value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, extra_flags); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x); ImGui::PopID(); + ImGui::PopItemWidth(); } - ImGui::PopItemWidth(); ImGui::PopID(); - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, style.FramePadding.y); + window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); ImGui::EndGroup(); diff --git a/imgui.h b/imgui.h index c082be5a7..6c315c25f 100644 --- a/imgui.h +++ b/imgui.h @@ -211,7 +211,7 @@ namespace ImGui IMGUI_API void PopStyleVar(int count = 1); // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -0.01f always align width to the right side) + IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API void PopItemWidth(); IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position IMGUI_API void PushAllowKeyboardFocus(bool v); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets From 9be331965394dc3268835cbb5f9196502a015983 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 09:08:47 +0100 Subject: [PATCH 26/34] Tweaks, comments around ImFontAtlas Removed unsigned int from API --- imgui.cpp | 18 +++++++++--------- imgui.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fcb725434..43ed59d3b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8470,8 +8470,8 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, return font; } -// NB: ownership of 'data' is given to ImFontAtlas which will clear it. -ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) +// Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() +ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) { // Create new font ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont)); @@ -8482,8 +8482,8 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf ImFontAtlasData* data = (ImFontAtlasData*)ImGui::MemAlloc(sizeof(ImFontAtlasData)); memset(data, 0, sizeof(ImFontAtlasData)); data->OutFont = font; - data->TTFData = in_ttf_data; - data->TTFDataSize = in_ttf_data_size; + data->TTFData = ttf_data; + data->TTFDataSize = (size_t)ttf_size; data->SizePixels = size_pixels; data->GlyphRanges = glyph_ranges; data->FontNo = font_no; @@ -8495,15 +8495,15 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf return font; } -ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, unsigned int in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) +ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) { // Decompress - const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)in_compressed_ttf_data); - unsigned char* buf_decompressed = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); - stb_decompress(buf_decompressed, (unsigned char*)in_compressed_ttf_data, in_compressed_ttf_data_size); + const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data); + unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); + stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); // Add - ImFont* font = AddFontFromMemoryTTF(buf_decompressed, (unsigned int)buf_decompressed_size, size_pixels, glyph_ranges, font_no); + ImFont* font = AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, glyph_ranges, font_no); return font; } diff --git a/imgui.h b/imgui.h index 6c315c25f..639b0b9dc 100644 --- a/imgui.h +++ b/imgui.h @@ -967,8 +967,8 @@ struct ImFontAtlas IMGUI_API ~ImFontAtlas(); IMGUI_API ImFont* AddFontDefault(); IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // Pass ownership of 'in_ttf_data' memory, will be deleted after build - IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, unsigned int in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // 'in_compressed_ttf_data' untouched and still owned by caller. compress with binary_to_compressed_c. + IMGUI_API ImFont* AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() + IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // 'compressed_ttf_data' untouched and still owned by caller. Compress with binary_to_compressed_c.cpp IMGUI_API void ClearTexData(); // Saves RAM once the texture has been copied to graphics memory. IMGUI_API void Clear(); From 356a37edcfa78d62590b72ccc75e10839793990d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 11:49:24 +0100 Subject: [PATCH 27/34] Added window title text horizontal alignment option (#222),, ImGuiAlign_ type for future use. --- imgui.cpp | 22 +++++++++++----------- imgui.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 43ed59d3b..b4d8c0927 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -498,7 +498,7 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); -static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max); +static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max, ImGuiAlign align = ImGuiAlign_Default); static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false); static void RenderCheckMark(ImVec2 pos, ImU32 col); @@ -559,6 +559,7 @@ ImGuiStyle::ImGuiStyle() WindowPadding = ImVec2(8,8); // Padding within a window WindowMinSize = ImVec2(32,32); // Minimum window size WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows + WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). @@ -2458,16 +2459,13 @@ static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end const int text_len = (int)(text_end - text); if (text_len > 0) { - // Render window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_end, wrap_width); - - // Log as text if (g.LogEnabled) LogText(pos, text, text_end); } } -static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max) +static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max, ImGuiAlign align) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -2477,15 +2475,16 @@ static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end const int text_len = (int)(text_display_end - text); if (text_len > 0) { - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f); - // Perform CPU side clipping for single clipped element to avoid using scissor state + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f); const bool need_clipping = (pos.x + text_size.x >= clip_max.x) || (pos.y + text_size.y >= clip_max.y); + // Align + if (align & ImGuiAlign_Center) pos.x = ImMax(pos.x, (pos.x + clip_max.x - text_size.x) * 0.5f); + else if (align & ImGuiAlign_Right) pos.x = ImMax(pos.x, clip_max.x - text_size.x); + // Render window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_display_end, 0.0f, need_clipping ? &clip_max : NULL); - - // Log as text if (g.LogEnabled) LogText(pos, text, text_display_end); } @@ -3547,8 +3546,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } const ImVec2 text_size = CalcTextSize(name, NULL, true); - const ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? (title_bar_rect.GetHeight()-3) : style.FramePadding.x), style.FramePadding.y*2 + text_size.y); - RenderTextClipped(text_min, name, NULL, &text_size, text_max); + ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? title_bar_rect.GetHeight()-3 : style.FramePadding.x), style.FramePadding.y*2 + text_size.y); + if (style.WindowTitleAlign & ImGuiAlign_Right) text_max.x -= style.FramePadding.x; + RenderTextClipped(text_min, name, NULL, &text_size, text_max, style.WindowTitleAlign); } if (flags & ImGuiWindowFlags_Popup) { diff --git a/imgui.h b/imgui.h index 639b0b9dc..cdf5766a0 100644 --- a/imgui.h +++ b/imgui.h @@ -42,6 +42,7 @@ typedef ImU32 ImGuiID; // unique ID used by widgets (typically hash typedef int ImGuiCol; // enum ImGuiCol_ typedef int ImGuiStyleVar; // enum ImGuiStyleVar_ typedef int ImGuiKey; // enum ImGuiKey_ +typedef int ImGuiAlign; // enum ImGuiAlign_ typedef int ImGuiColorEditMode; // enum ImGuiColorEditMode_ typedef int ImGuiMouseCursor; // enum ImGuiMouseCursor_ typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_ @@ -559,6 +560,14 @@ enum ImGuiStyleVar_ ImGuiStyleVar_GrabMinSize // float }; +enum ImGuiAlign_ +{ + ImGuiAlign_Left = 1 << 0, + ImGuiAlign_Center = 1 << 1, + ImGuiAlign_Right = 1 << 2, + ImGuiAlign_Default = ImGuiAlign_Left, +}; + // Enumeration for ColorEditMode() enum ImGuiColorEditMode_ { @@ -598,6 +607,7 @@ struct ImGuiStyle ImVec2 WindowPadding; // Padding within a window ImVec2 WindowMinSize; // Minimum window size float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows + ImGuiAlign WindowTitleAlign; // Alignment for title bar text float ChildWindowRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets) float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). From 30552ecfd61a7b5ab7cceaf7ecf32c5c2665371c Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 11:51:22 +0100 Subject: [PATCH 28/34] Fixed comment (fix #223) --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index cdf5766a0..61593ba5c 100644 --- a/imgui.h +++ b/imgui.h @@ -318,11 +318,11 @@ namespace ImGui IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); // Widgets: Drags (tip: ctrl+click on a drag box to input text) - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_max >= v_max we have no bound + IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_min >= v_max we have no bound IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); From ad79db32c73ae98ed76ae875c016777183fd0f58 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 14:02:45 +0100 Subject: [PATCH 29/34] Window title text centering tweaks, RenderTextClipped() now has different args for pos_max and clip_max #222 --- imgui.cpp | 59 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b4d8c0927..4c40ffc9d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -498,7 +498,7 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); -static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max, ImGuiAlign align = ImGuiAlign_Default); +static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& pos_max, const ImVec2* clip_max = NULL, ImGuiAlign align = ImGuiAlign_Default); static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false); static void RenderCheckMark(ImVec2 pos, ImU32 col); @@ -2465,29 +2465,30 @@ static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end } } -static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max, ImGuiAlign align) +static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& pos_max, const ImVec2* clip_max, ImGuiAlign align) { - ImGuiState& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - // Hide anything after a '##' string const char* text_display_end = FindTextDisplayEnd(text, text_end); const int text_len = (int)(text_display_end - text); - if (text_len > 0) - { - // Perform CPU side clipping for single clipped element to avoid using scissor state - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f); - const bool need_clipping = (pos.x + text_size.x >= clip_max.x) || (pos.y + text_size.y >= clip_max.y); + if (text_len == 0) + return; - // Align - if (align & ImGuiAlign_Center) pos.x = ImMax(pos.x, (pos.x + clip_max.x - text_size.x) * 0.5f); - else if (align & ImGuiAlign_Right) pos.x = ImMax(pos.x, clip_max.x - text_size.x); + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); - // Render - window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_display_end, 0.0f, need_clipping ? &clip_max : NULL); - if (g.LogEnabled) - LogText(pos, text, text_display_end); - } + // Perform CPU side clipping for single clipped element to avoid using scissor state + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f); + if (!clip_max) clip_max = &pos_max; + const bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); + + // Align + if (align & ImGuiAlign_Center) pos.x = ImMax(pos.x, (pos.x + pos_max.x - text_size.x) * 0.5f); + else if (align & ImGuiAlign_Right) pos.x = ImMax(pos.x, pos_max.x - text_size.x); + + // Render + window->DrawList->AddText(g.Font, g.FontSize, pos, window->Color(ImGuiCol_Text), text, text_display_end, 0.0f, need_clipping ? clip_max : NULL); + if (g.LogEnabled) + LogText(pos, text, text_display_end); } // Render a rectangle shaped with optional rounding and borders @@ -3538,17 +3539,19 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ if (p_opened != NULL) CloseWindowButton(p_opened); - ImVec2 text_min = window->Pos + style.FramePadding; - if (!(flags & ImGuiWindowFlags_NoCollapse)) - { - RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true); - text_min.x += g.FontSize + style.ItemInnerSpacing.x; - } - const ImVec2 text_size = CalcTextSize(name, NULL, true); - ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? title_bar_rect.GetHeight()-3 : style.FramePadding.x), style.FramePadding.y*2 + text_size.y); - if (style.WindowTitleAlign & ImGuiAlign_Right) text_max.x -= style.FramePadding.x; - RenderTextClipped(text_min, name, NULL, &text_size, text_max, style.WindowTitleAlign); + if (!(flags & ImGuiWindowFlags_NoCollapse)) + RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true); + + ImVec2 text_min = window->Pos + style.FramePadding; + ImVec2 text_max = window->Pos + ImVec2(window->Size.x - style.FramePadding.x, style.FramePadding.y*2 + text_size.y); + ImVec2 clip_max = ImVec2(window->Pos.x + window->Size.x - (p_opened ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton() + bool pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0; + bool pad_right = (p_opened != NULL); + if (style.WindowTitleAlign & ImGuiAlign_Center) pad_right = pad_left; + if (pad_left) text_min.x += g.FontSize + style.ItemInnerSpacing.x; + if (pad_right) text_max.x -= g.FontSize + style.ItemInnerSpacing.x; + RenderTextClipped(text_min, name, NULL, &text_size, text_max, &clip_max, style.WindowTitleAlign); } if (flags & ImGuiWindowFlags_Popup) { From 9d9cf31972b96f90e46ac547423d724bf8647ded Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 14:53:29 +0100 Subject: [PATCH 30/34] ImFontAtlas: added ClearFonts(), making the different clear funcs more explicit (#224) --- imgui.cpp | 14 ++++++++++---- imgui.h | 7 ++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4c40ffc9d..1ca522f52 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -343,6 +343,7 @@ - columns: columns header to act as button (~sort op) and allow resize/reorder (github issue #125) - columns: user specify columns size (github issue #125) - popup: border options. richer api like BeginChild() perhaps? (github issue #197) + - combo: sparse combo boxes (via function call?) - combo: turn child handling code into pop up helper - combo: contents should extends to fit label if combo widget is small - combo/listbox: keyboard control. need inputtext like non-active focus + key handling. considering keybord for custom listbox (see github pr #203) @@ -8384,10 +8385,8 @@ void ImFontAtlas::ClearTexData() TexPixelsRGBA32 = NULL; } -void ImFontAtlas::Clear() +void ImFontAtlas::ClearFonts() { - ClearInputData(); - ClearTexData(); for (size_t i = 0; i < Fonts.size(); i++) { Fonts[i]->~ImFont(); @@ -8396,6 +8395,13 @@ void ImFontAtlas::Clear() Fonts.clear(); } +void ImFontAtlas::Clear() +{ + ClearInputData(); + ClearTexData(); + ClearFonts(); +} + void ImGui::GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size) { printf("GetDefaultFontData() is obsoleted in ImGui 1.30.\n"); @@ -9824,7 +9830,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::TreePop(); } - if (ImGui::TreeNode("Fonts")) + if (ImGui::TreeNode("Fonts", "Fonts (%d)", (int)ImGui::GetIO().Fonts->Fonts.size())) { ImGui::TextWrapped("Tip: Load fonts with GetIO().Fonts->AddFontFromFileTTF()."); for (size_t i = 0; i < ImGui::GetIO().Fonts->Fonts.size(); i++) diff --git a/imgui.h b/imgui.h index 61593ba5c..378e9b307 100644 --- a/imgui.h +++ b/imgui.h @@ -979,8 +979,10 @@ struct ImFontAtlas IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); IMGUI_API ImFont* AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // 'compressed_ttf_data' untouched and still owned by caller. Compress with binary_to_compressed_c.cpp - IMGUI_API void ClearTexData(); // Saves RAM once the texture has been copied to graphics memory. - IMGUI_API void Clear(); + IMGUI_API void ClearTexData(); // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics memory. + IMGUI_API void ClearInputData(); // Clear the input TTF data (inc sizes, glyph ranges) + IMGUI_API void ClearFonts(); // Clear the ImGui-side font data (glyphs storage, UV coordinates) + IMGUI_API void Clear(); // Clear all // Retrieve texture data // User is in charge of copying the pixels into graphics memory, then call SetTextureUserID() @@ -1011,7 +1013,6 @@ struct ImFontAtlas struct ImFontAtlasData; ImVector InputData; // Internal data IMGUI_API bool Build(); // Build pixels data. This is automatically for you by the GetTexData*** functions. - IMGUI_API void ClearInputData(); // Clear the input TTF data. IMGUI_API void RenderCustomTexData(int pass, void* rects); }; From 4b088ec7e896218bc67c79457fa6ce4def1f1bbb Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 15:10:36 +0100 Subject: [PATCH 31/34] ImFontAtlas: Fix toward allowing to add extra font without clearing existing one (need to comment out ClearInputData) (#224) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1ca522f52..e906baf4d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8531,7 +8531,7 @@ bool ImFontAtlas::Build() for (size_t input_i = 0; input_i < InputData.size(); input_i++) { ImFontAtlasData& data = *InputData[input_i]; - IM_ASSERT(data.OutFont && !data.OutFont->IsLoaded()); + IM_ASSERT(data.OutFont && (!data.OutFont->IsLoaded() || data.OutFont->ContainerAtlas == this)); const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)data.TTFData, data.FontNo); IM_ASSERT(font_offset >= 0); if (!stbtt_InitFont(&data.FontInfo, (unsigned char*)data.TTFData, font_offset)) @@ -8645,6 +8645,7 @@ bool ImFontAtlas::Build() int font_ascent, font_descent, font_line_gap; stbtt_GetFontVMetrics(&data.FontInfo, &font_ascent, &font_descent, &font_line_gap); data.OutFont->BaseLine = (font_ascent * font_scale); + data.OutFont->Glyphs.resize(0); const float uv_scale_x = 1.0f / TexWidth; const float uv_scale_y = 1.0f / TexHeight; From 5df542c3c09f09676c6f54e539736351219b8bf4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 15:16:12 +0100 Subject: [PATCH 32/34] ImFontAtlas: doesn't clear input data, left to the application. (#224) --- examples/directx11_example/imgui_impl_dx11.cpp | 4 ++++ examples/directx9_example/imgui_impl_dx9.cpp | 4 ++++ examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 4 ++++ examples/opengl_example/imgui_impl_glfw.cpp | 4 ++++ imgui.cpp | 1 - 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index ee1114847..4af5551d4 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -230,6 +230,10 @@ static void ImGui_ImplDX11_CreateFontsTexture() samplerDesc.MaxLOD = 0.f; g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); } + + // Cleanup (don't clear the input data if you want to append new fonts later) + io.Fonts->ClearInputData(); + io.Fonts->ClearTexData(); } bool ImGui_ImplDX11_CreateDeviceObjects() diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 3c14dc254..01628b9c8 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -224,6 +224,10 @@ static void ImGui_ImplDX9_CreateFontsTexture() // Store our identifier io.Fonts->TexID = (void *)pTexture; + + // Cleanup (don't clear the input data if you want to append new fonts later) + io.Fonts->ClearInputData(); + io.Fonts->ClearTexData(); } bool ImGui_ImplDX9_CreateDeviceObjects() diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 5796c04e8..cf7c5c991 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -174,6 +174,10 @@ void ImGui_ImplGlfwGL3_CreateFontsTexture() // Store our identifier io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Cleanup (don't clear the input data if you want to append new fonts later) + io.Fonts->ClearInputData(); + io.Fonts->ClearTexData(); } bool ImGui_ImplGlfwGL3_CreateDeviceObjects() diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index decf2529f..c5f9b22a4 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -156,6 +156,10 @@ bool ImGui_ImplGlfw_CreateDeviceObjects() // Store our identifier io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + // Cleanup (don't clear the input data if you want to append new fonts later) + io.Fonts->ClearInputData(); + io.Fonts->ClearTexData(); + return true; } diff --git a/imgui.cpp b/imgui.cpp index e906baf4d..a5a70daef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8683,7 +8683,6 @@ bool ImFontAtlas::Build() ImGui::MemFree(buf_ranges); buf_packedchars = NULL; buf_ranges = NULL; - ClearInputData(); // Render into our custom data block RenderCustomTexData(1, &extra_rects); From 1e4c22c206e38d542c2b0eed8f910d8d0f834034 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 May 2015 16:08:34 +0100 Subject: [PATCH 33/34] Added io.MetricsActiveWindows counter (#213) --- imgui.cpp | 2 ++ imgui.h | 1 + 2 files changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index a5a70daef..43da5574b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2255,6 +2255,7 @@ void ImGui::Render() // Gather windows to render g.IO.MetricsRenderVertices = 0; + g.IO.MetricsActiveWindows = 0; for (size_t i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].resize(0); for (size_t i = 0; i != g.Windows.size(); i++) @@ -2263,6 +2264,7 @@ void ImGui::Render() if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) { // FIXME: Generalize this with a proper layering system so we can stack. + g.IO.MetricsActiveWindows++; if (window->Flags & ImGuiWindowFlags_Popup) AddWindowToRenderList(g.RenderDrawLists[1], window); else if (window->Flags & ImGuiWindowFlags_Tooltip) diff --git a/imgui.h b/imgui.h index 378e9b307..c56e1dee4 100644 --- a/imgui.h +++ b/imgui.h @@ -700,6 +700,7 @@ struct ImGuiIO bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input) float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsRenderVertices; // Vertices processed during last call to Render() + int MetricsActiveWindows; // Number of visible windows (exclude child windows) //------------------------------------------------------------------ // [Internal] ImGui will maintain those fields for you From e57ee2852ad35ae73dd33f928e928b9c2de5ee32 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 May 2015 11:32:12 +0100 Subject: [PATCH 34/34] Comments --- imgui.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 43da5574b..b30ff4d04 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12,8 +12,8 @@ - PROGRAMMER GUIDE (read me!) - API BREAKING CHANGES (read me when you update!) - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - - Can I have multiple widgets with the same label? (Yes) - How do I update to a newer version of ImGui? + - Can I have multiple widgets with the same label? (Yes) - Why is my text output blurry? - How can I load a different font than the default? - How can I load multiple fonts? @@ -186,6 +186,16 @@ FREQUENTLY ASKED QUESTIONS (FAQ), TIPS ====================================== + Q: How do I update to a newer version of ImGui? + A: Overwrite the following files: + imgui.cpp + imgui.h + stb_rect_pack.h + stb_textedit.h + stb_truetype.h + Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a function, search for its name + in the code, there will likely be a comment about it. Please report any issue to the GitHub page! + Q: Can I have multiple widgets with the same label? A: Yes. A primer on the use of labels/IDs in ImGui.. @@ -270,15 +280,6 @@ e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! - Q: How do I update to a newer version of ImGui? - A: Overwrite the following files: - imgui.cpp - imgui.h - stb_rect_pack.h - stb_textedit.h - stb_truetype.h - Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. - Q: Why is my text output blurry? A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) @@ -329,6 +330,7 @@ - main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them. - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode? + - input text: add ImGuiInputTextFlags_EnterToApply? (off github issue #218) !- input number: large int not reliably supported because of int<>float conversions. - input number: optional range min/max for Input*() functions - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)