From 544ba36bf66e877b4ce69eb03a9d93736e6dab24 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 26 Apr 2016 11:59:56 +0200 Subject: [PATCH 001/105] Fixed GetFrontMostModalRootWindow() (#604) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ad3c6c114..c3184d3ff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3210,8 +3210,8 @@ static void CloseInactivePopups() static ImGuiWindow* GetFrontMostModalRootWindow() { ImGuiState& g = *GImGui; - if (!g.OpenedPopupStack.empty()) - if (ImGuiWindow* front_most_popup = g.OpenedPopupStack.back().Window) + for (int n = g.OpenedPopupStack.Size-1; n >= 0; n--) + if (ImGuiWindow* front_most_popup = g.OpenedPopupStack.Data[n].Window) if (front_most_popup->Flags & ImGuiWindowFlags_Modal) return front_most_popup; return NULL; From be7621f7c55bb4f410f6a545efd62babb10c5649 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 26 Apr 2016 19:23:36 +0200 Subject: [PATCH 002/105] Updated FAQ about non UTF-8 literal (#609, #613) --- imgui.cpp | 8 ++++++-- imgui.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c3184d3ff..8fb4a18f7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -411,13 +411,17 @@ io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. ImGui will support UTF-8 encoding across the board. - Character input depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. + A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. + All strings passed need to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese CP-1251 for Cyrillic) will not work. + In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. + You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); // Load Japanese characters io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() io.ImeWindowHandle = MY_HWND; // To input using Microsoft IME, give ImGui the hwnd of your application + As for text input, depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. + - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug" - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) diff --git a/imgui.h b/imgui.h index d6a097ee9..e093116ed 100644 --- a/imgui.h +++ b/imgui.h @@ -1262,7 +1262,7 @@ struct ImFontAtlas void SetTexID(void* id) { TexID = id; } // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) - // (Those functions could be static but aren't so most users don't have to refer to the ImFontAtlas:: name ever if in their code; just using io.Fonts->) + // NB: Make sure that your string are UTF-8 and NOT in your local code page. See FAQ for details. IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs From c5149cd53c80d022e6924b20e964544e9537cb20 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 27 Apr 2016 23:34:24 +0200 Subject: [PATCH 003/105] MenuItem(): checkmark render in disabled color when disabled --- imgui.cpp | 4 ++-- imgui_internal.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8fb4a18f7..1010afb7e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8364,7 +8364,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame float extra_w = ImMax(0.0f, ImGui::GetContentRegionAvail().x - w); - bool pressed = ImGui::Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + bool pressed = ImGui::Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f)); if (shortcut_size.x > 0.0f) { ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); @@ -8373,7 +8373,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo } if (selected) - RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), GetColorU32(ImGuiCol_Text)); + RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled)); return pressed; } diff --git a/imgui_internal.h b/imgui_internal.h index 90ceba1a0..eff7e27ba 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -707,7 +707,7 @@ namespace ImGui IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); - IMGUI_API void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false); + IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool opened, float scale = 1.0f, bool shadow = false); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. From 819cc414b1014d685e39bb32b5c2b65c72c4ecfa Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 28 Apr 2016 10:25:23 +0200 Subject: [PATCH 004/105] Metrics window: uses IM_COL32() macro to generate constant colors. --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1010afb7e..0038d011c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9346,8 +9346,8 @@ void ImGui::ShowMetricsWindow(bool* opened) ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); - clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, ImColor(255,255,0)); - vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, ImColor(255,0,255)); + clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); + vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255)); } if (!draw_opened) continue; @@ -9363,7 +9363,7 @@ void ImGui::ShowMetricsWindow(bool* opened) } ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) - overlay_draw_list->AddPolyline(triangles_pos, 3, ImColor(255,255,0), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle + overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle } ImGui::TreePop(); } From 7406d64c64a2759fd82ea7dad93b1e15a0615c85 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Apr 2016 18:55:23 +0200 Subject: [PATCH 005/105] PushClipRect(): not altering passed values, leave it to caller responsibility to floor properly (followup #582) --- imgui.cpp | 20 +++++++++++--------- imgui_draw.cpp | 4 ---- imgui_internal.h | 1 + 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0038d011c..77f630904 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -552,6 +552,7 @@ - shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus) !- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing - keyboard: full keyboard navigation and focus. (#323) + - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - input: rework IO system to be able to pass actual ordered/timestamped events. - input: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style). @@ -2371,6 +2372,7 @@ static void AddWindowToRenderList(ImVector& out_render_list, ImGuiW } } +// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) { ImGuiWindow* window = GetCurrentWindow(); @@ -4121,11 +4123,11 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); const float border_size = window->BorderSize; - ImRect clip_rect; - clip_rect.Min.x = title_bar_rect.Min.x + ImMax(border_size, (float)(int)(window->WindowPadding.x*0.5f)); - clip_rect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + border_size; - clip_rect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, (float)(int)(window->WindowPadding.x*0.5f)); - clip_rect.Max.y = window->Pos.y + window->Size.y - border_size - window->ScrollbarSizes.y; + ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size); + clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size); PushClipRect(clip_rect.Min, clip_rect.Max, true); // Clear 'accessed' flag last thing @@ -8426,7 +8428,7 @@ bool ImGui::BeginMenuBar() ImGui::BeginGroup(); // Save position ImGui::PushID("##menubar"); ImRect rect = window->MenuBarRect(); - PushClipRect(ImVec2(rect.Min.x, rect.Min.y + window->BorderSize), ImVec2(rect.Max.x, rect.Max.y), false); + PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false); window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.MenuBarAppending = true; @@ -8989,7 +8991,7 @@ float ImGui::GetColumnWidth(int column_index) if (column_index < 0) column_index = window->DC.ColumnsCurrent; - const float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index); + float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index); return w; } @@ -8999,8 +9001,8 @@ static void PushColumnClipRect(int column_index) if (column_index < 0) column_index = window->DC.ColumnsCurrent; - const float x1 = window->Pos.x + ImGui::GetColumnOffset(column_index) - 1; - const float x2 = window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1; + float x1 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index) - 1.0f); + float x2 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1.0f); ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true); } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e2eea92c8..da070b22d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -228,10 +228,6 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_ } cr.z = ImMax(cr.x, cr.z); cr.w = ImMax(cr.y, cr.w); - cr.x = (float)(int)(cr.x + 0.5f); // Round (expecting to round down). Ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. - cr.y = (float)(int)(cr.y + 0.5f); - cr.z = (float)(int)(cr.z + 0.5f); - cr.w = (float)(int)(cr.w + 0.5f); _ClipRectStack.push_back(cr); UpdateClipRect(); diff --git a/imgui_internal.h b/imgui_internal.h index eff7e27ba..41fb04f99 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -135,6 +135,7 @@ static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; } +static inline float ImFloor(float f) { return (float)(int)f; } static inline ImVec2 ImFloor(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. From bfb2dc22907f129a4a62c1ba3394ddecf00e57e5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Apr 2016 19:02:19 +0200 Subject: [PATCH 006/105] Examples: OpenGL3: Saving/restoring glActiveTexture() state (#602) --- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 2 ++ examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index b1d2a40b4..0e3a754cb 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -46,6 +46,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) // Backup GL state GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); @@ -111,6 +112,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) // Restore modified GL state glUseProgram(last_program); + glActiveTexture(last_active_texture); glBindTexture(GL_TEXTURE_2D, last_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 5406f424b..c3fed5f0b 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -40,6 +40,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) // Backup GL state GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); @@ -105,6 +106,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) // Restore modified GL state glUseProgram(last_program); + glActiveTexture(last_active_texture); glBindTexture(GL_TEXTURE_2D, last_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); From 60d6c6d0e8cb88828758ebe81830ef478be17673 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 11:46:49 +0200 Subject: [PATCH 007/105] Comments/tweaks on ItemAdd() --- imgui.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 77f630904..c6c4f04a0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1721,29 +1721,23 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) ImGuiWindow* window = GetCurrentWindow(); window->DC.LastItemID = id ? *id : 0; window->DC.LastItemRect = bb; + window->DC.LastItemHoveredAndUsable = false; + window->DC.LastItemHoveredRect = false; if (IsClippedEx(bb, id, false)) - { - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; return false; - } // This is a sensible default, but widgets are free to override it after calling ItemAdd() ImGuiState& g = *GImGui; if (IsMouseHoveringRect(bb.Min, bb.Max)) { - // Matching the behavior of IsHovered() but ignore if ActiveId==window->MoveID (we clicked on the window background) + // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) // So that clicking on items with no active id such as Text() still returns true with IsItemHovered() window->DC.LastItemHoveredRect = true; - window->DC.LastItemHoveredAndUsable = false; if (g.HoveredRootWindow == window->RootWindow) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveID)) if (IsWindowContentHoverable(window)) window->DC.LastItemHoveredAndUsable = true; } - else - { - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; - } return true; } @@ -1754,14 +1748,13 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when ImGuiWindow* window = GetCurrentWindowRead(); if (!bb.Overlaps(window->ClipRect)) - { if (!id || *id != GImGui->ActiveId) if (clip_even_when_logged || !g.LogEnabled) return true; - } return false; } +// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) { ImGuiState& g = *GImGui; From befe02559ac3de15d1ba3a41d0939696cf6330a0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 12:14:07 +0200 Subject: [PATCH 008/105] Added IsRootWindowOrAnyChildHovered() helper (#615) --- imgui.cpp | 12 ++++++++---- imgui.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c6c4f04a0..d15f3b015 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4579,15 +4579,19 @@ bool ImGui::IsWindowFocused() bool ImGui::IsRootWindowFocused() { ImGuiState& g = *GImGui; - ImGuiWindow* root_window = g.CurrentWindow->RootWindow; - return g.FocusedWindow == root_window; + return g.FocusedWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildFocused() { ImGuiState& g = *GImGui; - ImGuiWindow* root_window = g.CurrentWindow->RootWindow; - return g.FocusedWindow && g.FocusedWindow->RootWindow == root_window; + return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow; +} + +bool ImGui::IsRootWindowOrAnyChildHovered() +{ + ImGuiState& g = *GImGui; + return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow); } float ImGui::GetWindowWidth() diff --git a/imgui.h b/imgui.h index e093116ed..a451cea7a 100644 --- a/imgui.h +++ b/imgui.h @@ -385,8 +385,9 @@ namespace ImGui IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) IMGUI_API bool IsWindowFocused(); // is current window focused - IMGUI_API bool IsRootWindowFocused(); // is current root window focused (top parent window in case of child windows) + IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused + IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle of given size starting from cursor pos is visible (not clipped). to perform coarse clipping on user's side (as an optimization) IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window IMGUI_API float GetTime(); From df749e3f1357edf924f584710591749095fbfe2b Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 14:34:55 +0200 Subject: [PATCH 009/105] Added CollapsingHeader() variant with close button, obsoleted 4 parameters version. Refactored code into TreeNodeBehavior. (#600) New flag and declaration makes uses of SetNextTreeNode() functions on collapsing header more obvious as well (#579). --- imgui.cpp | 145 ++++++++++++++++++++++++++++------------------- imgui.h | 21 ++++++- imgui_demo.cpp | 17 ++++++ imgui_internal.h | 11 ++-- 4 files changed, 127 insertions(+), 67 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d15f3b015..f6b0742a9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -152,6 +152,7 @@ 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) @@ -5260,7 +5261,15 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } bool pressed = false; - const bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0); + bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0); + + // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. + if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + { + SetHoveredID(id); + hovered = false; + } + if (hovered) { SetHoveredID(id); @@ -5626,14 +5635,13 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags) // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). // NB- If we are above max depth we still allow manually opened nodes to be logged. - if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoExpandOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) + if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) opened = true; return opened; } -// FIXME: Split into CollapsingHeader(label, default_open?) and TreeNodeBehavior(label), obsolete the 4 parameters function. -bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open) +bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -5641,20 +5649,16 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display ImGuiState& g = *GImGui; const ImGuiStyle& style = g.Style; + const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); - IM_ASSERT(str_id != NULL || label != NULL); - if (str_id == NULL) - str_id = label; - if (label == NULL) - label = str_id; - const bool label_hide_text_after_double_hash = (label == str_id); // Only search and hide text after ## if we have passed label and ID separately, otherwise allow "##" within format string. - const ImGuiID id = window->GetID(str_id); - const ImVec2 label_size = CalcTextSize(label, NULL, label_hide_text_after_double_hash); + if (!label_end) + label_end = FindRenderedTextEnd(label); + const ImVec2 label_size = CalcTextSize(label, label_end, false); // We vertically grow up to current line height up the typical widget height. const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it - const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), label_size.y + padding.y*2); + const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); if (display_frame) { @@ -5670,12 +5674,15 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not) const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); - bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0)); + bool opened = TreeNodeBehaviorIsOpened(id, flags); if (!ItemAdd(interact_bb, &id)) + { + if (opened && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + TreePushRawID(id); return opened; + } - bool hovered, held; - bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, ImGuiButtonFlags_NoKeyModifiers); + bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0)); if (pressed) { opened = !opened; @@ -5696,12 +5703,12 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display const char log_prefix[] = "\n##"; const char log_suffix[] = "##"; LogRenderedText(text_pos, log_prefix, log_prefix+3); - RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size); + RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); LogRenderedText(text_pos, log_suffix+1, log_suffix+3); } else { - RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size); + RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); } } else @@ -5713,13 +5720,47 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false); if (g.LogEnabled) LogRenderedText(text_pos, ">"); - RenderText(text_pos, label, NULL, label_hide_text_after_double_hash); + RenderText(text_pos, label, label_end, false); + } + + if (opened && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + TreePushRawID(id); + return opened; +} + +bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label); +} + +bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + if (p_open && !*p_open) + return false; + + ImGuiID id = window->GetID(label); + bool opened = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); + if (p_open) + { + // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. + ImGuiState& g = *GImGui; + SetItemAllowOverlap(); + float button_sz = g.FontSize * 0.5f; + if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(window->DC.LastItemRect.Max.x - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) + *p_open = false; } return opened; } -// If returning 'true' the node is open and the user is responsible for calling TreePop bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); @@ -5727,30 +5768,10 @@ bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) return false; ImGuiState& g = *GImGui; - ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - if (!str_id || !str_id[0]) - str_id = fmt; - - ImGui::PushID(str_id); - const bool opened = ImGui::CollapsingHeader(g.TempBuffer, "", false); - ImGui::PopID(); - - if (opened) - ImGui::TreePush(str_id); - - return opened; + const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + return TreeNodeBehavior(window->GetID(str_id), 0, g.TempBuffer, label_end); } -bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool s = TreeNodeV(str_id, fmt, args); - va_end(args); - return s; -} - -// If returning 'true' the node is open and the user is responsible for calling TreePop bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); @@ -5758,18 +5779,16 @@ bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) return false; ImGuiState& g = *GImGui; - ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - - if (!ptr_id) - ptr_id = fmt; - - ImGui::PushID(ptr_id); - const bool opened = ImGui::CollapsingHeader(g.TempBuffer, "", false); - ImGui::PopID(); - - if (opened) - ImGui::TreePush(ptr_id); + const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + return TreeNodeBehavior(window->GetID(ptr_id ? ptr_id : fmt), 0, g.TempBuffer, label_end); +} +bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool opened = TreeNodeV(str_id, fmt, args); + va_end(args); return opened; } @@ -5777,14 +5796,18 @@ bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) { va_list args; va_start(args, fmt); - bool s = TreeNodeV(ptr_id, fmt, args); + bool opened = TreeNodeV(ptr_id, fmt, args); va_end(args); - return s; + return opened; } -bool ImGui::TreeNode(const char* str_label_id) +bool ImGui::TreeNode(const char* label) { - return TreeNode(str_label_id, "%s", str_label_id); + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + return TreeNodeBehavior(window->GetID(label), 0, label, NULL); } void ImGui::SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond) @@ -9127,6 +9150,14 @@ void ImGui::TreePush(const void* ptr_id) PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); } +void ImGui::TreePushRawID(ImGuiID id) +{ + ImGuiWindow* window = GetCurrentWindow(); + ImGui::Indent(); + window->DC.TreeDepth++; + window->IDStack.push_back(id); +} + void ImGui::TreePop() { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui.h b/imgui.h index a451cea7a..6a46035be 100644 --- a/imgui.h +++ b/imgui.h @@ -70,6 +70,7 @@ typedef int ImGuiWindowFlags; // window flags for Begin*() // e typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_ typedef int ImGuiInputTextFlags; // flags for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ +typedef int ImGuiTreeNodeFlags; // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); // Others helpers at bottom of the file: @@ -251,7 +252,6 @@ namespace ImGui IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding - IMGUI_API bool CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false); IMGUI_API bool Checkbox(const char* label, bool* v); IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); IMGUI_API bool RadioButton(const char* label, bool active); @@ -307,15 +307,17 @@ 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: 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(). + IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // " IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // " IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // " - IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose + IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layout purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. + IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop(). + IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height @@ -441,6 +443,7 @@ namespace ImGui // Obsolete (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + static inline bool CollapsingHeader(const char* label, const char* str_id, bool display_frame = true, bool default_open = false) { (void)str_id; (void)display_frame; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ static inline void OpenNextNode(bool open) { ImGui::SetNextTreeNodeOpened(open, 0); } // OBSOLETE 1.34+ @@ -512,6 +515,18 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; +// Flags for ImGui::TreeNode*(), ImGui::CollapsingHeader*() +enum ImGuiTreeNodeFlags_ +{ + ImGuiTreeNodeFlags_Selected = 1 << 0, + ImGuiTreeNodeFlags_Framed = 1 << 1, + ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, + ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, + ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, + ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, + ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog, +}; + // Flags for ImGui::Selectable() enum ImGuiSelectableFlags_ { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index cf6cf21bc..ac88f842c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -284,6 +284,23 @@ void ImGui::ShowTestWindow(bool* p_opened) ImGui::TreePop(); } + if (ImGui::TreeNode("Collapsing Headers")) + { + static bool closable_group = true; + if (ImGui::CollapsingHeader("Header")) + { + ImGui::Checkbox("Enable extra group", &closable_group); + for (int i = 0; i < 5; i++) + ImGui::Text("Some content %d", i); + } + if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) + { + for (int i = 0; i < 5; i++) + ImGui::Text("More content %d", i); + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Bullets")) { ImGui::BulletText("Bullet point 1"); diff --git a/imgui_internal.h b/imgui_internal.h index 41fb04f99..d099d3b7d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -161,13 +161,8 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_DontClosePopups = 1 << 5, // disable automatically closing parent popup on press ImGuiButtonFlags_Disabled = 1 << 6, // disable interaction ImGuiButtonFlags_AlignTextBaseLine = 1 << 7, // vertically align button to match text baseline - ButtonEx() only - ImGuiButtonFlags_NoKeyModifiers = 1 << 8 // disable interaction if a key modifier is held -}; - -enum ImGuiTreeNodeFlags_ -{ - ImGuiTreeNodeFlags_DefaultOpen = 1 << 0, - ImGuiTreeNodeFlags_NoAutoExpandOnLog = 1 << 1 + ImGuiButtonFlags_NoKeyModifiers = 1 << 8, // disable interaction if a key modifier is held + ImGuiButtonFlags_AllowOverlapMode = 1 << 9 // require previous frame HoveredId to either match id or be null before being usable }; enum ImGuiSliderFlags_ @@ -730,7 +725,9 @@ namespace ImGui IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); + IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging + IMGUI_API void TreePushRawID(ImGuiID id); IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); From ab6bc05fc34c9249393b85788b088c4bc20ded29 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 15:44:50 +0200 Subject: [PATCH 010/105] Fixed ImGuiTreeNodeFlags_AllowOverlapMode to behave better on touch-style inputs (#600) --- imgui.cpp | 15 ++++++--------- imgui.h | 14 +++++++------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f6b0742a9..47ecc56d4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5262,14 +5262,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool bool pressed = false; bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0); - - // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) - { - SetHoveredID(id); - hovered = false; - } - if (hovered) { SetHoveredID(id); @@ -5319,6 +5311,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } } + // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. + if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + hovered = pressed = held = false; + if (out_hovered) *out_hovered = hovered; if (out_held) *out_held = held; @@ -5688,6 +5684,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l opened = !opened; window->DC.StateStorage->SetInt(id, opened); } + if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) + SetItemAllowOverlap(); // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); @@ -5752,7 +5750,6 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. ImGuiState& g = *GImGui; - SetItemAllowOverlap(); float button_sz = g.FontSize * 0.5f; if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(window->DC.LastItemRect.Max.x - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) *p_open = false; diff --git a/imgui.h b/imgui.h index 6a46035be..953d1f654 100644 --- a/imgui.h +++ b/imgui.h @@ -518,13 +518,13 @@ enum ImGuiInputTextFlags_ // Flags for ImGui::TreeNode*(), ImGui::CollapsingHeader*() enum ImGuiTreeNodeFlags_ { - ImGuiTreeNodeFlags_Selected = 1 << 0, - ImGuiTreeNodeFlags_Framed = 1 << 1, - ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, - ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, - ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, - ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, - ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog, + ImGuiTreeNodeFlags_Selected = 1 << 0, // FIXME: TODO + ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) + ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one + ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack + ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes). + ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened + ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; // Flags for ImGui::Selectable() From ec6471ca87c64e70cbd984265eeedfdf2076d34b Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 16:06:46 +0200 Subject: [PATCH 011/105] TreeNodeEx() wired the display-side ImGuiTreeNodeFlags_Selected flag (#581) --- imgui.cpp | 2 +- imgui.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 47ecc56d4..7aff89cc9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5712,7 +5712,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l else { // Unframed typed for tree nodes - if (hovered) + if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) RenderFrame(bb.Min, bb.Max, col, false); RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false); diff --git a/imgui.h b/imgui.h index 953d1f654..11b63b8fd 100644 --- a/imgui.h +++ b/imgui.h @@ -518,7 +518,7 @@ enum ImGuiInputTextFlags_ // Flags for ImGui::TreeNode*(), ImGui::CollapsingHeader*() enum ImGuiTreeNodeFlags_ { - ImGuiTreeNodeFlags_Selected = 1 << 0, // FIXME: TODO + ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack From ac501102fc7524433c2343f2fa2cc47ea08f548e Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 17:43:17 +0200 Subject: [PATCH 012/105] Added IsItemClicked() helper (#581) --- imgui.cpp | 8 ++++++-- imgui.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7aff89cc9..0c7ef495e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1722,8 +1722,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) ImGuiWindow* window = GetCurrentWindow(); window->DC.LastItemID = id ? *id : 0; window->DC.LastItemRect = bb; - window->DC.LastItemHoveredAndUsable = false; - window->DC.LastItemHoveredRect = false; + window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; if (IsClippedEx(bb, id, false)) return false; @@ -3056,6 +3055,11 @@ bool ImGui::IsItemActive() return false; } +bool ImGui::IsItemClicked(int mouse_button) +{ + return IsMouseClicked(mouse_button) && IsItemHovered(); +} + bool ImGui::IsAnyItemHovered() { return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0; diff --git a/imgui.h b/imgui.h index 11b63b8fd..7e0d9b547 100644 --- a/imgui.h +++ b/imgui.h @@ -378,6 +378,7 @@ namespace ImGui IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) + IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); IMGUI_API bool IsAnyItemActive(); From 547f34cf22640526b63f02f50c73ef9409e8acab Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 17:43:51 +0200 Subject: [PATCH 013/105] Refactor ButtonBehavior(), fixed double-click mode also triggering on single-click (relate to #516) --- imgui.cpp | 40 ++++++++++++++++++++-------------------- imgui_internal.h | 19 ++++++++++--------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0c7ef495e..aced3a995 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5264,6 +5264,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool return false; } + if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) + flags |= ImGuiButtonFlags_PressedOnClickRelease; + bool pressed = false; bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0); if (hovered) @@ -5271,32 +5274,29 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool SetHoveredID(id); if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { - if (g.IO.MouseDoubleClicked[0] && (flags & ImGuiButtonFlags_PressedOnDoubleClick)) + if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) // Most common type { - pressed = true; - } - else if (g.IO.MouseClicked[0]) - { - if (flags & ImGuiButtonFlags_PressedOnClick) - { - pressed = true; - SetActiveID(0); - } - else - { - SetActiveID(id, window); - } + SetActiveID(id, window); // Hold on ID FocusWindow(window); } - else if (g.IO.MouseReleased[0] && (flags & ImGuiButtonFlags_PressedOnRelease)) + if ((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) + { + pressed = true; + SetActiveID(0); + FocusWindow(window); + } + if ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]) + { + pressed = true; + FocusWindow(window); + } + if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) { pressed = true; SetActiveID(0); } - else if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && ImGui::IsMouseClicked(0, true)) - { + if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && ImGui::IsMouseClicked(0, true)) pressed = true; - } } } @@ -5309,7 +5309,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } else { - if (hovered) + if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) pressed = true; SetActiveID(0); } @@ -8242,7 +8242,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick; if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnClick|ImGuiButtonFlags_PressedOnRelease; if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; - if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick; + if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; bool hovered, held; bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, button_flags); if (flags & ImGuiSelectableFlags_Disabled) diff --git a/imgui_internal.h b/imgui_internal.h index d099d3b7d..db4b9ccda 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -154,15 +154,16 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {} enum ImGuiButtonFlags_ { ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat - ImGuiButtonFlags_PressedOnClick = 1 << 1, // return pressed on click (default requires click+release) - ImGuiButtonFlags_PressedOnRelease = 1 << 2, // return pressed on release (default requires click+release) - ImGuiButtonFlags_PressedOnDoubleClick = 1 << 3, // return pressed on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChilds = 1 << 4, // allow interaction even if a child window is overlapping - ImGuiButtonFlags_DontClosePopups = 1 << 5, // disable automatically closing parent popup on press - ImGuiButtonFlags_Disabled = 1 << 6, // disable interaction - ImGuiButtonFlags_AlignTextBaseLine = 1 << 7, // vertically align button to match text baseline - ButtonEx() only - ImGuiButtonFlags_NoKeyModifiers = 1 << 8, // disable interaction if a key modifier is held - ImGuiButtonFlags_AllowOverlapMode = 1 << 9 // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set) + ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release) + ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release) + ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release) + ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping + ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press + ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction + ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only + ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held + ImGuiButtonFlags_AllowOverlapMode = 1 << 10 // require previous frame HoveredId to either match id or be null before being usable }; enum ImGuiSliderFlags_ From a38fd2e186e59973d7a778bb4bbd434f2f5dbddf Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 17:45:31 +0200 Subject: [PATCH 014/105] Added TreeNodeEx() functions (#581, #600, #190) --- imgui.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++---------- imgui.h | 5 +++++ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index aced3a995..59b05e744 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5762,7 +5762,16 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags return opened; } -bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) +bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + return TreeNodeBehavior(window->GetID(label), flags, label, NULL); +} + +bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -5770,25 +5779,53 @@ bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) ImGuiState& g = *GImGui; const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - return TreeNodeBehavior(window->GetID(str_id), 0, g.TempBuffer, label_end); + return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end); +} + +bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiState& g = *GImGui; + const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end); +} + +bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) +{ + return TreeNodeExV(str_id, 0, fmt, args); } bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) { - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; + return TreeNodeExV(ptr_id, 0, fmt, args); +} - ImGuiState& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - return TreeNodeBehavior(window->GetID(ptr_id ? ptr_id : fmt), 0, g.TempBuffer, label_end); +bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool opened = TreeNodeExV(str_id, flags, fmt, args); + va_end(args); + return opened; +} + +bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool opened = TreeNodeExV(ptr_id, flags, fmt, args); + va_end(args); + return opened; } bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) { va_list args; va_start(args, fmt); - bool opened = TreeNodeV(str_id, fmt, args); + bool opened = TreeNodeExV(str_id, 0, fmt, args); va_end(args); return opened; } @@ -5797,7 +5834,7 @@ bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) { va_list args; va_start(args, fmt); - bool opened = TreeNodeV(ptr_id, fmt, args); + bool opened = TreeNodeExV(ptr_id, 0, fmt, args); va_end(args); return opened; } diff --git a/imgui.h b/imgui.h index 7e0d9b547..66e1f5cfb 100644 --- a/imgui.h +++ b/imgui.h @@ -312,6 +312,11 @@ namespace ImGui IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // " IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // " IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // " + IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); + IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); + IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); + IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); + IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layout purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); From 4c880b7106d79309fa6d0cdf065e4131431ce6ee Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 17:46:08 +0200 Subject: [PATCH 015/105] Added ImGuiTreeNodeFlags_OpenOnDoubleClick (#581, #516, #190) --- imgui.cpp | 3 ++- imgui.h | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 59b05e744..d9b970e05 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5682,7 +5682,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l return opened; } - bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0)); + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0) | ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) ? ImGuiButtonFlags_PressedOnDoubleClick : 0); + bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); if (pressed) { opened = !opened; diff --git a/imgui.h b/imgui.h index 66e1f5cfb..ae02c90ee 100644 --- a/imgui.h +++ b/imgui.h @@ -530,6 +530,11 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes). ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened + ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Double-click to open node + //ImGuiTreeNodeFlags_OpenOnArrowOnly = 1 << 7, // FIXME: TODO: Can only click by + //ImGuiTreeNodeFlags_UnindentArrow = 1 << 8, // FIXME: TODO + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 9, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 10, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; From dc8446d048b0dc021e4d0a407e05185424902f73 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 17:55:04 +0200 Subject: [PATCH 016/105] Demo: Added simple tree node selection demo (#581, #516, #190) --- imgui.h | 4 ++-- imgui_demo.cpp | 43 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/imgui.h b/imgui.h index ae02c90ee..ce484f8d1 100644 --- a/imgui.h +++ b/imgui.h @@ -530,8 +530,8 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes). ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened - ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Double-click to open node - //ImGuiTreeNodeFlags_OpenOnArrowOnly = 1 << 7, // FIXME: TODO: Can only click by + ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node + //ImGuiTreeNodeFlags_OpenOnArrowOnly = 1 << 7, // FIXME: TODO //ImGuiTreeNodeFlags_UnindentArrow = 1 << 8, // FIXME: TODO //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 9, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 10, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ac88f842c..3a9df979b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -270,16 +270,45 @@ void ImGui::ShowTestWindow(bool* p_opened) { if (ImGui::TreeNode("Trees")) { - for (int i = 0; i < 5; i++) + if (ImGui::TreeNode("Basic trees")) { - if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) + for (int i = 0; i < 5; i++) + if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) + { + ImGui::Text("blah blah"); + ImGui::SameLine(); + if (ImGui::SmallButton("print")) printf("Child %d pressed", i); + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("With selectable nodes")) + { + ShowHelpMarker("Click to select, CTRL+Click to toggle, double-click to open"); + static int selection_mask = 0x02; // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. + int node_clicked = -1; + for (int i = 0; i < 5; i++) { - ImGui::Text("blah blah"); - ImGui::SameLine(); - if (ImGui::SmallButton("print")) - printf("Child %d pressed", i); - ImGui::TreePop(); + ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnDoubleClick; + bool opened = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Child %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; + if (opened) + { + ImGui::Text("blah blah"); + ImGui::TreePop(); + } } + if (node_clicked != -1) + { + // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. + if (ImGui::GetIO().KeyCtrl) + selection_mask ^= (1 << node_clicked); // CTRL+click to toggle + else + selection_mask = (1 << node_clicked); // Click to single-select + } + ImGui::TreePop(); } ImGui::TreePop(); } From 470b88e9659f3f4fc9f043507347a5b2d55b463f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 20:02:25 +0200 Subject: [PATCH 017/105] ButtonBehavior(): ImGuiButtonFlags_PressedOnDoubleClick clears active id on double-click so that multiple flags don't trigger multiple times --- imgui.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d9b970e05..f2015e62f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1762,7 +1762,7 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) { ImGuiWindow* window = GetCurrentWindowRead(); if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) - if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max)) + if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max)) if (IsWindowContentHoverable(g.HoveredRootWindow)) return true; } @@ -5279,17 +5279,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool SetActiveID(id, window); // Hold on ID FocusWindow(window); } - if ((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) + if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { pressed = true; SetActiveID(0); FocusWindow(window); } - if ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]) - { - pressed = true; - FocusWindow(window); - } if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) { pressed = true; From df764c21d6f82a54ce6c8cb5dffbf6839eb19a4c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 20:04:48 +0200 Subject: [PATCH 018/105] Bullet(), BulletText(): slightly bigger. less polygons --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f2015e62f..43f2c63e0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5915,8 +5915,8 @@ void ImGui::Bullet() } // Render - const float bullet_size = g.FontSize*0.15f; - window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text)); + const float bullet_size = g.FontSize*0.20f; + window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text), 8); // Stay on same line ImGui::SameLine(0, style.FramePadding.x*2); @@ -5943,8 +5943,8 @@ void ImGui::BulletTextV(const char* fmt, va_list args) return; // Render - const float bullet_size = g.FontSize*0.15f; - window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text)); + const float bullet_size = g.FontSize*0.20f; + window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text), 8); RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end); } From f79b2d6ce38e119e72a2a1a04a617f05be7ac802 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 20:12:14 +0200 Subject: [PATCH 019/105] TreeNode: added ImGuiTreeNodeFlags_OpenOnArrow flag (#581, #324, #190) --- imgui.cpp | 21 ++++++++++++++++++--- imgui.h | 11 ++++++----- imgui_demo.cpp | 8 ++++---- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 43f2c63e0..b632e398b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5677,12 +5677,27 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l return opened; } - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0) | ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) ? ImGuiButtonFlags_PressedOnDoubleClick : 0); + // Flags that affects opening behavior: + // - 0(default) ..................... single-click anywhere to open + // - OpenOnDoubleClick .............. double-click anywhere to open + // - OpenOnArrow .................... single-click on arrow to open + // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); + if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) + button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); if (pressed) { - opened = !opened; - window->DC.StateStorage->SetInt(id, opened); + bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); + if (flags & ImGuiTreeNodeFlags_OpenOnArrow) + toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + collapser_width, interact_bb.Max.y)); + if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) + toggled |= g.IO.MouseDoubleClicked[0]; + if (toggled) + { + opened = !opened; + window->DC.StateStorage->SetInt(id, opened); + } } if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) SetItemAllowOverlap(); diff --git a/imgui.h b/imgui.h index ce484f8d1..c82e1422d 100644 --- a/imgui.h +++ b/imgui.h @@ -528,13 +528,14 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack - ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes). + ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node - //ImGuiTreeNodeFlags_OpenOnArrowOnly = 1 << 7, // FIXME: TODO - //ImGuiTreeNodeFlags_UnindentArrow = 1 << 8, // FIXME: TODO - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 9, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 10, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible + ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. + //ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). + //ImGuiTreeNodeFlags_UnindentArrow = 1 << 9, // FIXME: TODO: Unindent tree so that Label is aligned to current X position + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3a9df979b..acdc0330c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -285,18 +285,18 @@ void ImGui::ShowTestWindow(bool* p_opened) if (ImGui::TreeNode("With selectable nodes")) { - ShowHelpMarker("Click to select, CTRL+Click to toggle, double-click to open"); + ShowHelpMarker("Click to select, CTRL+Click to toggle, click on arrows to open"); static int selection_mask = 0x02; // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. int node_clicked = -1; - for (int i = 0; i < 5; i++) + for (int i = 0; i < 6; i++) { - ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnDoubleClick; + ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; bool opened = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Child %d", i); if (ImGui::IsItemClicked()) node_clicked = i; if (opened) { - ImGui::Text("blah blah"); + ImGui::Text("Blah blah"); ImGui::TreePop(); } } From 9733f4fa244a11e096440676810156975e6a4483 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 20:19:28 +0200 Subject: [PATCH 020/105] Internal RenderBullet() helper. --- imgui.cpp | 18 ++++++++++-------- imgui_internal.h | 4 +++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b632e398b..00990ba52 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2741,6 +2741,12 @@ void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text)); } +void ImGui::RenderBullet(ImVec2 pos) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8); +} + void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) { ImGuiState& g = *GImGui; @@ -5929,12 +5935,9 @@ void ImGui::Bullet() return; } - // Render - const float bullet_size = g.FontSize*0.20f; - window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text), 8); - - // Stay on same line - ImGui::SameLine(0, style.FramePadding.x*2); + // Render and stay on same line + RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); + SameLine(0, style.FramePadding.x*2); } // Text with a little bullet aligned to the typical tree node. @@ -5958,8 +5961,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) return; // Render - const float bullet_size = g.FontSize*0.20f; - window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text), 8); + RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end); } diff --git a/imgui_internal.h b/imgui_internal.h index db4b9ccda..0ef0b8478 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -699,12 +699,14 @@ namespace ImGui inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); } // NB: All position are in absolute pixels coordinates (not window coordinates) - // FIXME: Refactor all RenderText* functions into one. + // FIXME: All those functions are a mess and needs to be refactored into something decent. Avoid use outside of imgui.cpp! + // We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers. IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool opened, float scale = 1.0f, bool shadow = false); + IMGUI_API void RenderBullet(ImVec2 pos); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. From bb674ccee6d1539dbb4c6f01eb4b22042c3f38cc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 21:15:46 +0200 Subject: [PATCH 021/105] TreeNode: added ImGuiTreeNodeFlags_AlwaysOpen flag (#581, #324) --- imgui.cpp | 10 ++++++++-- imgui.h | 4 ++-- imgui_demo.cpp | 5 ++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 00990ba52..95bb2aa2e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5600,6 +5600,9 @@ void ImGui::LogButtons() bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags) { + if (flags & ImGuiTreeNodeFlags_AlwaysOpen) + return true; + // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) ImGuiState& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -5692,7 +5695,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - if (pressed) + if (pressed && !(flags & ImGuiTreeNodeFlags_AlwaysOpen)) { bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) @@ -5736,7 +5739,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) RenderFrame(bb.Min, bb.Max, col, false); - RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false); + if (flags & ImGuiTreeNodeFlags_AlwaysOpen) + RenderBullet(bb.Min + ImVec2((padding.x + collapser_width) * 0.5f, g.FontSize*0.50f + text_base_offset_y)); + else + RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false); if (g.LogEnabled) LogRenderedText(text_pos, ">"); RenderText(text_pos, label, label_end, false); diff --git a/imgui.h b/imgui.h index c82e1422d..dd3c9fbfd 100644 --- a/imgui.h +++ b/imgui.h @@ -532,7 +532,7 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. - //ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). + ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). //ImGuiTreeNodeFlags_UnindentArrow = 1 << 9, // FIXME: TODO: Unindent tree so that Label is aligned to current X position //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible @@ -695,7 +695,7 @@ 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! - float IndentSpacing; // Horizontal indentation when e.g. entering a tree node + float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2) float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar float ScrollbarRounding; // Radius of grab corners for scrollbar diff --git a/imgui_demo.cpp b/imgui_demo.cpp index acdc0330c..92e883a1b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -291,11 +291,14 @@ void ImGui::ShowTestWindow(bool* p_opened) for (int i = 0; i < 6; i++) { ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; - bool opened = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Child %d", i); + if (i >= 3) + node_flags |= ImGuiTreeNodeFlags_AlwaysOpen; + bool opened = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable %s %d", (i >= 3) ? "Leaf" : "Node", i); if (ImGui::IsItemClicked()) node_clicked = i; if (opened) { + ImGui::Text("Blah blah"); ImGui::Text("Blah blah"); ImGui::TreePop(); } From b93040e600a6788f73443cfb49a10f0382025977 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 23:46:48 +0200 Subject: [PATCH 022/105] TreeNode: minor tidying up (#581, #324) --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 95bb2aa2e..b4fa6c0d5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5671,7 +5671,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; } - const float collapser_width = g.FontSize + (display_frame ? padding.x*2 : padding.x); + const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); @@ -5699,7 +5699,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + collapser_width, interact_bb.Max.y)); + toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) toggled |= g.IO.MouseDoubleClicked[0]; if (toggled) @@ -5713,7 +5713,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - const ImVec2 text_pos = bb.Min + padding + ImVec2(collapser_width, text_base_offset_y); + const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, padding.y + text_base_offset_y); if (display_frame) { // Framed type @@ -5740,7 +5740,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l RenderFrame(bb.Min, bb.Max, col, false); if (flags & ImGuiTreeNodeFlags_AlwaysOpen) - RenderBullet(bb.Min + ImVec2((padding.x + collapser_width) * 0.5f, g.FontSize*0.50f + text_base_offset_y)); + RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); else RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false); if (g.LogEnabled) From 13df4668d1573cd887798157b3904762c0175b09 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 23:47:58 +0200 Subject: [PATCH 023/105] Added GetTreeNodeToLabelSpacing() helper - tentative name (#581, #324) --- imgui.cpp | 11 +++++++++++ imgui.h | 1 + 2 files changed, 12 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index b4fa6c0d5..b1ffa3e36 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5871,6 +5871,17 @@ bool ImGui::TreeNode(const char* label) return TreeNodeBehavior(window->GetID(label), 0, label, NULL); } +float ImGui::GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags) +{ + ImGuiState& g = *GImGui; + float off_from_start; + if (flags & ImGuiTreeNodeFlags_Framed) + off_from_start = g.FontSize + (g.Style.FramePadding.x * 3.0f) - ((float)(int)(g.CurrentWindow->WindowPadding.x*0.5f) - 1); + else + off_from_start = g.FontSize + (g.Style.FramePadding.x * 2.0f); + return off_from_start; +} + void ImGui::SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond) { ImGuiState& g = *GImGui; diff --git a/imgui.h b/imgui.h index dd3c9fbfd..0b76157b9 100644 --- a/imgui.h +++ b/imgui.h @@ -321,6 +321,7 @@ namespace ImGui IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. + IMGUI_API float GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags = 0); // return horizontal distance between cursor and text label due to collapsing node. == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header From 4170b4847d628c7116228a853eed3ae55493cc69 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 1 May 2016 23:49:10 +0200 Subject: [PATCH 024/105] Style: Changed default IndentSpacing from 22 to 21 (#581, #324) --- imgui.cpp | 2 +- imgui.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b1ffa3e36..fad187b43 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -708,7 +708,7 @@ 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! - IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node + IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar diff --git a/imgui.h b/imgui.h index 0b76157b9..5258a5b9e 100644 --- a/imgui.h +++ b/imgui.h @@ -696,7 +696,7 @@ 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! - float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2) + float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar float ScrollbarRounding; // Radius of grab corners for scrollbar From 4f34ed5010ce2350ebb27379281ca8471b4a7abe Mon Sep 17 00:00:00 2001 From: Anton Holmberg Date: Sun, 1 May 2016 16:18:31 -0700 Subject: [PATCH 025/105] Fix typo in Programmer guide --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index fad187b43..97a935ecb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -78,7 +78,7 @@ - read the FAQ below this section! - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. - call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - - see examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first at it is the simplest. + - see examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first as it is the simplest. you may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme). From 89d50261873504c96ce2e10bd53d26c61c5c67e3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 2 May 2016 12:32:16 +0200 Subject: [PATCH 026/105] Renamed majority of use of "opened" to "open" for clarity. Renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(). (#625, #579) --- imgui.cpp | 235 ++++++++++++++++++++++++----------------------- imgui.h | 30 +++--- imgui_demo.cpp | 86 ++++++++--------- imgui_internal.h | 14 +-- 4 files changed, 183 insertions(+), 182 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 97a935ecb..70649fdbf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -53,7 +53,7 @@ ============== - double-click title bar to collapse window - - click upper right corner to close a window, available when 'bool* p_opened' is passed to ImGui::Begin() + - click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin() - click and drag on lower right corner to resize window - click and drag on any empty space to move window - double-click/double-tap on lower right corner grip to auto-fit to content @@ -152,6 +152,7 @@ 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). @@ -196,7 +197,7 @@ - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete). - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. - - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "opened" state of a popup. BeginPopup() returns true if the popup is opened. + - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened. - 2015/05/03 (1.40) - 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 @@ -365,7 +366,7 @@ TreePop(); } - - When working with trees, ID are used to preserve the opened/closed state of each tree node. + - When working with trees, ID are used to preserve the open/close state of each tree node. Depending on your use cases you may want to use strings, indices or pointers as ID. 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! @@ -444,7 +445,7 @@ - window: background options for child windows, border option (disable rounding) - window: add a way to clear an existing window instead of appending (e.g. for tooltip override using a consistent api rather than the deferred tooltip) - window: resizing from any sides? + mouse cursor directives for app. -!- window: begin with *p_opened == false should return false. +!- window: begin with *p_open == false should return false. - window: get size/pos helpers given names (see discussion in #249) - window: a collapsed window can be stuck behind the main menu bar? - window: when window is small, prioritize resize button over close button. @@ -2032,7 +2033,7 @@ void ImGui::NewFrame() for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) { if (g.IO.MouseClicked[i]) - g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenedPopupStack.empty()); + g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); mouse_any_down |= g.IO.MouseDown[i]; if (g.IO.MouseDown[i]) if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i]) @@ -2042,7 +2043,7 @@ void ImGui::NewFrame() if (g.CaptureMouseNextFrame != -1) g.IO.WantCaptureMouse = (g.CaptureMouseNextFrame != 0); else - g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenedPopupStack.empty()); + g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty()); g.IO.WantCaptureKeyboard = (g.CaptureKeyboardNextFrame != -1) ? (g.CaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); g.MouseCursor = ImGuiMouseCursor_Arrow; @@ -2141,7 +2142,7 @@ void ImGui::Shutdown() g.ColorModifiers.clear(); g.StyleModifiers.clear(); g.FontStack.clear(); - g.OpenedPopupStack.clear(); + g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].clear(); @@ -2712,7 +2713,7 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, } // Render a triangle to denote expanded/collapsed state -void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool shadow) +void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale, bool shadow) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -2722,7 +2723,7 @@ void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale); ImVec2 a, b, c; - if (opened) + if (is_open) { center.y -= r*0.25f; a = center + ImVec2(0,1)*r; @@ -2994,7 +2995,7 @@ ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() { ImGuiState& g = *GImGui; if (g.CurrentPopupStack.Size > 0) - return g.OpenedPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; + return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; return g.IO.MousePos; } @@ -3157,8 +3158,8 @@ void ImGui::EndTooltip() static bool IsPopupOpen(ImGuiID id) { ImGuiState& g = *GImGui; - const bool opened = g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].PopupID == id; - return opened; + const bool is_open = g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupID == id; + return is_open; } // Mark popup as open (toggle toward open state). @@ -3172,12 +3173,12 @@ void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) ImGuiID id = window->GetID(str_id); int current_stack_size = g.CurrentPopupStack.Size; ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) - if (g.OpenedPopupStack.Size < current_stack_size + 1) - g.OpenedPopupStack.push_back(popup_ref); - else if (reopen_existing || g.OpenedPopupStack[current_stack_size].PopupID != id) + if (g.OpenPopupStack.Size < current_stack_size + 1) + g.OpenPopupStack.push_back(popup_ref); + else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupID != id) { - g.OpenedPopupStack.resize(current_stack_size+1); - g.OpenedPopupStack[current_stack_size] = popup_ref; + g.OpenPopupStack.resize(current_stack_size+1); + g.OpenPopupStack[current_stack_size] = popup_ref; } } @@ -3189,7 +3190,7 @@ void ImGui::OpenPopup(const char* str_id) static void CloseInactivePopups() { ImGuiState& g = *GImGui; - if (g.OpenedPopupStack.empty()) + if (g.OpenPopupStack.empty()) return; // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. @@ -3197,9 +3198,9 @@ static void CloseInactivePopups() int n = 0; if (g.FocusedWindow) { - for (n = 0; n < g.OpenedPopupStack.Size; n++) + for (n = 0; n < g.OpenPopupStack.Size; n++) { - ImGuiPopupRef& popup = g.OpenedPopupStack[n]; + ImGuiPopupRef& popup = g.OpenPopupStack[n]; if (!popup.Window) continue; IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); @@ -3207,21 +3208,21 @@ static void CloseInactivePopups() continue; bool has_focus = false; - for (int m = n; m < g.OpenedPopupStack.Size && !has_focus; m++) - has_focus = (g.OpenedPopupStack[m].Window && g.OpenedPopupStack[m].Window->RootWindow == g.FocusedWindow->RootWindow); + for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) + has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.FocusedWindow->RootWindow); if (!has_focus) break; } } - if (n < g.OpenedPopupStack.Size) // This test is not required but it allows to set a useful breakpoint on the line below - g.OpenedPopupStack.resize(n); + if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a useful breakpoint on the line below + g.OpenPopupStack.resize(n); } static ImGuiWindow* GetFrontMostModalRootWindow() { ImGuiState& g = *GImGui; - for (int n = g.OpenedPopupStack.Size-1; n >= 0; n--) - if (ImGuiWindow* front_most_popup = g.OpenedPopupStack.Data[n].Window) + for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) + if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window) if (front_most_popup->Flags & ImGuiWindowFlags_Modal) return front_most_popup; return NULL; @@ -3231,10 +3232,10 @@ static void ClosePopupToLevel(int remaining) { ImGuiState& g = *GImGui; if (remaining > 0) - ImGui::FocusWindow(g.OpenedPopupStack[remaining-1].Window); + ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window); else - ImGui::FocusWindow(g.OpenedPopupStack[0].ParentWindow); - g.OpenedPopupStack.resize(remaining); + ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow); + g.OpenPopupStack.resize(remaining); } static void ClosePopup(ImGuiID id) @@ -3242,7 +3243,7 @@ static void ClosePopup(ImGuiID id) if (!IsPopupOpen(id)) return; ImGuiState& g = *GImGui; - ClosePopupToLevel(g.OpenedPopupStack.Size - 1); + ClosePopupToLevel(g.OpenPopupStack.Size - 1); } // Close the popup we have begin-ed into. @@ -3250,9 +3251,9 @@ void ImGui::CloseCurrentPopup() { ImGuiState& g = *GImGui; int popup_idx = g.CurrentPopupStack.Size - 1; - if (popup_idx < 0 || popup_idx > g.OpenedPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupID != g.OpenedPopupStack[popup_idx].PopupID) + if (popup_idx < 0 || popup_idx > g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupID != g.OpenPopupStack[popup_idx].PopupID) return; - while (popup_idx > 0 && g.OpenedPopupStack[popup_idx].Window && (g.OpenedPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) + while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) popup_idx--; ClosePopupToLevel(popup_idx); } @@ -3284,18 +3285,18 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) else ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - bool opened = ImGui::Begin(name, NULL, flags); + bool is_open = ImGui::Begin(name, NULL, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; - if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) + if (!is_open) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) ImGui::EndPopup(); - return opened; + return is_open; } bool ImGui::BeginPopup(const char* str_id) { - if (GImGui->OpenedPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance + if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance { ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; @@ -3303,7 +3304,7 @@ bool ImGui::BeginPopup(const char* str_id) return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders); } -bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags extra_flags) +bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags) { ImGuiState& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -3315,16 +3316,16 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags e } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, p_opened, flags); - if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) + bool is_open = ImGui::Begin(name, p_open, flags); + if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); - if (opened) + if (is_open) ClosePopup(id); return false; } - return opened; + return is_open; } void ImGui::EndPopup() @@ -3583,14 +3584,14 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). // You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. -// - Passing 'bool* p_opened' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. +// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. // - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiSetCond_FirstUseEver) prior to calling Begin(). -bool ImGui::Begin(const char* name, bool* p_opened, ImGuiWindowFlags flags) +bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { - return ImGui::Begin(name, p_opened, ImVec2(0.f, 0.f), -1.0f, flags); + return ImGui::Begin(name, p_open, ImVec2(0.f, 0.f), -1.0f, flags); } -bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) +bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) { ImGuiState& g = *GImGui; const ImGuiStyle& style = g.Style; @@ -3627,7 +3628,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ bool window_was_active = (window->LastFrameActive == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) { - ImGuiPopupRef& popup_ref = g.OpenedPopupStack[g.CurrentPopupStack.Size]; + ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; window_was_active &= (window->PopupID == popup_ref.PopupID); window_was_active &= (window == popup_ref.Window); popup_ref.Window = window; @@ -4085,12 +4086,12 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) { - if (p_opened != NULL) + if (p_open != NULL) { const float pad = 2.0f; const float rad = (window->TitleBarHeight() - pad*2.0f) * 0.5f; if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad)) - *p_opened = false; + *p_open = false; } const ImVec2 text_size = CalcTextSize(name, NULL, true); @@ -4099,9 +4100,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ 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() + ImVec2 clip_max = ImVec2(window->Pos.x + window->Size.x - (p_open ? 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); + bool pad_right = (p_open != 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; @@ -5598,7 +5599,7 @@ void ImGui::LogButtons() LogToClipboard(g.LogAutoExpandMaxDepth); } -bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags) +bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { if (flags & ImGuiTreeNodeFlags_AlwaysOpen) return true; @@ -5608,13 +5609,13 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags) ImGuiWindow* window = g.CurrentWindow; ImGuiStorage* storage = window->DC.StateStorage; - bool opened; - if (g.SetNextTreeNodeOpenedCond != 0) + bool is_open; + if (g.SetNextTreeNodeOpenCond != 0) { - if (g.SetNextTreeNodeOpenedCond & ImGuiSetCond_Always) + if (g.SetNextTreeNodeOpenCond & ImGuiSetCond_Always) { - opened = g.SetNextTreeNodeOpenedVal; - storage->SetInt(id, opened); + is_open = g.SetNextTreeNodeOpenVal; + storage->SetInt(id, is_open); } else { @@ -5622,27 +5623,27 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags) const int stored_value = storage->GetInt(id, -1); if (stored_value == -1) { - opened = g.SetNextTreeNodeOpenedVal; - storage->SetInt(id, opened); + is_open = g.SetNextTreeNodeOpenVal; + storage->SetInt(id, is_open); } else { - opened = stored_value != 0; + is_open = stored_value != 0; } } - g.SetNextTreeNodeOpenedCond = 0; + g.SetNextTreeNodeOpenCond = 0; } else { - opened = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; + is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; } // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). // NB- If we are above max depth we still allow manually opened nodes to be logged. if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) - opened = true; + is_open = true; - return opened; + return is_open; } bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) @@ -5678,12 +5679,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not) const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); - bool opened = TreeNodeBehaviorIsOpened(id, flags); + bool is_open = TreeNodeBehaviorIsOpen(id, flags); if (!ItemAdd(interact_bb, &id)) { - if (opened && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); - return opened; + return is_open; } // Flags that affects opening behavior: @@ -5704,8 +5705,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l toggled |= g.IO.MouseDoubleClicked[0]; if (toggled) { - opened = !opened; - window->DC.StateStorage->SetInt(id, opened); + is_open = !is_open; + window->DC.StateStorage->SetInt(id, is_open); } } if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) @@ -5718,7 +5719,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { // Framed type RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), opened, 1.0f, true); + RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f, true); if (g.LogEnabled) { // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. @@ -5742,15 +5743,15 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (flags & ImGuiTreeNodeFlags_AlwaysOpen) RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); else - RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false); + RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f, false); if (g.LogEnabled) LogRenderedText(text_pos, ">"); RenderText(text_pos, label, label_end, false); } - if (opened && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); - return opened; + return is_open; } bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) @@ -5772,7 +5773,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags return false; ImGuiID id = window->GetID(label); - bool opened = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); + bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); if (p_open) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. @@ -5782,7 +5783,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags *p_open = false; } - return opened; + return is_open; } bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) @@ -5830,36 +5831,36 @@ bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* { va_list args; va_start(args, fmt); - bool opened = TreeNodeExV(str_id, flags, fmt, args); + bool is_open = TreeNodeExV(str_id, flags, fmt, args); va_end(args); - return opened; + return is_open; } bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) { va_list args; va_start(args, fmt); - bool opened = TreeNodeExV(ptr_id, flags, fmt, args); + bool is_open = TreeNodeExV(ptr_id, flags, fmt, args); va_end(args); - return opened; + return is_open; } bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) { va_list args; va_start(args, fmt); - bool opened = TreeNodeExV(str_id, 0, fmt, args); + bool is_open = TreeNodeExV(str_id, 0, fmt, args); va_end(args); - return opened; + return is_open; } bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) { va_list args; va_start(args, fmt); - bool opened = TreeNodeExV(ptr_id, 0, fmt, args); + bool is_open = TreeNodeExV(ptr_id, 0, fmt, args); va_end(args); - return opened; + return is_open; } bool ImGui::TreeNode(const char* label) @@ -5882,11 +5883,11 @@ float ImGui::GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags) return off_from_start; } -void ImGui::SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond) +void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond) { ImGuiState& g = *GImGui; - g.SetNextTreeNodeOpenedVal = opened; - g.SetNextTreeNodeOpenedCond = cond ? cond : ImGuiSetCond_Always; + g.SetNextTreeNodeOpenVal = is_open; + g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::PushID(const char* str_id) @@ -8171,12 +8172,12 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f); const bool hovered = IsHovered(frame_bb, id); - bool popup_opened = IsPopupOpen(id); + bool popup_open = IsPopupOpen(id); bool popup_opened_now = false; const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_opened || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING + RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); if (*current_item >= 0 && *current_item < items_count) @@ -8203,7 +8204,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi { FocusWindow(window); OpenPopup(label); - popup_opened = popup_opened_now = true; + popup_open = popup_opened_now = true; } } } @@ -8555,9 +8556,9 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImGuiWindow* backed_focused_window = g.FocusedWindow; bool pressed; - bool opened = IsPopupOpen(id); - bool menuset_opened = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); - if (menuset_opened) + bool menu_is_open = IsPopupOpen(id); + bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); + if (menuset_is_open) g.FocusedWindow = window; ImVec2 popup_pos, pos = window->DC.CursorPos; @@ -8567,7 +8568,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); float w = label_size.x; - pressed = ImGui::Selectable(label, opened, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + pressed = ImGui::Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); ImGui::PopStyleVar(); ImGui::SameLine(); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); @@ -8577,14 +8578,14 @@ bool ImGui::BeginMenu(const char* label, bool enabled) popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame float extra_w = ImMax(0.0f, ImGui::GetContentRegionAvail().x - w); - pressed = ImGui::Selectable(label, opened, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + pressed = ImGui::Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); if (!enabled) ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); RenderCollapseTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), false); if (!enabled) ImGui::PopStyleColor(); } bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); - if (menuset_opened) + if (menuset_is_open) g.FocusedWindow = backed_focused_window; bool want_open = false, want_close = false; @@ -8592,9 +8593,9 @@ bool ImGui::BeginMenu(const char* label, bool enabled) { // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; - if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) + if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { - if (ImGuiWindow* next_window = g.OpenedPopupStack[g.CurrentPopupStack.Size].Window) + if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) { ImRect next_window_rect = next_window->Rect(); ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; @@ -8609,39 +8610,39 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } } - want_close = (opened && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); - want_open = (!opened && hovered && !moving_within_opened_triangle) || (!opened && hovered && pressed); + want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); + want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); } - else if (opened && pressed && menuset_opened) // menu-bar: click open menu to close + else if (menu_is_open && pressed && menuset_is_open) // menu-bar: click open menu to close { want_close = true; - want_open = opened = false; + want_open = menu_is_open = false; } - else if (pressed || (hovered && menuset_opened && !opened)) // menu-bar: first click to open, then hover to open others + else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others want_open = true; if (want_close && IsPopupOpen(id)) ClosePopupToLevel(GImGui->CurrentPopupStack.Size); - if (!opened && want_open && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size) + if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) { // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. ImGui::OpenPopup(label); return false; } - opened |= want_open; + menu_is_open |= want_open; if (want_open) ImGui::OpenPopup(label); - if (opened) + if (menu_is_open) { ImGui::SetNextWindowPos(popup_pos, ImGuiSetCond_Always); ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); - opened = BeginPopupEx(label, flags); // opened can be 'false' when the popup is completely clipped (e.g. zero size display) + menu_is_open = BeginPopupEx(label, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } - return opened; + return menu_is_open; } void ImGui::EndMenu() @@ -9399,9 +9400,9 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} // HELP //----------------------------------------------------------------------------- -void ImGui::ShowMetricsWindow(bool* opened) +void ImGui::ShowMetricsWindow(bool* p_open) { - if (ImGui::Begin("ImGui Metrics", opened)) + if (ImGui::Begin("ImGui Metrics", p_open)) { ImGui::Text("ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); @@ -9415,15 +9416,15 @@ void ImGui::ShowMetricsWindow(bool* opened) { static void NodeDrawList(ImDrawList* draw_list, const char* label) { - bool node_opened = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); + bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); if (draw_list == ImGui::GetWindowDrawList()) { ImGui::SameLine(); ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) - if (node_opened) ImGui::TreePop(); + if (node_open) ImGui::TreePop(); return; } - if (!node_opened) + if (!node_open) return; ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list @@ -9436,7 +9437,7 @@ void ImGui::ShowMetricsWindow(bool* opened) ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); continue; } - bool draw_opened = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + bool node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); if (show_clip_rects && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; @@ -9447,7 +9448,7 @@ void ImGui::ShowMetricsWindow(bool* opened) clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255)); } - if (!draw_opened) + if (!node_open) continue; for (int i = elem_offset; i+2 < elem_offset + (int)pcmd->ElemCount; i += 3) { @@ -9498,12 +9499,12 @@ void ImGui::ShowMetricsWindow(bool* opened) Funcs::NodeDrawList(g.RenderDrawLists[0][i], "DrawList"); ImGui::TreePop(); } - if (ImGui::TreeNode("Popups", "Opened Popups Stack (%d)", g.OpenedPopupStack.Size)) + if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) { - for (int i = 0; i < g.OpenedPopupStack.Size; i++) + for (int i = 0; i < g.OpenPopupStack.Size; i++) { - ImGuiWindow* window = g.OpenedPopupStack[i].Window; - ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenedPopupStack[i].PopupID, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); + ImGuiWindow* window = g.OpenPopupStack[i].Window; + ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupID, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); } ImGui::TreePop(); } diff --git a/imgui.h b/imgui.h index 5258a5b9e..eaf44b9e0 100644 --- a/imgui.h +++ b/imgui.h @@ -110,15 +110,15 @@ namespace ImGui IMGUI_API void Shutdown(); IMGUI_API void ShowUserGuide(); // help block IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // style editor block - IMGUI_API void ShowTestWindow(bool* opened = NULL); // test window demonstrating ImGui features - IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window for debugging ImGui + IMGUI_API void ShowTestWindow(bool* p_open = NULL); // test window demonstrating ImGui features + IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // metrics window for debugging ImGui // Window - IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. - IMGUI_API void End(); // finish appending to current window, pop it off the window stack. - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). - IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " + IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). + IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. + IMGUI_API void End(); // finish appending to current window, pop it off the window stack. + IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). + IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " IMGUI_API void EndChild(); IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() @@ -320,7 +320,7 @@ namespace ImGui IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layout purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); - IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. + IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. IMGUI_API float GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags = 0); // return horizontal distance between cursor and text label due to collapsing node. == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header @@ -360,15 +360,15 @@ namespace ImGui // Popups IMGUI_API void OpenPopup(const char* str_id); // mark popup as open. popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). - IMGUI_API bool BeginPopup(const char* str_id); // return true if popup if opened and start outputting to it. only call EndPopup() if BeginPopup() returned true! - IMGUI_API bool BeginPopupModal(const char* name, bool* p_opened = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (can't close them by clicking outside) + IMGUI_API bool BeginPopup(const char* str_id); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! + IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (can't close them by clicking outside) IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(bool also_over_items = true, const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on current window. IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (no window). IMGUI_API void EndPopup(); IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. - // Logging: all text output from interface is redirected to tty/file/clipboard. Tree nodes are automatically opened. + // Logging: all text output from interface is redirected to tty/file/clipboard. By default, tree nodes are automatically opened during logging. IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard @@ -453,7 +453,7 @@ namespace ImGui static inline bool CollapsingHeader(const char* label, const char* str_id, bool display_frame = true, bool default_open = false) { (void)str_id; (void)display_frame; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ - static inline void OpenNextNode(bool open) { ImGui::SetNextTreeNodeOpened(open, 0); } // OBSOLETE 1.34+ + static inline void OpenNextNode(bool open) { ImGui::SetNextTreeNodeOpen(open, 0); } // OBSOLETE 1.34+ static inline bool GetWindowIsFocused() { return ImGui::IsWindowFocused(); } // OBSOLETE 1.36+ static inline bool GetWindowCollapsed() { return ImGui::IsWindowCollapsed(); } // OBSOLETE 1.39+ static inline ImVec2 GetItemBoxMin() { return GetItemRectMin(); } // OBSOLETE 1.36+ @@ -528,15 +528,15 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one - ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack + ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) - ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened + ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). //ImGuiTreeNodeFlags_UnindentArrow = 1 << 9, // FIXME: TODO: Unindent tree so that Label is aligned to current X position //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 92e883a1b..979accc31 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -49,15 +49,15 @@ #ifndef IMGUI_DISABLE_TEST_WINDOWS -static void ShowExampleAppConsole(bool* opened); -static void ShowExampleAppLog(bool* opened); -static void ShowExampleAppLayout(bool* opened); -static void ShowExampleAppPropertyEditor(bool* opened); -static void ShowExampleAppLongText(bool* opened); -static void ShowExampleAppAutoResize(bool* opened); -static void ShowExampleAppFixedOverlay(bool* opened); -static void ShowExampleAppManipulatingWindowTitle(bool* opened); -static void ShowExampleAppCustomRendering(bool* opened); +static void ShowExampleAppConsole(bool* p_open); +static void ShowExampleAppLog(bool* p_open); +static void ShowExampleAppLayout(bool* p_open); +static void ShowExampleAppPropertyEditor(bool* p_open); +static void ShowExampleAppLongText(bool* p_open); +static void ShowExampleAppAutoResize(bool* p_open); +static void ShowExampleAppFixedOverlay(bool* p_open); +static void ShowExampleAppManipulatingWindowTitle(bool* p_open); +static void ShowExampleAppCustomRendering(bool* p_open); static void ShowExampleAppMainMenuBar(); static void ShowExampleMenuFile(); @@ -91,7 +91,7 @@ void ImGui::ShowUserGuide() } // Demonstrate most ImGui features (big function!) -void ImGui::ShowTestWindow(bool* p_opened) +void ImGui::ShowTestWindow(bool* p_open) { // Examples apps static bool show_app_main_menu_bar = false; @@ -150,7 +150,7 @@ void ImGui::ShowTestWindow(bool* p_opened) if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("ImGui Demo", p_opened, window_flags)) + if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) { // Early out if the window is collapsed, as an optimization. ImGui::End(); @@ -293,12 +293,12 @@ void ImGui::ShowTestWindow(bool* p_opened) ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; if (i >= 3) node_flags |= ImGuiTreeNodeFlags_AlwaysOpen; - bool opened = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable %s %d", (i >= 3) ? "Leaf" : "Node", i); + bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable %s %d", (i >= 3) ? "Leaf" : "Node", i); if (ImGui::IsItemClicked()) node_clicked = i; - if (opened) + if (node_open) { - ImGui::Text("Blah blah"); + ImGui::Text("Selectable Blah blah"); ImGui::Text("Blah blah"); ImGui::TreePop(); } @@ -1046,9 +1046,9 @@ void ImGui::ShowTestWindow(bool* p_opened) if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). - bool tree_opened = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. + bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); - if (tree_opened) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data // Bullet ImGui::Button("Button##3"); @@ -1437,9 +1437,9 @@ void ImGui::ShowTestWindow(bool* p_opened) ImGui::TreePop(); } - bool node_opened = ImGui::TreeNode("Tree within single cell"); + bool node_open = ImGui::TreeNode("Tree within single cell"); ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell."); - if (node_opened) + if (node_open) { ImGui::Columns(2, "tree items"); ImGui::Separator(); @@ -1766,9 +1766,9 @@ static void ShowExampleMenuFile() if (ImGui::MenuItem("Quit", "Alt+F4")) {} } -static void ShowExampleAppAutoResize(bool* opened) +static void ShowExampleAppAutoResize(bool* p_open) { - if (!ImGui::Begin("Example: Auto-resizing window", opened, ImGuiWindowFlags_AlwaysAutoResize)) + if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::End(); return; @@ -1782,10 +1782,10 @@ static void ShowExampleAppAutoResize(bool* opened) ImGui::End(); } -static void ShowExampleAppFixedOverlay(bool* opened) +static void ShowExampleAppFixedOverlay(bool* p_open) { ImGui::SetNextWindowPos(ImVec2(10,10)); - if (!ImGui::Begin("Example: Fixed Overlay", opened, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) + if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) { ImGui::End(); return; @@ -1796,9 +1796,9 @@ static void ShowExampleAppFixedOverlay(bool* opened) ImGui::End(); } -static void ShowExampleAppManipulatingWindowTitle(bool* opened) +static void ShowExampleAppManipulatingWindowTitle(bool* p_open) { - (void)opened; + (void)p_open; // By default, Windows are uniquely identified by their title. // You can use the "##" and "###" markers to manipulate the display/ID. Read FAQ at the top of this file! @@ -1823,10 +1823,10 @@ static void ShowExampleAppManipulatingWindowTitle(bool* opened) ImGui::End(); } -static void ShowExampleAppCustomRendering(bool* opened) +static void ShowExampleAppCustomRendering(bool* p_open) { ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("Example: Custom rendering", opened)) + if (!ImGui::Begin("Example: Custom rendering", p_open)) { ImGui::End(); return; @@ -1975,10 +1975,10 @@ struct ExampleAppConsole ScrollToBottom = true; } - void Draw(const char* title, bool* opened) + void Draw(const char* title, bool* p_open) { ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin(title, opened)) + if (!ImGui::Begin(title, p_open)) { ImGui::End(); return; @@ -2191,10 +2191,10 @@ struct ExampleAppConsole } }; -static void ShowExampleAppConsole(bool* opened) +static void ShowExampleAppConsole(bool* p_open) { static ExampleAppConsole console; - console.Draw("Example: Console", opened); + console.Draw("Example: Console", p_open); } // Usage: @@ -2223,10 +2223,10 @@ struct ExampleAppLog ScrollToBottom = true; } - void Draw(const char* title, bool* p_opened = NULL) + void Draw(const char* title, bool* p_open = NULL) { ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiSetCond_FirstUseEver); - ImGui::Begin(title, p_opened); + ImGui::Begin(title, p_open); if (ImGui::Button("Clear")) Clear(); ImGui::SameLine(); bool copy = ImGui::Button("Copy"); @@ -2261,7 +2261,7 @@ struct ExampleAppLog } }; -static void ShowExampleAppLog(bool* opened) +static void ShowExampleAppLog(bool* p_open) { static ExampleAppLog log; @@ -2275,19 +2275,19 @@ static void ShowExampleAppLog(bool* opened) last_time = time; } - log.Draw("Example: Log", opened); + log.Draw("Example: Log", p_open); } -static void ShowExampleAppLayout(bool* opened) +static void ShowExampleAppLayout(bool* p_open) { ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiSetCond_FirstUseEver); - if (ImGui::Begin("Example: Layout", opened, ImGuiWindowFlags_MenuBar)) + if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar)) { if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("Close")) *opened = false; + if (ImGui::MenuItem("Close")) *p_open = false; ImGui::EndMenu(); } ImGui::EndMenuBar(); @@ -2323,10 +2323,10 @@ static void ShowExampleAppLayout(bool* opened) ImGui::End(); } -static void ShowExampleAppPropertyEditor(bool* opened) +static void ShowExampleAppPropertyEditor(bool* p_open) { ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("Example: Property editor", opened)) + if (!ImGui::Begin("Example: Property editor", p_open)) { ImGui::End(); return; @@ -2344,12 +2344,12 @@ static void ShowExampleAppPropertyEditor(bool* opened) { ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. - bool is_opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); + bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); ImGui::NextColumn(); ImGui::AlignFirstTextHeightToWidgets(); ImGui::Text("my sailor is rich"); ImGui::NextColumn(); - if (is_opened) + if (node_open) { static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; for (int i = 0; i < 8; i++) @@ -2395,10 +2395,10 @@ static void ShowExampleAppPropertyEditor(bool* opened) ImGui::End(); } -static void ShowExampleAppLongText(bool* opened) +static void ShowExampleAppLongText(bool* p_open) { ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("Example: Long text display", opened)) + if (!ImGui::Begin("Example: Long text display", p_open)) { ImGui::End(); return; diff --git a/imgui_internal.h b/imgui_internal.h index 0ef0b8478..4027b060f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -381,7 +381,7 @@ struct ImGuiState ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector FontStack; // Stack for PushFont()/PopFont() - ImVector OpenedPopupStack; // Which popups are open (persistent) + ImVector OpenPopupStack; // Which popups are open (persistent) ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) // Storage for SetNexWindow** and SetNextTreeNode*** functions @@ -394,8 +394,8 @@ struct ImGuiState ImGuiSetCond SetNextWindowContentSizeCond; ImGuiSetCond SetNextWindowCollapsedCond; bool SetNextWindowFocus; - bool SetNextTreeNodeOpenedVal; - ImGuiSetCond SetNextTreeNodeOpenedCond; + bool SetNextTreeNodeOpenVal; + ImGuiSetCond SetNextTreeNodeOpenCond; // Render ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user @@ -470,8 +470,8 @@ struct ImGuiState SetNextWindowContentSizeCond = 0; SetNextWindowCollapsedCond = 0; SetNextWindowFocus = false; - SetNextTreeNodeOpenedVal = false; - SetNextTreeNodeOpenedCond = 0; + SetNextTreeNodeOpenVal = false; + SetNextTreeNodeOpenCond = 0; ScalarAsInputTextId = 0; ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f); @@ -705,7 +705,7 @@ namespace ImGui IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); - IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool opened, float scale = 1.0f, bool shadow = false); + IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f, bool shadow = false); IMGUI_API void RenderBullet(ImVec2 pos); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. @@ -729,7 +729,7 @@ namespace ImGui IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); - IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging + IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging IMGUI_API void TreePushRawID(ImGuiID id); IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); From 50df86985d99e20d5a145abb284b83a4b1cb6e7a Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 May 2016 10:47:42 +0200 Subject: [PATCH 027/105] Examples: DirectX9: Removed dependency on dx3x9.h so it can be used in a DirectXMath.h only environment (#611) --- examples/directx9_example/imgui_impl_dx9.cpp | 46 +++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 813d58ef2..3db8c8c96 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -10,7 +10,7 @@ #include "imgui_impl_dx9.h" // DirectX -#include +#include #define DIRECTINPUT_VERSION 0x0800 #include @@ -26,9 +26,9 @@ static int g_VertexBufferSize = 5000, g_IndexBufferSize = 1 struct CUSTOMVERTEX { - D3DXVECTOR3 pos; - D3DCOLOR col; - D3DXVECTOR2 uv; + float pos[3]; + D3DCOLOR col; + float uv[2]; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) @@ -37,6 +37,11 @@ struct CUSTOMVERTEX // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) { + // Avoid rendering when minimized + ImGuiIO& io = ImGui::GetIO(); + if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f) + return; + // Create and grow buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -75,12 +80,12 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) const ImDrawVert* vtx_src = &cmd_list->VtxBuffer[0]; for (int i = 0; i < cmd_list->VtxBuffer.size(); i++) { - vtx_dst->pos.x = vtx_src->pos.x; - vtx_dst->pos.y = vtx_src->pos.y; - vtx_dst->pos.z = 0.0f; + vtx_dst->pos[0] = vtx_src->pos.x; + vtx_dst->pos[1] = vtx_src->pos.y; + vtx_dst->pos[2] = 0.0f; vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 - vtx_dst->uv.x = vtx_src->uv.x; - vtx_dst->uv.y = vtx_src->uv.y; + vtx_dst->uv[0] = vtx_src->uv.x; + vtx_dst->uv[1] = vtx_src->uv.y; vtx_dst++; vtx_src++; } @@ -115,12 +120,21 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); // Setup orthographic projection matrix - D3DXMATRIXA16 mat; - D3DXMatrixIdentity(&mat); - g_pd3dDevice->SetTransform( D3DTS_WORLD, &mat ); - g_pd3dDevice->SetTransform( D3DTS_VIEW, &mat ); - D3DXMatrixOrthoOffCenterLH( &mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f ); - g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mat ); + // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() + { + const float L = 0.5f, R = io.DisplaySize.x+0.5f, T = 0.5f, B = io.DisplaySize.y+0.5f; + D3DMATRIX mat_identity = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } }; + D3DMATRIX mat_projection = + { + 2.0f/(R-L), 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f/(T-B), 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f, + }; + g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); + } // Render command lists int vtx_offset = 0; @@ -256,7 +270,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture() // Upload texture to graphics system g_FontTexture = NULL; - if (D3DXCreateTexture(g_pd3dDevice, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8B8G8R8, D3DPOOL_DEFAULT, &g_FontTexture) < 0) + if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0) return false; D3DLOCKED_RECT tex_locked_rect; if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) From 731ff3d3f56e1f4b41cc4a3f02ab03fac6f5d6be Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 May 2016 11:12:59 +0200 Subject: [PATCH 028/105] Examples: DirectX9: Removed dependency on dx3x9 (remainder) (#611) --- examples/directx9_example/build_win32.bat | 2 +- examples/directx9_example/directx9_example.vcxproj | 4 ++-- examples/directx9_example/main.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/directx9_example/build_win32.bat b/examples/directx9_example/build_win32.bat index 08a347565..c3647d4c1 100644 --- a/examples/directx9_example/build_win32.bat +++ b/examples/directx9_example/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. /I "%DXSDK_DIR%/Include" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx9_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d9.lib d3dx9d.lib +cl /nologo /Zi /MD /I ..\.. /I "%DXSDK_DIR%/Include" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx9_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d9.lib diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index 83932c55a..66a182b54 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -86,7 +86,7 @@ true $(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories) - d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies) + d3d9.lib;dxguid.lib;%(AdditionalDependencies) Console @@ -116,7 +116,7 @@ true true $(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories) - d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies) + d3d9.lib;dxguid.lib;%(AdditionalDependencies) Console diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 99be4e84d..babee5fd4 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -3,7 +3,7 @@ #include #include "imgui_impl_dx9.h" -#include +#include #define DIRECTINPUT_VERSION 0x0800 #include #include From f46c91f5ad05ea6f2581bb84c784853dacb4b945 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 May 2016 11:30:43 +0200 Subject: [PATCH 029/105] Examples: DirectX9: Removed dependency on dxguid.lib + remainder of d3dx9.lib (#611) --- examples/directx9_example/directx9_example.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index 66a182b54..c10731dee 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -86,7 +86,7 @@ true $(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories) - d3d9.lib;dxguid.lib;%(AdditionalDependencies) + d3d9.lib;%(AdditionalDependencies) Console @@ -99,7 +99,7 @@ true $(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories) - d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies) + d3d9.lib;%(AdditionalDependencies) Console @@ -116,7 +116,7 @@ true true $(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories) - d3d9.lib;dxguid.lib;%(AdditionalDependencies) + d3d9.lib;%(AdditionalDependencies) Console @@ -133,7 +133,7 @@ true true $(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories) - d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies) + d3d9.lib;%(AdditionalDependencies) Console From 4ce6cf0512c1dbf22199d238a473a42a6b99712a Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 May 2016 20:22:35 +0200 Subject: [PATCH 030/105] Demo: Moved "Fonts" section style editor --- imgui_demo.cpp | 82 +++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 979accc31..2e1fa18f9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -217,47 +217,6 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size)) - { - ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); - ImFontAtlas* atlas = ImGui::GetIO().Fonts; - if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) - { - ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); - ImGui::TreePop(); - } - ImGui::PushItemWidth(100); - for (int i = 0; i < atlas->Fonts.Size; i++) - { - ImFont* font = atlas->Fonts[i]; - ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size); - ImGui::TreePush((void*)(intptr_t)i); - if (i > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { atlas->Fonts[i] = atlas->Fonts[0]; atlas->Fonts[0] = font; } } - ImGui::PushFont(font); - ImGui::Text("The quick brown fox jumps over the lazy dog"); - ImGui::PopFont(); - if (ImGui::TreeNode("Details")) - { - ImGui::DragFloat("font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this font - ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); - ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); - for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - { - ImFontConfig* cfg = &font->ConfigData[config_i]; - ImGui::BulletText("Input %d: \'%s\'\nOversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); - } - ImGui::TreePop(); - } - ImGui::TreePop(); - } - static float window_scale = 1.0f; - ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window - ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything - ImGui::PopItemWidth(); - ImGui::SetWindowFontScale(window_scale); - ImGui::TreePop(); - } - if (ImGui::TreeNode("Logging")) { ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output."); @@ -1685,6 +1644,47 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::TreePop(); } + if (ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size)) + { + ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); + ImFontAtlas* atlas = ImGui::GetIO().Fonts; + if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) + { + ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); + ImGui::TreePop(); + } + ImGui::PushItemWidth(100); + for (int i = 0; i < atlas->Fonts.Size; i++) + { + ImFont* font = atlas->Fonts[i]; + ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size); + ImGui::TreePush((void*)(intptr_t)i); + if (i > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { atlas->Fonts[i] = atlas->Fonts[0]; atlas->Fonts[0] = font; } } + ImGui::PushFont(font); + ImGui::Text("The quick brown fox jumps over the lazy dog"); + ImGui::PopFont(); + if (ImGui::TreeNode("Details")) + { + ImGui::DragFloat("font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this font + ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); + ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); + for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) + { + ImFontConfig* cfg = &font->ConfigData[config_i]; + ImGui::BulletText("Input %d: \'%s\'\nOversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); + } + ImGui::TreePop(); + } + ImGui::TreePop(); + } + static float window_scale = 1.0f; + ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window + ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything + ImGui::PopItemWidth(); + ImGui::SetWindowFontScale(window_scale); + ImGui::TreePop(); + } + ImGui::PopItemWidth(); } From 0058492156fe7651e39694a9e07c5017327f517d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 May 2016 17:20:11 +0200 Subject: [PATCH 031/105] Fonts readme, refering to IconFontCppHeaders, AddRemapChar() function, etc. --- extra_fonts/README.txt | 25 +++++++++++++++++++++---- imgui.cpp | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/extra_fonts/README.txt b/extra_fonts/README.txt index b577b870d..1e9bc13ce 100644 --- a/extra_fonts/README.txt +++ b/extra_fonts/README.txt @@ -1,9 +1,13 @@ The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' that you can use without any external files. - Those are only provided as a convenience, you can load your own .TTF files. + The files in this folder are only provided as a convenience, you can use any of your own .TTF files. Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). + If you want to use icons in ImGui, a good idea is to merge an icon font within your main font, and refer to icons directly in your strings. + You can use headers files with definitions for popular icon fonts codepoints, by Juliette Foucaut, at https://github.com/juliettef/IconFontCppHeaders + + --------------------------------- LOADING INSTRUCTIONS --------------------------------- @@ -35,10 +39,10 @@ Combine two fonts into one: - // Load main font + // Load a first font io.Fonts->AddFontDefault(); - // Add character ranges and merge into main font + // Add character ranges and merge into the previous font // The ranges array is not copied by the AddFont* functions and is used lazily // so ensure it is available for duration of font usage static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // will not be copied by AddFont* so keep in scope. @@ -63,6 +67,16 @@ ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); font->DisplayOffset.y += 1; // Render 1 pixel down + +--------------------------------- + REMAP CODEPOINTS +--------------------------------- + + All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese CP-1251 for Cyrillic) will not work. + In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. + You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. + + --------------------------------- EMBED A FONT IN SOURCE CODE --------------------------------- @@ -75,8 +89,9 @@ ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...); + --------------------------------- - INCLUDED FONT FILES + FONT FILES INCLUDED IN THIS FOLDER --------------------------------- Cousine-Regular.ttf @@ -102,6 +117,7 @@ Copyright (c) 2012, Jonathan Pinhorn SIL OPEN FONT LICENSE Version 1.1 + --------------------------------- LINKS --------------------------------- @@ -109,6 +125,7 @@ Icon fonts https://fortawesome.github.io/Font-Awesome/ https://github.com/SamBrishes/kenney-icon-font + https://design.google.com/icons/ Typefaces for source code beautification https://github.com/chrissimpkins/codeface diff --git a/imgui.cpp b/imgui.cpp index 70649fdbf..b3e9a4b20 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -414,7 +414,7 @@ Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. - All strings passed need to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese CP-1251 for Cyrillic) will not work. + All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will not work. In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. From 9b793276736a63302bc1be7108f583eb604eaf59 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 May 2016 20:22:57 +0200 Subject: [PATCH 032/105] BeginGroup() fixed using within Columns set (fix #630) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index b3e9a4b20..ae0ecd34b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8911,7 +8911,7 @@ void ImGui::BeginGroup() group_data.BackupLogLinePosY = window->DC.LogLinePosY; group_data.AdvanceCursor = true; - window->DC.IndentX = window->DC.CursorPos.x - window->Pos.x; + window->DC.IndentX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX; window->DC.CursorMaxPos = window->DC.CursorPos; window->DC.CurrentLineHeight = 0.0f; window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; From efedaa5df37b671e1ebd86aad3f3d6ef7ec1c449 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 May 2016 20:49:17 +0200 Subject: [PATCH 033/105] Updated FAQ (#628) --- README.md | 4 +++- imgui.cpp | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 88c7f4e3e..3057fd5e3 100644 --- a/README.md +++ b/README.md @@ -95,12 +95,14 @@ Frequently Asked Question (FAQ) The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations. How do I update to a newer version of ImGui? -
Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) +
What is ImTextureID and how do I display an image?
I integrated ImGui in my engine and the text or lines are blurry..
I integrated ImGui in my engine and some elements are disappearing when I move windows around.. +
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs.
How can I load a different font than the default?
How can I load multiple fonts?
How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? +
How can I use the drawing facilities without an ImGui window? (using ImDrawList API) See the FAQ in imgui.cpp for answers. diff --git a/imgui.cpp b/imgui.cpp index ae0ecd34b..518ee0f3a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -20,12 +20,13 @@ - How can I help? - How do I update to a newer version of ImGui? - What is ImTextureID and how do I display an image? - - Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) / A primer on the use of labels/IDs in ImGui. - I integrated ImGui in my engine and the text or lines are blurry.. - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs. - How can I load a different font than the default? - How can I load multiple fonts? - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? + - How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - ISSUES & TODO-LIST - CODE @@ -278,6 +279,13 @@ ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. It is your responsibility to get textures uploaded to your GPU. + Q: I integrated ImGui in my engine and the text or lines are blurry.. + A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). + Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. + + Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1,y1,x2,y2) and NOT as (x1,y1,width,height). + Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) A: Yes. A primer on the use of labels/IDs in ImGui.. @@ -371,13 +379,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: I integrated ImGui in my engine and the text or lines are blurry.. - A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). - Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. - - Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1,y1,x2,y2) and NOT as (x1,y1,width,height). - Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF file you want: @@ -424,6 +425,10 @@ As for text input, depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. + Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) + A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, + then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. + - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug" - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) @@ -565,6 +570,7 @@ - style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438) - style editor: color child window height expressed in multiple of line height. - remote: make a system like RemoteImGui first-class citizen/project (#75) + - drawlist: move Font, FontSize, FontTexUvWhitePixel inside ImDrawList and make it self-contained (apart from drawing settings?) - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack. - examples: directx9: save/restore device state more thoroughly. - examples: window minimize, maximize (#583) From 79ad22e1f2e90eee6d07940786ad604fdcab2aea Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 May 2016 23:17:53 +0200 Subject: [PATCH 034/105] Fixed various Clang -Weverything warnings (#626) --- examples/opengl_example/imgui_impl_glfw.cpp | 2 +- examples/sdl_opengl_example/imgui_impl_sdl.cpp | 2 +- imgui.cpp | 12 +++++------- imgui_demo.cpp | 9 ++++++--- imgui_draw.cpp | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index f6447e151..2d1f5c1a0 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -101,7 +101,7 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - glBindTexture(GL_TEXTURE_2D, last_texture); + glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); diff --git a/examples/sdl_opengl_example/imgui_impl_sdl.cpp b/examples/sdl_opengl_example/imgui_impl_sdl.cpp index 0d885b07f..a35dc1cea 100644 --- a/examples/sdl_opengl_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl_example/imgui_impl_sdl.cpp @@ -90,7 +90,7 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - glBindTexture(GL_TEXTURE_2D, last_texture); + glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); diff --git a/imgui.cpp b/imgui.cpp index 518ee0f3a..153375b9c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -603,7 +603,6 @@ #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf #endif // Clang warnings with -Weverything @@ -615,7 +614,6 @@ #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // #pragma clang diagnostic ignored "-Wmissing-noreturn" // warning : function xx could be declared with attribute 'noreturn' warning // GetDefaultFontData() asserts which some implementation makes it never return. -#pragma clang diagnostic ignored "-Wdeprecated-declarations"// warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code) #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' #endif #ifdef __GNUC__ @@ -4815,7 +4813,7 @@ void ImGui::SetNextWindowFocus() ImVec2 ImGui::GetContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); - ImVec2 content_region_size = ImVec2(window->SizeContentsExplicit.x ? window->SizeContentsExplicit.x : window->Size.x - window->ScrollbarSizes.x, window->SizeContentsExplicit.y ? window->SizeContentsExplicit.y : window->Size.y - window->ScrollbarSizes.y); + ImVec2 content_region_size = ImVec2(window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : window->Size.x - window->ScrollbarSizes.x, window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : window->Size.y - window->ScrollbarSizes.y); ImVec2 mx = content_region_size - window->Scroll - window->WindowPadding; if (window->DC.ColumnsCount != 1) mx.x = ImGui::GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; @@ -4843,7 +4841,7 @@ ImVec2 ImGui::GetWindowContentRegionMin() ImVec2 ImGui::GetWindowContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); - ImVec2 content_region_size = ImVec2(window->SizeContentsExplicit.x ? window->SizeContentsExplicit.x : window->Size.x, window->SizeContentsExplicit.y ? window->SizeContentsExplicit.y : window->Size.y); + ImVec2 content_region_size = ImVec2(window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : window->Size.x, window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : window->Size.y); ImVec2 m = content_region_size - window->Scroll - window->WindowPadding - window->ScrollbarSizes; return m; } @@ -9163,7 +9161,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) window->DC.ColumnsCount = columns_count; window->DC.ColumnsShowBorders = border; - const float content_region_width = window->SizeContentsExplicit.x ? window->SizeContentsExplicit.x : window->Size.x; + const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; window->DC.ColumnsMinX = window->DC.IndentX; // Lock our horizontal range window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; @@ -9443,7 +9441,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); continue; } - bool node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); if (show_clip_rects && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; @@ -9454,7 +9452,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255)); } - if (!node_open) + if (!pcmd_node_open) continue; for (int i = elem_offset; i+2 < elem_offset + (int)pcmd->ElemCount; i += 3) { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2e1fa18f9..afe8e5a30 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -25,9 +25,12 @@ #define snprintf _snprintf #endif #ifdef __clang__ +#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code) #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal +#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. +#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size @@ -2182,7 +2185,7 @@ struct ExampleAppConsole // A better implementation would preserve the data on the current input line along with cursor position. if (prev_history_pos != HistoryPos) { - data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : ""); + data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : ""); data->BufDirty = true; } } @@ -2340,7 +2343,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open) struct funcs { - static void ShowDummyObject(const char* prefix, ImU32 uid) + static void ShowDummyObject(const char* prefix, int uid) { ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. @@ -2357,7 +2360,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open) ImGui::PushID(i); // Use field index as identifier. if (i < 2) { - ShowDummyObject("Child", ImGui::GetID("foo")); + ShowDummyObject("Child", 424242); } else { diff --git a/imgui_draw.cpp b/imgui_draw.cpp index da070b22d..4531f8afc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -37,7 +37,7 @@ #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // -//#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // +#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used From c1da3e354e031577070b22d677f2e5d9de0813b6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 May 2016 23:20:41 +0200 Subject: [PATCH 035/105] Examples: SDL: Fixed unused variable warning on non-Windows platforms (#626) --- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 ++ examples/sdl_opengl_example/imgui_impl_sdl.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index c3fed5f0b..d97b4cc00 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -330,6 +330,8 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(window, &wmInfo); io.ImeWindowHandle = wmInfo.info.win.window; +#else + (void)window; #endif return true; diff --git a/examples/sdl_opengl_example/imgui_impl_sdl.cpp b/examples/sdl_opengl_example/imgui_impl_sdl.cpp index a35dc1cea..ae42f143c 100644 --- a/examples/sdl_opengl_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl_example/imgui_impl_sdl.cpp @@ -218,6 +218,8 @@ bool ImGui_ImplSdl_Init(SDL_Window* window) SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(window, &wmInfo); io.ImeWindowHandle = wmInfo.info.win.window; +#else + (void)window; #endif return true; From f22b6e1e09229161a703e31aef88ce9631b4dd65 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 May 2016 23:28:16 +0200 Subject: [PATCH 036/105] Fixed/silenced various absurd GCC warnings from outer space (#626) --- imgui.cpp | 4 ++-- imgui_draw.cpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 153375b9c..ae44ef98c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -613,12 +613,12 @@ #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // -#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning : function xx could be declared with attribute 'noreturn' warning // GetDefaultFontData() asserts which some implementation makes it never return. -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' +#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' // #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size +#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' #endif //------------------------------------------------------------------------- diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4531f8afc..8bfdaa787 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -58,7 +58,7 @@ namespace IMGUI_STB_NAMESPACE #ifdef _MSC_VER #pragma warning (push) -#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration +#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration #endif #ifdef __clang__ @@ -68,6 +68,11 @@ namespace IMGUI_STB_NAMESPACE #pragma clang diagnostic ignored "-Wmissing-prototypes" #endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] +#endif + #define STBRP_ASSERT(x) IM_ASSERT(x) #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #define STBRP_STATIC @@ -86,6 +91,10 @@ namespace IMGUI_STB_NAMESPACE #endif #include "stb_truetype.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #ifdef __clang__ #pragma clang diagnostic pop #endif From 67df0ba18543dfaadd4eadd44e23522b398676cd Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 6 May 2016 09:18:07 +0200 Subject: [PATCH 037/105] Updated FAQ and Readme with more prominent info about WantCaptureMouse etc. flags (#635) --- README.md | 1 + imgui.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3057fd5e3..9e32e9e26 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ The library started its life and is best known as "ImGui" only due to the fact t
I integrated ImGui in my engine and the text or lines are blurry..
I integrated ImGui in my engine and some elements are disappearing when I move windows around..
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs. +
How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application?
How can I load a different font than the default?
How can I load multiple fonts?
How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? diff --git a/imgui.cpp b/imgui.cpp index ae44ef98c..79969ebd8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -23,6 +23,7 @@ - I integrated ImGui in my engine and the text or lines are blurry.. - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs. + - How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application? - How can I load a different font than the default? - How can I load multiple fonts? - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? @@ -141,9 +142,8 @@ SwapBuffers(); } - - after calling ImGui::NewFrame() you can read back flags from the IO structure to tell how ImGui intends to use your inputs. - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an on-screen keyboard, if available. + - You can read back 'io.WantCaptureMouse', 'io.WantCaptureKeybord' etc. flags from the IO structure to tell how ImGui intends to use your + inputs and to know if you should share them or hide them from the rest of your application. Read the FAQ below for more information. API BREAKING CHANGES @@ -379,6 +379,12 @@ 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 can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application? + A: You can read the 'io.WantCaptureXXX' flags in the ImGuiIO structure. Preferably read them after calling ImGui::NewFrame() to avoid those flags lagging by one frame. + When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. + When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an on-screen keyboard, if available. + ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is a more accurate and complete than testing for ImGui::IsMouseHoveringAnyWindow(). + Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF file you want: From 313d388bba42e0634a02b976dcdbae238d25eddc Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 6 May 2016 11:31:32 +0200 Subject: [PATCH 038/105] Reorganised windows moving code, documented a lag in FindHoveredWindow(), fixing lag whole moving windows (#635) --- imgui.cpp | 69 ++++++++++++++++++++++++++---------------------- imgui_internal.h | 6 +++-- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 79969ebd8..613e8db6f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2007,8 +2007,35 @@ void ImGui::NewFrame() g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; - if (!g.ActiveId) + + // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. + if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) + { + KeepAliveID(g.MovedWindowMoveId); + IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow); + IM_ASSERT(g.MovedWindow->RootWindow->MoveID == g.MovedWindowMoveId); + if (g.IO.MouseDown[0]) + { + if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove)) + { + g.MovedWindow->PosFloat += g.IO.MouseDelta; + if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings)) + MarkSettingsDirty(); + } + FocusWindow(g.MovedWindow); + } + else + { + SetActiveID(0); + g.MovedWindow = NULL; + g.MovedWindowMoveId = 0; + } + } + else + { g.MovedWindow = NULL; + g.MovedWindowMoveId = 0; + } // Delay saving settings so we don't spam disk too much if (g.SettingsDirtyTimer > 0.0f) @@ -2019,11 +2046,11 @@ void ImGui::NewFrame() } // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow - g.HoveredWindow = FindHoveredWindow(g.IO.MousePos, false); + g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false); if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow)) g.HoveredRootWindow = g.HoveredWindow->RootWindow; else - g.HoveredRootWindow = FindHoveredWindow(g.IO.MousePos, true); + g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true); if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) { @@ -2420,8 +2447,6 @@ void ImGui::EndFrame() ImGui::End(); // Click to focus window and start moving (after we're done with all our widgets) - if (!g.ActiveId) - g.MovedWindow = NULL; if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) { if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear @@ -2432,7 +2457,8 @@ void ImGui::EndFrame() if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovedWindow = g.HoveredWindow; - SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow); + g.MovedWindowMoveId = g.HoveredRootWindow->MoveID; + SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); } } else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) @@ -2842,6 +2868,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items } // Find window given position, search front-to-back +// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) { ImGuiState& g = *GImGui; @@ -2856,7 +2883,7 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) continue; // Using the clipped AABB so a child window will typically be clipped by its parent. - ImRect bb(window->ClippedWindowRect.Min - g.Style.TouchExtraPadding, window->ClippedWindowRect.Max + g.Style.TouchExtraPadding); + ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding); if (bb.Contains(pos)) return window; } @@ -3884,28 +3911,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->PosFloat = g.IO.MousePos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. } - // User moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. - KeepAliveID(window->MoveID); - if (g.ActiveId == window->MoveID) - { - if (g.IO.MouseDown[0]) - { - if (!(flags & ImGuiWindowFlags_NoMove)) - { - window->PosFloat += g.IO.MouseDelta; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); - } - IM_ASSERT(g.MovedWindow != NULL); - FocusWindow(g.MovedWindow); - } - else - { - SetActiveID(0); - g.MovedWindow = NULL; // Not strictly necessary but doing it for sanity. - } - } - // Clamp position so it stays visible if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) { @@ -4120,8 +4125,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() - window->ClippedWindowRect = window->Rect(); - window->ClippedWindowRect.Clip(window->ClipRect); + window->WindowRectClipped = window->Rect(); + window->WindowRectClipped.Clip(window->ClipRect); // Pressing CTRL+C while holding on a window copy its content to the clipboard // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. @@ -4158,7 +4163,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->Collapsed = parent_window && parent_window->Collapsed; if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - window->Collapsed |= (window->ClippedWindowRect.Min.x >= window->ClippedWindowRect.Max.x || window->ClippedWindowRect.Min.y >= window->ClippedWindowRect.Max.y); + window->Collapsed |= (window->WindowRectClipped.Min.x >= window->WindowRectClipped.Max.x || window->WindowRectClipped.Min.y >= window->WindowRectClipped.Max.y); // We also hide the window from rendering because we've already added its border to the command list. // (we could perform the check earlier in the function but it is simpler at this point) diff --git a/imgui_internal.h b/imgui_internal.h index 4027b060f..6c72a0515 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -375,7 +375,8 @@ struct ImGuiState bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Set only by active widget ImGuiWindow* ActiveIdWindow; - ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window. + ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. + ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId ImVector Settings; // .ini Settings float SettingsDirtyTimer; // Save .ini settinngs on disk when time reaches zero ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() @@ -460,6 +461,7 @@ struct ImGuiState ActiveIdAllowOverlap = false; ActiveIdWindow = NULL; MovedWindow = NULL; + MovedWindowMoveId = 0; SettingsDirtyTimer = 0.0f; SetNextWindowPosVal = ImVec2(0.0f, 0.0f); @@ -627,7 +629,7 @@ struct IMGUI_API ImGuiWindow ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. - ImRect ClippedWindowRect; // = ClipRect just after setup in Begin() + ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. int LastFrameActive; float ItemWidthDefault; ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items From ce4d731486b379c5a4fc6e5d4f54f3a2256e16b0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 18:10:32 +0200 Subject: [PATCH 039/105] Minor comments, tweaks --- imgui.h | 7 ++++--- imgui_demo.cpp | 2 ++ imgui_internal.h | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui.h b/imgui.h index eaf44b9e0..2a7199c9b 100644 --- a/imgui.h +++ b/imgui.h @@ -158,7 +158,7 @@ namespace ImGui IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget + IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use negative 'offset' to access previous widgets. IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage(); @@ -948,7 +948,7 @@ struct ImGuiTextBuffer IMGUI_API void appendv(const char* fmt, va_list args); }; -// Helper: Key->value storage +// Helper: Simple Key->value storage // - Store collapse state for a tree (Int 0/1) // - Store color edit options (Int using values in ImGuiColorEditMode enum). // - Custom user storage for temporary values. @@ -956,6 +956,7 @@ struct ImGuiTextBuffer // Declare your own storage if: // - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). // - You want to store custom debug data easily without adding or editing structures in your code. +// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. struct ImGuiStorage { struct Pair @@ -970,7 +971,7 @@ struct ImGuiStorage // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) // - Set***() functions find pair, insertion on demand if missing. - // - Sorted insertion is costly but should amortize. A typical frame shouldn't need to insert any new pair. + // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair. IMGUI_API void Clear(); IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; IMGUI_API void SetInt(ImGuiID key, int val); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index afe8e5a30..894f4676f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1030,9 +1030,11 @@ void ImGui::ShowTestWindow(bool* p_open) static bool track = true; static int track_line = 50, scroll_to_px = 200; ImGui::Checkbox("Track", &track); + ImGui::PushItemWidth(100); ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line %.0f"); bool scroll_to = ImGui::Button("Scroll To"); ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px"); + ImGui::PopItemWidth(); if (scroll_to) track = false; for (int i = 0; i < 5; i++) diff --git a/imgui_internal.h b/imgui_internal.h index 6c72a0515..0b31fa324 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -378,7 +378,7 @@ struct ImGuiState ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId ImVector Settings; // .ini Settings - float SettingsDirtyTimer; // Save .ini settinngs on disk when time reaches zero + float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector FontStack; // Stack for PushFont()/PopFont() @@ -417,7 +417,7 @@ struct ImGuiState float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio float DragSpeedScaleSlow; float DragSpeedScaleFast; - ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? + ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? char Tooltip[1024]; char* PrivateClipboard; // If no custom clipboard handler is defined ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor From 69cc00f91fa440476453ab30d2597481f6b96c6d Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 18:18:37 +0200 Subject: [PATCH 040/105] ImGuiStorage: Added bool helper functions for completeness. --- imgui.cpp | 15 +++++++++++++++ imgui.h | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 613e8db6f..b982a71e4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1313,6 +1313,11 @@ int ImGuiStorage::GetInt(ImU32 key, int default_val) const return it->val_i; } +bool ImGuiStorage::GetBool(ImU32 key, bool default_val) const +{ + return GetInt(key, default_val ? 1 : 0) != 0; +} + float ImGuiStorage::GetFloat(ImU32 key, float default_val) const { ImVector::iterator it = LowerBound(const_cast&>(Data), key); @@ -1338,6 +1343,11 @@ int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) return &it->val_i; } +bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) +{ + return (bool*)GetIntRef(key, default_val ? 1 : 0); +} + float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { ImVector::iterator it = LowerBound(Data, key); @@ -1366,6 +1376,11 @@ void ImGuiStorage::SetInt(ImU32 key, int val) it->val_i = val; } +void ImGuiStorage::SetBool(ImU32 key, bool val) +{ + SetInt(key, val ? 1 : 0); +} + void ImGuiStorage::SetFloat(ImU32 key, float val) { ImVector::iterator it = LowerBound(Data, key); diff --git a/imgui.h b/imgui.h index 2a7199c9b..2683308c1 100644 --- a/imgui.h +++ b/imgui.h @@ -975,6 +975,8 @@ struct ImGuiStorage IMGUI_API void Clear(); IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; IMGUI_API void SetInt(ImGuiID key, int val); + IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; + IMGUI_API void SetBool(ImGuiID key, bool val); IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; IMGUI_API void SetFloat(ImGuiID key, float val); IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL @@ -986,7 +988,8 @@ struct ImGuiStorage // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; // - You can also use this to quickly create temporary editable values during a session of using Edit&Continue, without restarting your application. IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); - IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0); + IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false); + IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); // Use on your own storage if you know only integer are being stored (open/close all tree nodes) From 6e8579fc144f1d59a75aabf3740470d3e3739a1b Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sat, 7 May 2016 17:57:13 +0200 Subject: [PATCH 041/105] Ignore implicit conversion warnings --- imgui.cpp | 2 ++ imgui_demo.cpp | 2 ++ imgui_draw.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index b982a71e4..dffa1356d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -625,6 +625,8 @@ #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' +#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function +#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #endif //------------------------------------------------------------------------- diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 894f4676f..c19e2b5bf 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -35,6 +35,8 @@ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) +#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function +#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #endif // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8bfdaa787..5fcdc83cb 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -41,6 +41,8 @@ #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used +#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function +#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #endif //------------------------------------------------------------------------- From 5fe2cacd4da495be9b656b29d6e2e848434f447a Mon Sep 17 00:00:00 2001 From: josiahmanson Date: Sat, 7 May 2016 10:42:48 -0700 Subject: [PATCH 042/105] DX11 example depth test --- .../directx11_example/imgui_impl_dx11.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 5f209bc04..33afb7eaf 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -35,6 +35,7 @@ static ID3D11ShaderResourceView*g_pFontTextureView = NULL; static ID3D11RasterizerState* g_pRasterizerState = NULL; static ID3D11BlendState* g_pBlendState = NULL; static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; +static ID3D11DepthStencilState* g_pDSState = NULL; struct VERTEX_CONSTANT_BUFFER { @@ -138,6 +139,8 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; + ID3D11DepthStencilState* DepthStencilState; + UINT StencilRef; }; BACKUP_DX11_STATE old; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; @@ -155,6 +158,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); + ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); // Setup viewport D3D11_VIEWPORT vp; @@ -182,6 +186,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); ctx->RSSetState(g_pRasterizerState); + ctx->OMSetDepthStencilState( g_pDSState, 1 ); // Render command lists int vtx_offset = 0; @@ -224,6 +229,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); + ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -448,6 +454,18 @@ bool ImGui_ImplDX11_CreateDeviceObjects() g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); } + + // Create Depth-Stencil State + { + D3D11_DEPTH_STENCIL_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.StencilEnable = false; + desc.DepthEnable = true; + desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D11_COMPARISON_ALWAYS; + g_pd3dDevice->CreateDepthStencilState( &desc, &g_pDSState ); + } + ImGui_ImplDX11_CreateFontsTexture(); return true; @@ -471,6 +489,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } + if (g_pDSState) { g_pDSState->Release(); g_pDSState = NULL; } } bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context) From 8b428e8c74c013bd84cf4284e69192c0e222a4c9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 19:54:27 +0200 Subject: [PATCH 043/105] Added CreateContext/DestroyContext/GetCurrentContext/SetCurrentContext() (#586, #269) --- imgui.cpp | 35 ++++++++++++++++++++++++----------- imgui.h | 10 ++++++---- imgui_draw.cpp | 4 ++-- imgui_internal.h | 13 ++++++------- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b982a71e4..fe1fde54b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -153,6 +153,7 @@ 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. @@ -694,12 +695,12 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); //----------------------------------------------------------------------------- // We access everything through this pointer (always assumed to be != NULL) -// You can swap the pointer to a different context by calling ImGui::SetInternalState() -static ImGuiState GImDefaultState; -ImGuiState* GImGui = &GImDefaultState; +// You can swap the pointer to a different context by calling ImGui::SetCurrentContext() +static ImGuiState GImDefaultContext; +ImGuiState* GImGui = &GImDefaultContext; // Statically allocated default font atlas. This is merely a maneuver to keep ImFontAtlas definition at the bottom of the .h file (otherwise it'd be inside ImGuiIO) -// Also we wouldn't be able to new() one at this point, before users may define IO.MemAllocFn. +// Also we wouldn't be able to new() one at this point, before users have a chance to setup their allocator. static ImFontAtlas GImDefaultFontAtlas; //----------------------------------------------------------------------------- @@ -1888,21 +1889,33 @@ const char* ImGui::GetVersion() // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself // Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module -void* ImGui::GetInternalState() +ImGuiState* ImGui::GetCurrentContext() { return GImGui; } -size_t ImGui::GetInternalStateSize() +void ImGui::SetCurrentContext(ImGuiState* ctx) { - return sizeof(ImGuiState); + GImGui = ctx; } -void ImGui::SetInternalState(void* state, bool construct) +ImGuiState* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)) { - if (construct) - IM_PLACEMENT_NEW(state) ImGuiState(); - GImGui = (ImGuiState*)state; + if (!malloc_fn) malloc_fn = malloc; + ImGuiState* ctx = (ImGuiState*)malloc_fn(sizeof(ImGuiState)); + IM_PLACEMENT_NEW(ctx) ImGuiState(); + ctx->IO.MemAllocFn = malloc_fn; + ctx->IO.MemFreeFn = free_fn ? free_fn : free; + return ctx; +} + +void ImGui::DestroyContext(ImGuiState* ctx) +{ + void (*free_fn)(void*) = ctx->IO.MemFreeFn; + ctx->~ImGuiState(); + free_fn(ctx); + if (GImGui == ctx) + GImGui = NULL; } ImGuiIO& ImGui::GetIO() diff --git a/imgui.h b/imgui.h index 2683308c1..d54798035 100644 --- a/imgui.h +++ b/imgui.h @@ -54,6 +54,7 @@ struct ImGuiTextFilter; // Parse and apply text filters. In format " struct ImGuiTextBuffer; // Text buffer for logging/accumulating text struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom callbacks (advanced) struct ImGuiListClipper; // Helper to manually clip large list of items +struct ImGuiState; // ImGui context (opaque) // Enumerations (declared as int for compatibility and to not pollute the top of this file) typedef unsigned int ImU32; @@ -442,11 +443,12 @@ namespace ImGui IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); - // Internal state/context access - if you want to use multiple ImGui context, or share context between modules (e.g. DLL), or allocate the memory yourself + // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. IMGUI_API const char* GetVersion(); - IMGUI_API void* GetInternalState(); - IMGUI_API size_t GetInternalStateSize(); - IMGUI_API void SetInternalState(void* state, bool construct = false); + IMGUI_API ImGuiState* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); + IMGUI_API void DestroyContext(ImGuiState* ctx); + IMGUI_API ImGuiState* GetCurrentContext(); + IMGUI_API void SetCurrentContext(ImGuiState* ctx); // Obsolete (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8bfdaa787..007e48eed 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -245,7 +245,7 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_ void ImDrawList::PushClipRectFullScreen() { PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w)); - //PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiState from here? + //PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here? } void ImDrawList::PopClipRect() @@ -1665,7 +1665,7 @@ ImFont::~ImFont() // If you want to delete fonts you need to do it between Render() and NewFrame(). // FIXME-CLEANUP /* - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.Font == this) g.Font = NULL; */ diff --git a/imgui_internal.h b/imgui_internal.h index 0b31fa324..4eee4f7dd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -33,7 +33,6 @@ struct ImGuiTextEditState; struct ImGuiIniData; struct ImGuiMouseCursorData; struct ImGuiPopupRef; -struct ImGuiState; struct ImGuiWindow; typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ @@ -71,7 +70,7 @@ namespace ImGuiStb // Context //----------------------------------------------------------------------------- -extern IMGUI_API ImGuiState* GImGui; +extern IMGUI_API ImGuiState* GImGui; // current implicit ImGui context pointer //----------------------------------------------------------------------------- // Helpers @@ -144,7 +143,7 @@ static inline ImVec2 ImFloor(ImVec2 v) struct ImPlacementNewDummy {}; inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; } inline void operator delete(void*, ImPlacementNewDummy, void*) {} -#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy() ,_PTR) +#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR) #endif //----------------------------------------------------------------------------- @@ -274,7 +273,7 @@ struct ImGuiColumnData //float IndentX; }; -// Simple column measurement currently used for MenuItem() only. This is very short-sighted for now and NOT a generic helper. +// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiSimpleColumns { int Count; @@ -283,9 +282,9 @@ struct IMGUI_API ImGuiSimpleColumns float Pos[8], NextWidths[8]; ImGuiSimpleColumns(); - void Update(int count, float spacing, bool clear); - float DeclColumns(float w0, float w1, float w2); - float CalcExtraSpace(float avail_w); + void Update(int count, float spacing, bool clear); + float DeclColumns(float w0, float w1, float w2); + float CalcExtraSpace(float avail_w); }; // Internal state of the currently focused/edited text input box From 7b9c0a5c3fb8147699cdbc39b5dae04c55c8f9cc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 19:55:51 +0200 Subject: [PATCH 044/105] Renamed ImGuiState -> ImGuiContext (#586, #269) --- imgui.cpp | 320 +++++++++++++++++++++++------------------------ imgui.h | 10 +- imgui_internal.h | 10 +- 3 files changed, 170 insertions(+), 170 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fe1fde54b..3dfa7cfff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -696,8 +696,8 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); // We access everything through this pointer (always assumed to be != NULL) // You can swap the pointer to a different context by calling ImGui::SetCurrentContext() -static ImGuiState GImDefaultContext; -ImGuiState* GImGui = &GImDefaultContext; +static ImGuiContext GImDefaultContext; +ImGuiContext* GImGui = &GImDefaultContext; // Statically allocated default font atlas. This is merely a maneuver to keep ImFontAtlas definition at the bottom of the .h file (otherwise it'd be inside ImGuiIO) // Also we wouldn't be able to new() one at this point, before users have a chance to setup their allocator. @@ -1677,7 +1677,7 @@ ImGuiID ImGuiWindow::GetID(const void* ptr) static void SetCurrentWindow(ImGuiWindow* window) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.CurrentWindow = window; if (window) g.FontSize = window->CalcFontSize(); @@ -1685,14 +1685,14 @@ static void SetCurrentWindow(ImGuiWindow* window) ImGuiWindow* ImGui::GetParentWindow() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.ActiveId = id; g.ActiveIdAllowOverlap = false; g.ActiveIdIsJustActivated = true; @@ -1701,14 +1701,14 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) void ImGui::SetHoveredID(ImGuiID id) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.HoveredId = id; g.HoveredIdAllowOverlap = false; } void ImGui::KeepAliveID(ImGuiID id) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.ActiveId == id) g.ActiveIdIsAlive = true; } @@ -1721,7 +1721,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y) return; // Always align ourselves on pixel boundaries - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const float line_height = ImMax(window->DC.CurrentLineHeight, size.y); const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y); window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); @@ -1754,7 +1754,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) return false; // This is a sensible default, but widgets are free to override it after calling ItemAdd() - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (IsMouseHoveringRect(bb.Min, bb.Max)) { // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) @@ -1771,7 +1771,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); if (!bb.Overlaps(window->ClipRect)) @@ -1784,7 +1784,7 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when // NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap) { ImGuiWindow* window = GetCurrentWindowRead(); @@ -1798,7 +1798,7 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus; window->FocusIdxAllCounter++; @@ -1831,7 +1831,7 @@ void ImGui::FocusableItemUnregister(ImGuiWindow* window) ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImVec2 content_max; if (size.x < 0.0f || size.y < 0.0f) content_max = g.CurrentWindow->Pos + ImGui::GetContentRegionMax(); @@ -1889,30 +1889,30 @@ const char* ImGui::GetVersion() // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself // Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module -ImGuiState* ImGui::GetCurrentContext() +ImGuiContext* ImGui::GetCurrentContext() { return GImGui; } -void ImGui::SetCurrentContext(ImGuiState* ctx) +void ImGui::SetCurrentContext(ImGuiContext* ctx) { GImGui = ctx; } -ImGuiState* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)) +ImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)) { if (!malloc_fn) malloc_fn = malloc; - ImGuiState* ctx = (ImGuiState*)malloc_fn(sizeof(ImGuiState)); - IM_PLACEMENT_NEW(ctx) ImGuiState(); + ImGuiContext* ctx = (ImGuiContext*)malloc_fn(sizeof(ImGuiContext)); + IM_PLACEMENT_NEW(ctx) ImGuiContext(); ctx->IO.MemAllocFn = malloc_fn; ctx->IO.MemFreeFn = free_fn ? free_fn : free; return ctx; } -void ImGui::DestroyContext(ImGuiState* ctx) +void ImGui::DestroyContext(ImGuiContext* ctx) { void (*free_fn)(void*) = ctx->IO.MemFreeFn; - ctx->~ImGuiState(); + ctx->~ImGuiContext(); free_fn(ctx); if (GImGui == ctx) GImGui = NULL; @@ -1946,7 +1946,7 @@ int ImGui::GetFrameCount() void ImGui::NewFrame() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; // Check user data IM_ASSERT(g.IO.DeltaTime >= 0.0f); // Need a positive DeltaTime (zero is tolerated but will cause some timing issues) @@ -2178,7 +2178,7 @@ void ImGui::NewFrame() // NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations. void ImGui::Shutdown() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. @@ -2238,7 +2238,7 @@ void ImGui::Shutdown() static ImGuiIniData* FindWindowSettings(const char* name) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiID id = ImHash(name, 0); for (int i = 0; i != g.Settings.Size; i++) { @@ -2265,7 +2265,7 @@ static ImGuiIniData* AddWindowSettings(const char* name) // FIXME: Write something less rubbish static void LoadSettings() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const char* filename = g.IO.IniFilename; if (!filename) return; @@ -2311,7 +2311,7 @@ static void LoadSettings() static void SaveSettings() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const char* filename = g.IO.IniFilename; if (!filename) return; @@ -2353,7 +2353,7 @@ static void SaveSettings() static void MarkSettingsDirty() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.SettingsDirtyTimer <= 0.0f) g.SettingsDirtyTimer = g.IO.IniSavingRate; } @@ -2449,7 +2449,7 @@ void ImGui::PopClipRect() // This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. void ImGui::EndFrame() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.FrameCountEnded != g.FrameCount); // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again @@ -2520,7 +2520,7 @@ void ImGui::EndFrame() void ImGui::Render() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() if (g.FrameCountEnded != g.FrameCount) @@ -2610,7 +2610,7 @@ const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) // Pass text data straight to log (without being displayed) void ImGui::LogText(const char* fmt, ...) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (!g.LogEnabled) return; @@ -2631,7 +2631,7 @@ void ImGui::LogText(const char* fmt, ...) // We split text into individual lines to add current tree level padding static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = ImGui::GetCurrentWindowRead(); if (!text_end) @@ -2682,7 +2682,7 @@ static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); // Hide anything after a '##' string @@ -2709,7 +2709,7 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (!text_end) @@ -2733,7 +2733,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons if (text_len == 0) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); // Perform CPU side clipping for single clipped element to avoid using scissor state @@ -2779,7 +2779,7 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, // Render a triangle to denote expanded/collapsed state void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale, bool shadow) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); const float h = g.FontSize * 1.00f; @@ -2814,7 +2814,7 @@ void ImGui::RenderBullet(ImVec2 pos) void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); ImVec2 a, b, c; @@ -2837,7 +2837,7 @@ void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) // 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) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const char* text_display_end; if (hide_text_after_double_hash) @@ -2876,7 +2876,7 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex // } void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); if (g.LogEnabled) { @@ -2899,7 +2899,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items // FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; for (int i = g.Windows.Size-1; i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; @@ -2923,7 +2923,7 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) // NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding) bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); // Clip @@ -2938,13 +2938,13 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c bool ImGui::IsMouseHoveringWindow() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.HoveredWindow == g.CurrentWindow; } bool ImGui::IsMouseHoveringAnyWindow() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.HoveredWindow != NULL; } @@ -2974,7 +2974,7 @@ bool ImGui::IsKeyDown(int key_index) bool ImGui::IsKeyPressed(int key_index, bool repeat) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (key_index < 0) return false; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); const float t = g.IO.KeysDownDuration[key_index]; @@ -2992,7 +2992,7 @@ bool ImGui::IsKeyPressed(int key_index, bool repeat) bool ImGui::IsKeyReleased(int key_index) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (key_index < 0) return false; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); if (g.IO.KeysDownDurationPrev[key_index] >= 0.0f && !g.IO.KeysDown[key_index]) @@ -3002,14 +3002,14 @@ bool ImGui::IsKeyReleased(int key_index) bool ImGui::IsMouseDown(int button) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDown[button]; } bool ImGui::IsMouseClicked(int button, bool repeat) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); const float t = g.IO.MouseDownDuration[button]; if (t == 0.0f) @@ -3027,21 +3027,21 @@ bool ImGui::IsMouseClicked(int button, bool repeat) bool ImGui::IsMouseReleased(int button) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseReleased[button]; } bool ImGui::IsMouseDoubleClicked(int button) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDoubleClicked[button]; } bool ImGui::IsMouseDragging(int button, float lock_threshold) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); if (!g.IO.MouseDown[button]) return false; @@ -3058,7 +3058,7 @@ ImVec2 ImGui::GetMousePos() // NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.CurrentPopupStack.Size > 0) return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; return g.IO.MousePos; @@ -3066,7 +3066,7 @@ ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); if (lock_threshold < 0.0f) lock_threshold = g.IO.MouseDragThreshold; @@ -3078,7 +3078,7 @@ ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) void ImGui::ResetMouseDragDelta(int button) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr g.IO.MouseClickedPos[button] = g.IO.MousePos; @@ -3118,7 +3118,7 @@ bool ImGui::IsItemHoveredRect() bool ImGui::IsItemActive() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.ActiveId) { ImGuiWindow* window = GetCurrentWindowRead(); @@ -3152,7 +3152,7 @@ bool ImGui::IsItemVisible() // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. void ImGui::SetItemAllowOverlap() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.HoveredId == g.CurrentWindow->DC.LastItemID) g.HoveredIdAllowOverlap = true; if (g.ActiveId == g.CurrentWindow->DC.LastItemID) @@ -3188,7 +3188,7 @@ ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, float ou // Tooltip is stored and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous value. void ImGui::SetTooltipV(const char* fmt, va_list args) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args); } @@ -3202,7 +3202,7 @@ void ImGui::SetTooltip(const char* fmt, ...) static ImRect GetVisibleRect() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y) return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax); return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); @@ -3222,7 +3222,7 @@ void ImGui::EndTooltip() static bool IsPopupOpen(ImGuiID id) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const bool is_open = g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupID == id; return is_open; } @@ -3233,7 +3233,7 @@ static bool IsPopupOpen(ImGuiID id) // One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiID id = window->GetID(str_id); int current_stack_size = g.CurrentPopupStack.Size; @@ -3254,7 +3254,7 @@ void ImGui::OpenPopup(const char* str_id) static void CloseInactivePopups() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.OpenPopupStack.empty()) return; @@ -3285,7 +3285,7 @@ static void CloseInactivePopups() static ImGuiWindow* GetFrontMostModalRootWindow() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window) if (front_most_popup->Flags & ImGuiWindowFlags_Modal) @@ -3295,7 +3295,7 @@ static ImGuiWindow* GetFrontMostModalRootWindow() static void ClosePopupToLevel(int remaining) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (remaining > 0) ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window); else @@ -3307,14 +3307,14 @@ static void ClosePopup(ImGuiID id) { if (!IsPopupOpen(id)) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ClosePopupToLevel(g.OpenPopupStack.Size - 1); } // Close the popup we have begin-ed into. void ImGui::CloseCurrentPopup() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; int popup_idx = g.CurrentPopupStack.Size - 1; if (popup_idx < 0 || popup_idx > g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupID != g.OpenPopupStack[popup_idx].PopupID) return; @@ -3325,14 +3325,14 @@ void ImGui::CloseCurrentPopup() static inline void ClearSetNextWindowData() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0; g.SetNextWindowFocus = false; } static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImGuiID id = window->GetID(str_id); if (!IsPopupOpen(id)) @@ -3371,7 +3371,7 @@ bool ImGui::BeginPopup(const char* str_id) bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImGuiID id = window->GetID(name); if (!IsPopupOpen(id)) @@ -3507,7 +3507,7 @@ void ImGui::EndChild() // Helper to create a child window / scrolling region that looks like a normal widget frame. bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); @@ -3526,7 +3526,7 @@ void ImGui::EndChildFrame() static void CheckStacksSize(ImGuiWindow* window, bool write) { // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; int* p_backup = &window->DC.StackSizesBackup[0]; { int current = window->IDStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopID() { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot EndGroup() @@ -3568,7 +3568,7 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, ImGuiWindow* ImGui::FindWindowByName(const char* name) { // FIXME-OPT: Store sorted hashes -> pointers so we can do a bissection in a contiguous block - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiID id = ImHash(name, 0); for (int i = 0; i < g.Windows.Size; i++) if (g.Windows[i]->ID == id) @@ -3578,7 +3578,7 @@ ImGuiWindow* ImGui::FindWindowByName(const char* name) static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; // Create window the first time ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow)); @@ -3658,7 +3658,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; IM_ASSERT(name != NULL); // Window name required IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() @@ -4208,7 +4208,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us void ImGui::End() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGui::Columns(1, "#CloseColumns"); @@ -4234,7 +4234,7 @@ void ImGui::End() // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. static void Scrollbar(ImGuiWindow* window, bool horizontal) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); @@ -4332,7 +4332,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) // Moving window to front of display (which happens to be back of our sorted list) void ImGui::FocusWindow(ImGuiWindow* window) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing. g.FocusedWindow = window; @@ -4406,7 +4406,7 @@ float ImGui::CalcItemWidth() static void SetCurrentFont(ImFont* font) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? IM_ASSERT(font->Scale > 0.0f); g.Font = font; @@ -4417,7 +4417,7 @@ static void SetCurrentFont(ImFont* font) void ImGui::PushFont(ImFont* font) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (!font) font = g.IO.Fonts->Fonts[0]; SetCurrentFont(font); @@ -4427,7 +4427,7 @@ void ImGui::PushFont(ImFont* font) void ImGui::PopFont() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.CurrentWindow->DrawList->PopTextureID(); g.FontStack.pop_back(); SetCurrentFont(g.FontStack.empty() ? g.IO.Fonts->Fonts[0] : g.FontStack.back()); @@ -4477,7 +4477,7 @@ void ImGui::PopTextWrapPos() void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiColMod backup; backup.Col = idx; backup.PreviousValue = g.Style.Colors[idx]; @@ -4487,7 +4487,7 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) void ImGui::PopStyleColor(int count) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; while (count > 0) { ImGuiColMod& backup = g.ColorModifiers.back(); @@ -4499,7 +4499,7 @@ void ImGui::PopStyleColor(int count) static float* GetStyleVarFloatAddr(ImGuiStyleVar idx) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; switch (idx) { case ImGuiStyleVar_Alpha: return &g.Style.Alpha; @@ -4514,7 +4514,7 @@ static float* GetStyleVarFloatAddr(ImGuiStyleVar idx) static ImVec2* GetStyleVarVec2Addr(ImGuiStyleVar idx) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; switch (idx) { case ImGuiStyleVar_WindowPadding: return &g.Style.WindowPadding; @@ -4528,7 +4528,7 @@ static ImVec2* GetStyleVarVec2Addr(ImGuiStyleVar idx) void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; float* pvar = GetStyleVarFloatAddr(idx); IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a float. ImGuiStyleMod backup; @@ -4541,7 +4541,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImVec2* pvar = GetStyleVarVec2Addr(idx); IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a ImVec2. ImGuiStyleMod backup; @@ -4553,7 +4553,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) void ImGui::PopStyleVar(int count) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; while (count > 0) { ImGuiStyleMod& backup = g.StyleModifiers.back(); @@ -4621,31 +4621,31 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) bool ImGui::IsWindowHovered() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow); } bool ImGui::IsWindowFocused() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.FocusedWindow == g.CurrentWindow; } bool ImGui::IsRootWindowFocused() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.FocusedWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildFocused() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildHovered() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow); } @@ -4663,7 +4663,7 @@ float ImGui::GetWindowHeight() ImVec2 ImGui::GetWindowPos() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; return window->Pos; } @@ -4801,49 +4801,49 @@ void ImGui::SetWindowFocus(const char* name) void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowPosVal = pos; g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::SetNextWindowPosCenter(ImGuiSetCond cond) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX); g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowSizeVal = size; g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::SetNextWindowContentSize(const ImVec2& size) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowContentSizeVal = size; g.SetNextWindowContentSizeCond = ImGuiSetCond_Always; } void ImGui::SetNextWindowContentWidth(float width) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowContentSizeVal = ImVec2(width, g.SetNextWindowContentSizeCond ? g.SetNextWindowContentSizeVal.y : 0.0f); g.SetNextWindowContentSizeCond = ImGuiSetCond_Always; } void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowCollapsedVal = collapsed; g.SetNextWindowCollapsedCond = cond ? cond : ImGuiSetCond_Always; } void ImGui::SetNextWindowFocus() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextWindowFocus = true; } @@ -4892,19 +4892,19 @@ float ImGui::GetWindowContentRegionWidth() float ImGui::GetTextLineHeight() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.FontSize; } float ImGui::GetTextLineHeightWithSpacing() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.FontSize + g.Style.ItemSpacing.y; } float ImGui::GetItemsLineHeightWithSpacing() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; } @@ -4931,7 +4931,7 @@ ImVec2 ImGui::GetFontTexUvWhitePixel() void ImGui::SetWindowFontScale(float scale) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->FontWindowScale = scale; g.FontSize = window->CalcFontSize(); @@ -5076,7 +5076,7 @@ void ImGui::TextV(const char* fmt, va_list args) if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); TextUnformatted(g.TempBuffer, text_end); } @@ -5140,7 +5140,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; IM_ASSERT(text != NULL); const char* text_begin = text; if (text_end == NULL) @@ -5250,7 +5250,7 @@ void ImGui::AlignFirstTextHeightToWidgets() return; // Declare a dummy item size to that upcoming items that are smaller will center-align on the newly expanded line height. - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ItemSize(ImVec2(0, g.FontSize + g.Style.FramePadding.y*2), g.Style.FramePadding.y); ImGui::SameLine(0, 0); } @@ -5262,7 +5262,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float w = CalcItemWidth(); @@ -5292,7 +5292,7 @@ void ImGui::LabelText(const char* label, const char* fmt, ...) static inline bool IsWindowContentHoverable(ImGuiWindow* window) { // An active popup disable hovering on other windows (apart from its own children) - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (ImGuiWindow* focused_window = g.FocusedWindow) if (ImGuiWindow* focused_root_window = focused_window->RootWindow) if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) @@ -5303,7 +5303,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window) bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (flags & ImGuiButtonFlags_Disabled) @@ -5376,7 +5376,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -5415,7 +5415,7 @@ bool ImGui::Button(const char* label, const ImVec2& size_arg) // Small buttons fits within text without additional vertical spacing. bool ImGui::SmallButton(const char* label) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; float backup_padding_y = g.Style.FramePadding.y; g.Style.FramePadding.y = 0.0f; bool pressed = ButtonEx(label, ImVec2(0,0), ImGuiButtonFlags_AlignTextBaseLine); @@ -5503,7 +5503,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; // Default to using texture ID as ID. User can still push string/integer prefixes. @@ -5535,7 +5535,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I // Start logging ImGui output to TTY void ImGui::LogToTTY(int max_depth) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.LogEnabled) return; ImGuiWindow* window = GetCurrentWindowRead(); @@ -5550,7 +5550,7 @@ void ImGui::LogToTTY(int max_depth) // Start logging ImGui output to given file void ImGui::LogToFile(int max_depth, const char* filename) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.LogEnabled) return; ImGuiWindow* window = GetCurrentWindowRead(); @@ -5577,7 +5577,7 @@ void ImGui::LogToFile(int max_depth, const char* filename) // Start logging ImGui output to clipboard void ImGui::LogToClipboard(int max_depth) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.LogEnabled) return; ImGuiWindow* window = GetCurrentWindowRead(); @@ -5591,7 +5591,7 @@ void ImGui::LogToClipboard(int max_depth) void ImGui::LogFinish() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (!g.LogEnabled) return; @@ -5616,7 +5616,7 @@ void ImGui::LogFinish() // Helper to display logging buttons void ImGui::LogButtons() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGui::PushID("LogButtons"); const bool log_to_tty = ImGui::Button("Log To TTY"); @@ -5648,7 +5648,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) return true; // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiStorage* storage = window->DC.StateStorage; @@ -5695,7 +5695,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); @@ -5820,7 +5820,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags if (p_open) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; float button_sz = g.FontSize * 0.5f; if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(window->DC.LastItemRect.Max.x - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) *p_open = false; @@ -5844,7 +5844,7 @@ bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end); } @@ -5855,7 +5855,7 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end); } @@ -5917,7 +5917,7 @@ bool ImGui::TreeNode(const char* label) float ImGui::GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; float off_from_start; if (flags & ImGuiTreeNodeFlags_Framed) off_from_start = g.FontSize + (g.Style.FramePadding.x * 3.0f) - ((float)(int)(g.CurrentWindow->WindowPadding.x*0.5f) - 1); @@ -5928,7 +5928,7 @@ float ImGui::GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags) void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; g.SetNextTreeNodeOpenVal = is_open; g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiSetCond_Always; } @@ -5985,7 +5985,7 @@ void ImGui::Bullet() if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); @@ -6008,7 +6008,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const char* text_begin = g.TempBuffer; @@ -6144,7 +6144,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b // Create text input in place of a slider (when CTRL+Clicking on slider) bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) @@ -6212,7 +6212,7 @@ float ImGui::RoundScalar(float value, int decimal_precision) bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); const ImGuiStyle& style = g.Style; @@ -6349,7 +6349,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const float w = CalcItemWidth(); @@ -6412,7 +6412,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); @@ -6487,7 +6487,7 @@ bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_mi if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); @@ -6529,7 +6529,7 @@ bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); @@ -6567,7 +6567,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; // Draw frame @@ -6646,7 +6646,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const float w = CalcItemWidth(); @@ -6709,7 +6709,7 @@ bool ImGui::DragFloatN(const char* label, float* v, int components, float v_spee if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); @@ -6751,7 +6751,7 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGui::PushID(label); ImGui::BeginGroup(); PushMultiItemsWidths(2); @@ -6787,7 +6787,7 @@ bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, i if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); @@ -6829,7 +6829,7 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_ if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGui::PushID(label); ImGui::BeginGroup(); PushMultiItemsWidths(2); @@ -6854,7 +6854,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -6996,7 +6996,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; ImVec2 pos = window->DC.CursorPos; @@ -7031,7 +7031,7 @@ bool ImGui::Checkbox(const char* label, bool* v) if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -7094,7 +7094,7 @@ bool ImGui::RadioButton(const char* label, bool active) if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -7418,7 +7418,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiIO& io = g.IO; const ImGuiStyle& style = g.Style; @@ -7992,7 +7992,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -8065,7 +8065,7 @@ bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); @@ -8108,7 +8108,7 @@ bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextF if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; bool value_changed = false; ImGui::BeginGroup(); ImGui::PushID(label); @@ -8201,7 +8201,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const float w = CalcItemWidth(); @@ -8310,7 +8310,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) @@ -8491,7 +8491,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImVec2 pos = window->DC.CursorPos; ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); @@ -8525,7 +8525,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool ImGui::BeginMainMenuBar() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); ImGui::SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.FontBaseSize + g.Style.FramePadding.y * 2.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); @@ -8591,7 +8591,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); @@ -8701,7 +8701,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID("#colorbutton"); const float square_size = g.FontSize; @@ -8742,7 +8742,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) if (window->SkipItems) return false; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const float w_full = CalcItemWidth(); @@ -8903,7 +8903,7 @@ void ImGui::Separator() window->DrawList->AddLine(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border)); - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.LogEnabled) ImGui::LogText(IM_NEWLINE "--------------------------------"); @@ -9003,7 +9003,7 @@ void ImGui::SameLine(float pos_x, float spacing_w) if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (pos_x != 0.0f) { if (spacing_w < 0.0f) spacing_w = 0.0f; @@ -9026,7 +9026,7 @@ void ImGui::NextColumn() if (window->SkipItems) return; - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (window->DC.ColumnsCount > 1) { ImGui::PopItemWidth(); @@ -9072,7 +9072,7 @@ static float GetDraggedColumnOffset(int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = ImGui::GetCurrentWindowRead(); IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. IM_ASSERT(g.ActiveId == window->DC.ColumnsSetID + ImGuiID(column_index)); @@ -9085,7 +9085,7 @@ static float GetDraggedColumnOffset(int column_index) float ImGui::GetColumnOffset(int column_index) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); if (column_index < 0) column_index = window->DC.ColumnsCurrent; @@ -9140,7 +9140,7 @@ static void PushColumnClipRect(int column_index) void ImGui::Columns(int columns_count, const char* id, bool border) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); @@ -9232,7 +9232,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) void ImGui::Indent() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->DC.IndentX += g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; @@ -9240,7 +9240,7 @@ void ImGui::Indent() void ImGui::Unindent() { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->DC.IndentX -= g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; @@ -9397,7 +9397,7 @@ static const char* GetClipboardTextFn_DefaultImpl() // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers static void SetClipboardTextFn_DefaultImpl(const char* text) { - ImGuiState& g = *GImGui; + ImGuiContext& g = *GImGui; if (g.PrivateClipboard) { ImGui::MemFree(g.PrivateClipboard); @@ -9534,7 +9534,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; - ImGuiState& g = *GImGui; // Access private state + ImGuiContext& g = *GImGui; // Access private state Funcs::NodeWindows(g.Windows, "Windows"); if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.RenderDrawLists[0].Size)) { diff --git a/imgui.h b/imgui.h index d54798035..ad97c2a12 100644 --- a/imgui.h +++ b/imgui.h @@ -54,7 +54,7 @@ struct ImGuiTextFilter; // Parse and apply text filters. In format " struct ImGuiTextBuffer; // Text buffer for logging/accumulating text struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom callbacks (advanced) struct ImGuiListClipper; // Helper to manually clip large list of items -struct ImGuiState; // ImGui context (opaque) +struct ImGuiContext; // ImGui context (opaque) // Enumerations (declared as int for compatibility and to not pollute the top of this file) typedef unsigned int ImU32; @@ -445,10 +445,10 @@ namespace ImGui // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. IMGUI_API const char* GetVersion(); - IMGUI_API ImGuiState* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); - IMGUI_API void DestroyContext(ImGuiState* ctx); - IMGUI_API ImGuiState* GetCurrentContext(); - IMGUI_API void SetCurrentContext(ImGuiState* ctx); + IMGUI_API ImGuiContext* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); + IMGUI_API void DestroyContext(ImGuiContext* ctx); + IMGUI_API ImGuiContext* GetCurrentContext(); + IMGUI_API void SetCurrentContext(ImGuiContext* ctx); // Obsolete (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/imgui_internal.h b/imgui_internal.h index 4eee4f7dd..bf4f73f12 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -70,7 +70,7 @@ namespace ImGuiStb // Context //----------------------------------------------------------------------------- -extern IMGUI_API ImGuiState* GImGui; // current implicit ImGui context pointer +extern IMGUI_API ImGuiContext* GImGui; // current implicit ImGui context pointer //----------------------------------------------------------------------------- // Helpers @@ -344,7 +344,7 @@ struct ImGuiPopupRef }; // Main state for ImGui -struct ImGuiState +struct ImGuiContext { bool Initialized; ImGuiIO IO; @@ -436,7 +436,7 @@ struct ImGuiState int CaptureKeyboardNextFrame; char TempBuffer[1024*3+1]; // temporary text buffer - ImGuiState() + ImGuiContext() { Initialized = false; Font = NULL; @@ -672,8 +672,8 @@ namespace ImGui // If this ever crash because g.CurrentWindow is NULL it means that either // - ImGui::NewFrame() has never been called, which is illegal. // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. - inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; } - inline ImGuiWindow* GetCurrentWindow() { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; } + inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } + inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; } IMGUI_API ImGuiWindow* GetParentWindow(); IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API void FocusWindow(ImGuiWindow* window); From 834bfe4af5eb8ff7e0d04014ca156b67efa64aaf Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 20:11:14 +0200 Subject: [PATCH 045/105] Examples: DirectX11: Fixed handle leak + minor coding style fix for #640 --- .../directx11_example/imgui_impl_dx11.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 33afb7eaf..c43c6cf17 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -34,8 +34,8 @@ static ID3D11SamplerState* g_pFontSampler = NULL; static ID3D11ShaderResourceView*g_pFontTextureView = NULL; static ID3D11RasterizerState* g_pRasterizerState = NULL; static ID3D11BlendState* g_pBlendState = NULL; +static ID3D11DepthStencilState* g_pDepthStencilState = NULL; static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; -static ID3D11DepthStencilState* g_pDSState = NULL; struct VERTEX_CONSTANT_BUFFER { @@ -128,6 +128,8 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ID3D11BlendState* BlendState; FLOAT BlendFactor[4]; UINT SampleMask; + UINT StencilRef; + ID3D11DepthStencilState* DepthStencilState; ID3D11ShaderResourceView* PSShaderResource; ID3D11SamplerState* PSSampler; ID3D11PixelShader* PS; @@ -139,8 +141,6 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; - ID3D11DepthStencilState* DepthStencilState; - UINT StencilRef; }; BACKUP_DX11_STATE old; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; @@ -148,6 +148,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); ctx->RSGetState(&old.RS); ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); old.PSInstancesCount = old.VSInstancesCount = 256; @@ -158,7 +159,6 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); - ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); // Setup viewport D3D11_VIEWPORT vp; @@ -185,8 +185,8 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) // Setup render state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); ctx->RSSetState(g_pRasterizerState); - ctx->OMSetDepthStencilState( g_pDSState, 1 ); // Render command lists int vtx_offset = 0; @@ -218,6 +218,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); @@ -229,7 +230,6 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); - ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -454,16 +454,15 @@ bool ImGui_ImplDX11_CreateDeviceObjects() g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); } - // Create Depth-Stencil State { D3D11_DEPTH_STENCIL_DESC desc; ZeroMemory(&desc, sizeof(desc)); - desc.StencilEnable = false; desc.DepthEnable = true; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_ALWAYS; - g_pd3dDevice->CreateDepthStencilState( &desc, &g_pDSState ); + desc.StencilEnable = false; + g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); } ImGui_ImplDX11_CreateFontsTexture(); @@ -482,6 +481,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } + if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } @@ -489,7 +489,6 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } - if (g_pDSState) { g_pDSState->Release(); g_pDSState = NULL; } } bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context) From f4633d09acbbcdbc948b55b82edf93595b27db9f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 20:19:04 +0200 Subject: [PATCH 046/105] Examples: DirectX10, DirectX11: Removed seemingly unnecessary bunch of rasterizer state creation code. --- examples/directx10_example/main.cpp | 21 --------------------- examples/directx11_example/main.cpp | 21 --------------------- 2 files changed, 42 deletions(-) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index f47f9d5d9..a418da9f8 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -63,27 +63,6 @@ HRESULT CreateDeviceD3D(HWND hWnd) if (D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice) != S_OK) return E_FAIL; - // Setup rasterizer - { - D3D10_RASTERIZER_DESC RSDesc; - memset(&RSDesc, 0, sizeof(D3D10_RASTERIZER_DESC)); - RSDesc.FillMode = D3D10_FILL_SOLID; - RSDesc.CullMode = D3D10_CULL_NONE; - RSDesc.FrontCounterClockwise = FALSE; - RSDesc.DepthBias = 0; - RSDesc.SlopeScaledDepthBias = 0.0f; - RSDesc.DepthBiasClamp = 0; - RSDesc.DepthClipEnable = TRUE; - RSDesc.ScissorEnable = TRUE; - RSDesc.AntialiasedLineEnable = FALSE; - RSDesc.MultisampleEnable = (sd.SampleDesc.Count > 1) ? TRUE : FALSE; - - ID3D10RasterizerState* pRState = NULL; - g_pd3dDevice->CreateRasterizerState(&RSDesc, &pRState); - g_pd3dDevice->RSSetState(pRState); - pRState->Release(); - } - CreateRenderTarget(); return S_OK; diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index d90f49c87..a47e22d01 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -65,27 +65,6 @@ HRESULT CreateDeviceD3D(HWND hWnd) if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) return E_FAIL; - // Setup rasterizer - { - D3D11_RASTERIZER_DESC RSDesc; - memset(&RSDesc, 0, sizeof(D3D11_RASTERIZER_DESC)); - RSDesc.FillMode = D3D11_FILL_SOLID; - RSDesc.CullMode = D3D11_CULL_NONE; - RSDesc.FrontCounterClockwise = FALSE; - RSDesc.DepthBias = 0; - RSDesc.SlopeScaledDepthBias = 0.0f; - RSDesc.DepthBiasClamp = 0; - RSDesc.DepthClipEnable = TRUE; - RSDesc.ScissorEnable = TRUE; - RSDesc.AntialiasedLineEnable = FALSE; - RSDesc.MultisampleEnable = (sd.SampleDesc.Count > 1) ? TRUE : FALSE; - - ID3D11RasterizerState* pRState = NULL; - g_pd3dDevice->CreateRasterizerState(&RSDesc, &pRState); - g_pd3dDeviceContext->RSSetState(pRState); - pRState->Release(); - } - CreateRenderTarget(); return S_OK; From 656b1e848cc77a7a0f057113d8bccc49d5c04cda Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 20:53:55 +0200 Subject: [PATCH 047/105] Examples: DirectX11: Fixed uninitialized fields. Disabling depth-write (#640, #636) --- examples/directx11_example/imgui_impl_dx11.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index c43c6cf17..d595e6c01 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -454,14 +454,17 @@ bool ImGui_ImplDX11_CreateDeviceObjects() g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); } - // Create Depth-Stencil State + // Create depth-stencil State { D3D11_DEPTH_STENCIL_DESC desc; ZeroMemory(&desc, sizeof(desc)); - desc.DepthEnable = true; + desc.DepthEnable = false; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_ALWAYS; desc.StencilEnable = false; + desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + desc.BackFace = desc.FrontFace; g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); } From 2ef766a1cec4e3cf71e0920a6ca0efd0edbbe4bc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 20:57:38 +0200 Subject: [PATCH 048/105] Examples: DirectX10: Apply depth-stencil state like DirectX11 example (#640, #636) --- .../directx10_example/imgui_impl_dx10.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index f0e57f721..15dbed200 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -34,6 +34,7 @@ static ID3D10SamplerState* g_pFontSampler = NULL; static ID3D10ShaderResourceView*g_pFontTextureView = NULL; static ID3D10RasterizerState* g_pRasterizerState = NULL; static ID3D10BlendState* g_pBlendState = NULL; +static ID3D10DepthStencilState* g_pDepthStencilState = NULL; static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; struct VERTEX_CONSTANT_BUFFER @@ -125,6 +126,8 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) ID3D10BlendState* BlendState; FLOAT BlendFactor[4]; UINT SampleMask; + UINT StencilRef; + ID3D10DepthStencilState* DepthStencilState; ID3D10ShaderResourceView* PSShaderResource; ID3D10SamplerState* PSSampler; ID3D10PixelShader* PS; @@ -141,6 +144,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); ctx->RSGetState(&old.RS); ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); ctx->PSGetShader(&old.PS); @@ -176,6 +180,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) // Setup render state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); ctx->RSSetState(g_pRasterizerState); // Render command lists @@ -208,6 +213,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); @@ -447,6 +453,20 @@ bool ImGui_ImplDX10_CreateDeviceObjects() g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); } + // Create depth-stencil State + { + D3D10_DEPTH_STENCIL_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.DepthEnable = false; + desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D10_COMPARISON_ALWAYS; + desc.StencilEnable = false; + desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; + desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS; + desc.BackFace = desc.FrontFace; + g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); + } + ImGui_ImplDX10_CreateFontsTexture(); return true; @@ -463,6 +483,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects() if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } + if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } From 36ca8a8194e86999fb83547b8ec302cb2d4b1b4b Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 7 May 2016 21:09:53 +0200 Subject: [PATCH 049/105] Minor warnings fixes. --- imgui.cpp | 2 +- stb_rect_pack.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3dfa7cfff..80d84737f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6274,7 +6274,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v { // Positive: rescale to the positive range before powering float a; - if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) + if (fabsf(linear_zero_pos - 1.0f) > 1.e-6f) a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); else a = normalized_pos; diff --git a/stb_rect_pack.h b/stb_rect_pack.h index d7e899c4d..fafd88971 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -268,9 +268,9 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, } // find minimum y position if it starts at x1 -static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) +static int stbrp__skyline_find_min_y(stbrp_context *, stbrp_node *first, int x0, int width, int *pwaste) { - (void)c; + //(void)c; stbrp_node *node = first; int x1 = x0 + width; int min_y, visited_width, waste_area; From 8a0d3b9628d4b92a2d7d2a4a7b9424a745c76d9d Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 8 May 2016 11:49:21 +0200 Subject: [PATCH 050/105] Examples; DirectX10/11: Added comments about removing dependency on d3dcompiler DLL (#638) --- examples/directx10_example/imgui_impl_dx10.cpp | 6 ++++++ examples/directx10_example/main.cpp | 1 - examples/directx11_example/imgui_impl_dx11.cpp | 6 ++++++ examples/directx11_example/main.cpp | 1 - 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 15dbed200..bccee87e3 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -343,6 +343,12 @@ bool ImGui_ImplDX10_CreateDeviceObjects() if (g_pFontSampler) ImGui_ImplDX10_InvalidateDeviceObjects(); + // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) + // If you would like to use this DX11 sample code but remove this dependency you can: + // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [prefered solution] + // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. + // See https://github.com/ocornut/imgui/pull/638 for sources and details. + // Create the vertex shader { static const char* vertexShader = diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index a418da9f8..fb98cad16 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -5,7 +5,6 @@ #include "imgui_impl_dx10.h" #include #include -#include #define DIRECTINPUT_VERSION 0x0800 #include #include diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index d595e6c01..11f66f0e9 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -345,6 +345,12 @@ bool ImGui_ImplDX11_CreateDeviceObjects() if (g_pFontSampler) ImGui_ImplDX11_InvalidateDeviceObjects(); + // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) + // If you would like to use this DX11 sample code but remove this dependency you can: + // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [prefered solution] + // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. + // See https://github.com/ocornut/imgui/pull/638 for sources and details. + // Create the vertex shader { static const char* vertexShader = diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index a47e22d01..e3fe5aa71 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -4,7 +4,6 @@ #include #include "imgui_impl_dx11.h" #include -#include #define DIRECTINPUT_VERSION 0x0800 #include #include From aa11934efafe4db75993e23aacacf9ed8b1dd40c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 8 May 2016 17:12:54 +0200 Subject: [PATCH 051/105] Comments to clarify default shared ImFontAtlas and current context pointer thread-safety (#586, #591) --- imgui.cpp | 12 ++++++------ imgui.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f031f9903..171b64b4f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -696,15 +696,15 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); // Context //----------------------------------------------------------------------------- -// We access everything through this pointer (always assumed to be != NULL) -// You can swap the pointer to a different context by calling ImGui::SetCurrentContext() +// Default context, default font atlas. +// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable. static ImGuiContext GImDefaultContext; -ImGuiContext* GImGui = &GImDefaultContext; - -// Statically allocated default font atlas. This is merely a maneuver to keep ImFontAtlas definition at the bottom of the .h file (otherwise it'd be inside ImGuiIO) -// Also we wouldn't be able to new() one at this point, before users have a chance to setup their allocator. static ImFontAtlas GImDefaultFontAtlas; +// Current context pointer. Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext() +// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by (A) having two instances of the ImGui code under different namespaces or (B) change this variable to be TLS. Further development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 +ImGuiContext* GImGui = &GImDefaultContext; + //----------------------------------------------------------------------------- // User facing structures //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index ad97c2a12..2ba21a408 100644 --- a/imgui.h +++ b/imgui.h @@ -444,6 +444,7 @@ namespace ImGui IMGUI_API void SetClipboardText(const char* text); // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. + // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. IMGUI_API const char* GetVersion(); IMGUI_API ImGuiContext* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); IMGUI_API void DestroyContext(ImGuiContext* ctx); From 4b5a4cae09d0efd32c64b510490672d35bbccb51 Mon Sep 17 00:00:00 2001 From: cosmy1 Date: Mon, 9 May 2016 00:21:05 +0200 Subject: [PATCH 052/105] Fix compilation errors when disabling test windows. --- imgui_demo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c19e2b5bf..cdeb2cef8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2459,7 +2459,7 @@ static void ShowExampleAppLongText(bool* p_open) #else void ImGui::ShowTestWindow(bool*) {} -void ImGui::ShowUserGuide(bool*) {} -void ImGui::ShowStyleEditor(bool*) {} +void ImGui::ShowUserGuide() {} +void ImGui::ShowStyleEditor(ImGuiStyle*) {} #endif From a59a04f4d0822b69150433fb7cbf70e944874c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 9 May 2016 13:27:44 -0700 Subject: [PATCH 053/105] Fixed iOS/OSX build. --- imgui.cpp | 3 +-- imgui_demo.cpp | 3 +-- imgui_draw.cpp | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 171b64b4f..d9ea1d2ef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -621,8 +621,7 @@ #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' // -#endif -#ifdef __GNUC__ +#elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c19e2b5bf..9a6a85227 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -31,8 +31,7 @@ #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // -#endif -#ifdef __GNUC__ +#elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function diff --git a/imgui_draw.cpp b/imgui_draw.cpp index efbda15b8..57b13bf82 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -38,8 +38,7 @@ #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // -#endif -#ifdef __GNUC__ +#elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value From b630cb5b427081e724d2b452ba7d20bcddf6a686 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 10 May 2016 17:00:42 +0200 Subject: [PATCH 054/105] ImGuiWindow: Storing ParentWindow (#615, #646) --- imgui.cpp | 2 ++ imgui_internal.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index d9ea1d2ef..a849ba5a3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1641,6 +1641,7 @@ ImGuiWindow::ImGuiWindow(const char* name) DrawList->_OwnerName = Name; RootWindow = NULL; RootNonPopupWindow = NULL; + ParentWindow = NULL; FocusIdxAllCounter = FocusIdxTabCounter = -1; FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = IM_INT_MAX; @@ -3759,6 +3760,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--) if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) break; + window->ParentWindow = parent_window; window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. diff --git a/imgui_internal.h b/imgui_internal.h index bf4f73f12..6c90e53a6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -636,7 +636,8 @@ struct IMGUI_API ImGuiWindow float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. - ImGuiWindow* RootNonPopupWindow; // If we are a child widnow, this is pointing to the first non-child non-popup parent window. Else point to ourself. + ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself. + ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL. // Focus int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() From 8648346eab5a485c5006a6a9473fe6c9d3eb4fe6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 10 May 2016 17:02:10 +0200 Subject: [PATCH 055/105] Modal: fixed non-child window stacked over a modal losing its hoverabilty/focusability (#615, #604) --- imgui.cpp | 5 ++++- imgui_demo.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a849ba5a3..b77a00aa9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2085,7 +2085,10 @@ void ImGui::NewFrame() if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) { g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); - if (g.HoveredRootWindow != modal_window) + ImGuiWindow* window = g.HoveredRootWindow; + while (window && window != modal_window) + window = window->ParentWindow; + if (!window) g.HoveredRootWindow = g.HoveredWindow = NULL; } else diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9a6a85227..3a2296e67 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1244,6 +1244,9 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); ImGui::Separator(); + //static int dummy_i = 0; + //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0"); + static bool dont_ask_me_next_time = false; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); From 91f11fb1bd4d53ec5933c319650ac2ccb5da286a Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 11 May 2016 09:58:43 +0200 Subject: [PATCH 056/105] Comments / todos --- imgui.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index b77a00aa9..b3d87cce2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -556,6 +556,9 @@ - style: WindowPadding needs to be EVEN needs the 0.5 multiplier probably have a subtle effect on clip rectangle - text: simple markup language for color change? - font: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier. + - font: small opt: for monospace font (like the defalt one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance + - font: add support for kerning, probably optional. perhaps default to (32..128)^2 matrix ~ 36KB then hash fallback. + - font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize) - font: fix AddRemapChar() to work before font has been built. - log: LogButtons() options for specifying depth and/or hiding depth slider - log: have more control over the log scope (e.g. stop logging when leaving current tree node scope) From ed20fcf9d5399d1e59bc40c2fd59d71f5ee9c95a Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 11 May 2016 10:31:30 +0200 Subject: [PATCH 057/105] Fixed incorrect parameter to ButtonBehavior() in Columns code - had no side-effect (#649) Broken in 3eabad0321b7b7e949a87b3c6339fc5bea3403e7 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index b3d87cce2..78622fffe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9179,7 +9179,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) continue; bool hovered, held; - ButtonBehavior(column_rect, column_id, &hovered, &held, true); + ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; From 2f55dc1f335a3d63591af4b10a8a83545a15ab3b Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 12 May 2016 11:58:05 +0200 Subject: [PATCH 058/105] ImFontConfig: Clarified persistence requirement of GlyphRanges array (#651) --- imgui.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 2ba21a408..0f260ed45 100644 --- a/imgui.h +++ b/imgui.h @@ -1254,7 +1254,7 @@ struct ImFontConfig int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. bool PixelSnapH; // false // Align every character to pixel boundary (if enabled, set OversampleH/V to 1) ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs - const ImWchar* GlyphRanges; // // List of Unicode range (2 value per range, values are inclusive, zero-terminated list) + const ImWchar* GlyphRanges; // // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). bool MergeGlyphCenterV; // false // When merging (multiple ImFontInput for one ImFont), vertically center new glyphs instead of aligning their baseline @@ -1273,6 +1273,7 @@ struct ImFontConfig // 3. Upload the pixels data into a texture within your graphics system. // 4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during rendering to identify the texture. // 5. Call ClearTexData() to free textures memory on the heap. +// NB: If you use a 'glyph_ranges' array you need to make sure that your array persist up until the ImFont is cleared. We only copy the pointer, not the data. struct ImFontAtlas { IMGUI_API ImFontAtlas(); From b628acbb5271f92db3903c4b2f9fff0d2b1b5d7b Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 12 May 2016 20:59:20 +0200 Subject: [PATCH 059/105] StyleEditor: comments (#652) --- imgui.h | 2 +- imgui_demo.cpp | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 0f260ed45..fecfe3bf7 100644 --- a/imgui.h +++ b/imgui.h @@ -110,7 +110,7 @@ namespace ImGui IMGUI_API void Render(); // ends the ImGui frame, finalize rendering data, then call your io.RenderDrawListsFn() function if set. IMGUI_API void Shutdown(); IMGUI_API void ShowUserGuide(); // help block - IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // style editor block + IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // style editor block. you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) IMGUI_API void ShowTestWindow(bool* p_open = NULL); // test window demonstrating ImGui features IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // metrics window for debugging ImGui diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 768c44807..8f48fab35 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1554,9 +1554,11 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { ImGuiStyle& style = ImGui::GetStyle(); - const ImGuiStyle def; // Default style + // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to the default style) + const ImGuiStyle default_style; // Default style if (ImGui::Button("Revert Style")) - style = ref ? *ref : def; + style = ref ? *ref : default_style; + if (ref) { ImGui::SameLine(); @@ -1611,7 +1613,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { const ImVec4& col = style.Colors[i]; const char* name = ImGui::GetStyleColName(i); - if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0) + if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 22 - (int)strlen(name), "", col.x, col.y, col.z, col.w); } ImGui::LogFinish(); @@ -1640,9 +1642,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) continue; ImGui::PushID(i); ImGui::ColorEdit4(name, (float*)&style.Colors[i], true); - if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0) + if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) { - ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : def.Colors[i]; + ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : default_style.Colors[i]; if (ref) { ImGui::SameLine(); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; } } ImGui::PopID(); From 8d5b2fba95907d84fb541bddaec900b2e197297c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 12 May 2016 23:12:55 +0200 Subject: [PATCH 060/105] Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, being inconsistent and causing visual artefact (#655) Broke the meaning of TitleBg and TitleBgActive. Only affect values where Alpha<1.0f. Fixed default theme. --- imgui.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 78622fffe..9137f450f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -153,6 +153,14 @@ 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/05/12 (1.49) - title bar (using TitleBg/TitleBgActive colors) isn't rendered over a window background (WindowBg color) anymore. + If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. + This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given that color and the WindowBg color. + ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) + { + float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; + return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); + } - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). @@ -746,9 +754,9 @@ ImGuiStyle::ImGuiStyle() 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); Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); - Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.50f, 1.00f, 0.45f); + Colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); - Colors[ImGuiCol_TitleBgActive] = ImVec4(0.50f, 0.50f, 1.00f, 0.55f); + Colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); @@ -4056,7 +4064,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bg_color.w = bg_alpha; bg_color.w *= style.Alpha; if (bg_color.w > 0.0f) - window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding); + window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 15 : 4|8); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) From a2a5d715829ebe37162c613c8649a71f6ff4590f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 12 May 2016 23:13:54 +0200 Subject: [PATCH 061/105] Demo: Tweak irritating pink color. --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8f48fab35..3961b220c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1218,7 +1218,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::EndPopup(); } - static ImVec4 color = ImColor(1.0f, 0.0f, 1.0f, 1.0f); + static ImVec4 color = ImColor(0.8f, 0.5f, 1.0f, 1.0f); ImGui::ColorButton(color); if (ImGui::BeginPopupContextItem("color context menu")) { From e1e2752dcbfb1160b355d83bbc9301e36dcacd20 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 May 2016 10:50:59 +0200 Subject: [PATCH 062/105] Fixed repeating button behavior triggering twice, typically affect the +/- of InputInt/InputFloat and user repeating buttons (#656) + Took note of further work Broken in 547f34cf22640526b63f02f50c73ef9409e8acab --- imgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 9137f450f..bee8bb791 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5357,7 +5357,11 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool pressed = true; SetActiveID(0); } - if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && ImGui::IsMouseClicked(0, true)) + + // 'Repeat' mode acts when held regardless of _PressedOn flags + // FIXME: Need to clarify the repeat behavior with those differents flags. Currently the typical PressedOnClickRelease+Repeat will add an extra click on final release (hardly noticeable with repeat rate, but technically an issue) + // Relies on repeat behavior of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. + if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && ImGui::IsMouseClicked(0, true)) pressed = true; } } From f48f9a30ef5f598e3fa9ac42e07a89b78c5dbc74 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 May 2016 11:13:54 +0200 Subject: [PATCH 063/105] ButtonBehavior(), fixed subtle old bug when a repeating button would also return true on release + comments (#656) --- imgui.cpp | 18 ++++++++++++------ imgui.h | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bee8bb791..a9e648926 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5341,7 +5341,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool SetHoveredID(id); if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { - if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) // Most common type + // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat + // PressedOnClickRelease | * | .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds + // PressedOnClick | | .. + // PressedOnRelease | | .. (NOT on release) + // PressedOnDoubleClick | | .. + if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { SetActiveID(id, window); // Hold on ID FocusWindow(window); @@ -5354,13 +5359,13 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) { - pressed = true; + if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + pressed = true; SetActiveID(0); } - // 'Repeat' mode acts when held regardless of _PressedOn flags - // FIXME: Need to clarify the repeat behavior with those differents flags. Currently the typical PressedOnClickRelease+Repeat will add an extra click on final release (hardly noticeable with repeat rate, but technically an issue) - // Relies on repeat behavior of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. + // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). + // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && ImGui::IsMouseClicked(0, true)) pressed = true; } @@ -5376,7 +5381,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool else { if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) - pressed = true; + if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + pressed = true; SetActiveID(0); } } diff --git a/imgui.h b/imgui.h index fecfe3bf7..38e36762b 100644 --- a/imgui.h +++ b/imgui.h @@ -732,7 +732,7 @@ struct ImGuiIO float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array - float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds. (for actions where 'repeat' is active) + float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. void* UserData; // = NULL // Store your own data for retrieval by callbacks. From e79d2828c447647cb1ed0554f8df5484259bcb09 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 May 2016 23:10:16 +0200 Subject: [PATCH 064/105] Metrics window: coarse clipping the detailed vertex buffer for pleasure and benefits. --- imgui.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a9e648926..5680cc046 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9507,12 +9507,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); continue; } + ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); if (show_clip_rects && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; ImRect vtxs_rect; - ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); @@ -9520,20 +9520,22 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (!pcmd_node_open) continue; - for (int i = elem_offset; i+2 < elem_offset + (int)pcmd->ElemCount; i += 3) + ImGuiListClipper clipper(pcmd->ElemCount/3, ImGui::GetTextLineHeight()*3 + ImGui::GetStyle().ItemSpacing.y); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) { - ImVec2 triangles_pos[3]; char buf[300], *buf_p = buf; - for (int n = 0; n < 3; n++) + ImVec2 triangles_pos[3]; + for (int n = 0; n < 3; n++, vtx_i++) { - ImDrawVert& v = draw_list->VtxBuffer[(draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data[i+n] : i+n]; + ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; triangles_pos[n] = v.pos; - buf_p += sprintf(buf_p, "vtx %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", i+n, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle } + clipper.End(); ImGui::TreePop(); } overlay_draw_list->PopClipRect(); From 39bda5ea09ec94d31590cc7a3d515a30a1f6d9a5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 May 2016 10:22:25 +0200 Subject: [PATCH 065/105] Fixed a IMGUI_API->inline case (#657, #349) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 38e36762b..644885038 100644 --- a/imgui.h +++ b/imgui.h @@ -791,7 +791,7 @@ struct ImGuiIO // Functions IMGUI_API void AddInputCharacter(ImWchar c); // Helper to add a new character into InputCharacters[] IMGUI_API void AddInputCharactersUTF8(const char* utf8_chars); // Helper to add new characters into InputCharacters[] from an UTF-8 string - IMGUI_API void ClearInputCharacters() { InputCharacters[0] = 0; } // Helper to clear the text input buffer + inline void ClearInputCharacters() { InputCharacters[0] = 0; } // Helper to clear the text input buffer //------------------------------------------------------------------ // Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application From 431eaf1abe15ec21a47b7c44a8e168af75249c2f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 May 2016 15:35:50 +0200 Subject: [PATCH 066/105] Comments to clarify what float[2] int[2] etc. are. May switch to pointers? (#659) --- imgui.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 644885038..c201b077e 100644 --- a/imgui.h +++ b/imgui.h @@ -261,8 +261,8 @@ namespace ImGui IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0 IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); IMGUI_API bool ColorButton(const ImVec4& col, bool small_height = false, bool outline_border = true); - IMGUI_API bool ColorEdit3(const char* label, float col[3]); - IMGUI_API bool ColorEdit4(const char* label, float col[4], bool show_alpha = true); + IMGUI_API bool ColorEdit3(const char* label, float col[3]); // Hint: 'float col[3]' function argument is same as 'float* col'. You can pass address of first element out of a contiguous set, e.g. &myvector.x + IMGUI_API bool ColorEdit4(const char* label, float col[4], bool show_alpha = true); // " IMGUI_API void ColorEditMode(ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and should be obsoleted. IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); @@ -271,6 +271,7 @@ namespace ImGui IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL); // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) + // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, remember than a 'float v[3]' function argument is the same as 'float* v'. You can pass address of your first element out of a contiguous set, e.g. &myvector.x 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); From 9e6ed0991df75964f96ba64fbd79a50b61b74bae Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 May 2016 16:03:15 +0200 Subject: [PATCH 067/105] Demo: clarified misleading example (#660) --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3961b220c..c252324f2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2440,7 +2440,7 @@ static void ShowExampleAppLongText(bool* p_open) { // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); - ImGuiListClipper clipper(lines, ImGui::GetTextLineHeight()); + ImGuiListClipper clipper(lines, ImGui::GetTextLineHeightWithSpacing()); // Here we changed spacing is zero anyway so we could use GetTextLineHeight(), but _WithSpacing() is typically more correct for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) ImGui::Text("%i The quick brown fox jumps over the lazy dog\n", i); clipper.End(); From 339e191c53b7ce025e5e0fa049ad24e7a4d42c9d Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 May 2016 18:08:41 +0200 Subject: [PATCH 068/105] Demo: Console: Add a "Scroll to bottom" button (#662) --- imgui_demo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c252324f2..fa4f026d8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2002,7 +2002,8 @@ struct ExampleAppConsole if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); - if (ImGui::SmallButton("Clear")) ClearLog(); + if (ImGui::SmallButton("Clear")) ClearLog(); ImGui::SameLine(); + if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true; //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } ImGui::Separator(); From 790275eae234bcaef1c94dcc6d54ab6090671f68 Mon Sep 17 00:00:00 2001 From: Trezanik Date: Mon, 16 May 2016 01:02:09 +0100 Subject: [PATCH 069/105] Example: DirectX9: Backup and restore all state --- examples/directx9_example/imgui_impl_dx9.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 3db8c8c96..ba67d026c 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -58,14 +58,10 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) return; } - // Backup some DX9 state (not all!) - // FIXME: Backup/restore everything else - D3DRENDERSTATETYPE last_render_state_to_backup[] = { D3DRS_CULLMODE, D3DRS_LIGHTING, D3DRS_ZENABLE, D3DRS_ALPHABLENDENABLE, D3DRS_ALPHATESTENABLE, D3DRS_BLENDOP, D3DRS_SRCBLEND, D3DRS_DESTBLEND, D3DRS_SCISSORTESTENABLE }; - DWORD last_render_state_values[ARRAYSIZE(last_render_state_to_backup)] = { 0 }; - IDirect3DPixelShader9* last_ps; g_pd3dDevice->GetPixelShader( &last_ps ); - IDirect3DVertexShader9* last_vs; g_pd3dDevice->GetVertexShader( &last_vs ); - for (int n = 0; n < ARRAYSIZE(last_render_state_to_backup); n++) - g_pd3dDevice->GetRenderState(last_render_state_to_backup[n], &last_render_state_values[n]); + // Backup the DX9 state + IDirect3DStateBlock9* d3d9_state_block = NULL; + if ( g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0 ) + return; // Copy and convert all vertices into a single contiguous buffer CUSTOMVERTEX* vtx_dst; @@ -161,11 +157,9 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore some modified DX9 state (not all!) - g_pd3dDevice->SetPixelShader( last_ps ); - g_pd3dDevice->SetVertexShader( last_vs ); - for (int n = 0; n < ARRAYSIZE(last_render_state_to_backup); n++) - g_pd3dDevice->SetRenderState(last_render_state_to_backup[n], last_render_state_values[n]); + // Restore the DX9 state + d3d9_state_block->Apply(); + d3d9_state_block->Release(); } IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) From 1349d0aacf7b4d150def92ff18a2156dd8ec93cb Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 10:54:52 +0200 Subject: [PATCH 070/105] Examples: DirectX9: Removing spaces (#663) --- examples/directx9_example/imgui_impl_dx9.cpp | 52 ++++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index ba67d026c..bb309a867 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -60,7 +60,7 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) // Backup the DX9 state IDirect3DStateBlock9* d3d9_state_block = NULL; - if ( g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0 ) + if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) return; // Copy and convert all vertices into a single contiguous buffer @@ -90,30 +90,30 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) } g_pVB->Unlock(); g_pIB->Unlock(); - g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); - g_pd3dDevice->SetIndices( g_pIB ); - g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); + g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX)); + g_pd3dDevice->SetIndices(g_pIB); + g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing - g_pd3dDevice->SetPixelShader( NULL ); - g_pd3dDevice->SetVertexShader( NULL ); - g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); - g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false ); - g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false ); - g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true ); - g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false ); - g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); - g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); - g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); - g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, true ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); - g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); - g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + g_pd3dDevice->SetPixelShader(NULL); + g_pd3dDevice->SetVertexShader(NULL); + g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false); + g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); + g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); + g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // Setup orthographic projection matrix // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() @@ -148,9 +148,9 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) else { const RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->TextureId ); - g_pd3dDevice->SetScissorRect( &r ); - g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.size(), idx_offset, pcmd->ElemCount/3 ); + g_pd3dDevice->SetTexture(0, (LPDIRECT3DTEXTURE9)pcmd->TextureId); + g_pd3dDevice->SetScissorRect(&r); + g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.size(), idx_offset, pcmd->ElemCount/3); } idx_offset += pcmd->ElemCount; } From fa5ae60bceb40c107582f92153675000354febb4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 12:05:26 +0200 Subject: [PATCH 071/105] Demo: added decorated label to some vertical sliders. --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fa4f026d8..6c311c90b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -704,7 +704,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (i > 0) ImGui::SameLine(); ImGui::PushID(i); ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); - ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f"); + ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); ImGui::PopStyleVar(); ImGui::PopID(); } From 7a28f5bb818bf033315df96a190f4119ff123c19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 19:22:51 +0200 Subject: [PATCH 072/105] ImGuiListClipper new version, detect height automatically, fix compatibility with SetScrollPosHere (#662) --- imgui.cpp | 155 ++++++++++++++++++++++++++++++++++++------------- imgui.h | 44 +++++++------- imgui_demo.cpp | 31 ++++++---- 3 files changed, 156 insertions(+), 74 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5680cc046..6db38d719 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1607,6 +1607,88 @@ float ImGuiSimpleColumns::CalcExtraSpace(float avail_w) return ImMax(0.0f, avail_w - Width); } +//----------------------------------------------------------------------------- +// ImGuiListClipper +//----------------------------------------------------------------------------- + +static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) +{ + // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. + // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. + ImGui::SetCursorPosY(pos_y); + ImGuiWindow* window = ImGui::GetCurrentWindow(); + window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; + window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); +} + +// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 +// Use case B: Begin() called from constructor with items_height>0 +// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. +void ImGuiListClipper::Begin(int count, float items_height) +{ + StartPosY = ImGui::GetCursorPosY(); + ItemsHeight = items_height; + ItemsCount = count; + StepNo = 0; + DisplayEnd = DisplayStart = -1; + if (ItemsHeight > 0.0f) + { + ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display + if (DisplayStart > 0) + SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor + StepNo = 2; + } +} + +void ImGuiListClipper::End() +{ + if (ItemsCount < 0) + return; + float cur_y = ImGui::GetCursorPosY(); (void)cur_y; + float expected_display_end_y = StartPosY + DisplayEnd * ItemsHeight; + IM_ASSERT(fabsf(cur_y - expected_display_end_y) < 1.0f); // if this triggers, it probably means your items have varying height (in which case you can't use this helper) or the explicit height you have passed was incorrect. + if (ItemsCount < INT_MAX) + SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor + ItemsCount = -1; + StepNo = 3; +} + +bool ImGuiListClipper::Step() +{ + if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems) + { + ItemsCount = -1; + return false; + } + if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height. + { + DisplayStart = 0; + DisplayEnd = 1; + StartPosY = ImGui::GetCursorPosY(); + StepNo = 1; + return true; + } + if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. + { + if (ItemsCount == 1) { ItemsCount = -1; return false; } + float items_height = ImGui::GetCursorPosY() - StartPosY; + IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically + ImGui::SetCursorPosY(StartPosY); // Rewind cursor so we can Begin() again, this time with a known height. + Begin(ItemsCount, items_height); + StepNo = 3; + return true; + } + if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3. + { + IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0); + StepNo = 3; + return true; + } + if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. + End(); + return false; +} + //----------------------------------------------------------------------------- // ImGuiWindow //----------------------------------------------------------------------------- @@ -2878,18 +2960,8 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex } // Helper to calculate coarse clipping of large list of evenly sized items. -// NB: Prefer using the ImGuiListClipper higher-level helper if you can! +// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. // NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX -// If you are displaying thousands of items and you have a random access to the list, you can perform clipping yourself to save on CPU. -// { -// float item_height = ImGui::GetTextLineHeightWithSpacing(); -// int display_start, display_end; -// ImGui::CalcListClipping(count, item_height, &display_start, &display_end); // calculate how many to clip/display -// ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (display_start) * item_height); // advance cursor -// for (int i = display_start; i < display_end; i++) // display only visible items -// // TODO: display visible item -// ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (count - display_end) * item_height); // advance cursor -// } void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) { ImGuiContext& g = *GImGui; @@ -2901,6 +2973,11 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items *out_items_display_end = items_count; return; } + if (window->SkipItems) + { + *out_items_display_start = *out_items_display_end = 0; + return; + } const ImVec2 pos = window->DC.CursorPos; int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); @@ -8492,22 +8569,22 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. bool value_changed = false; ImGuiListClipper clipper(items_count, ImGui::GetTextLineHeightWithSpacing()); - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - { - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; - - ImGui::PushID(i); - if (ImGui::Selectable(item_text, item_selected)) + while (clipper.Step()) + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - *current_item = i; - value_changed = true; + const bool item_selected = (i == *current_item); + const char* item_text; + if (!items_getter(data, i, &item_text)) + item_text = "*Unknown item*"; + + ImGui::PushID(i); + if (ImGui::Selectable(item_text, item_selected)) + { + *current_item = i; + value_changed = true; + } + ImGui::PopID(); } - ImGui::PopID(); - } - clipper.End(); ImGui::ListBoxFooter(); return value_changed; } @@ -9520,22 +9597,22 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (!pcmd_node_open) continue; - ImGuiListClipper clipper(pcmd->ElemCount/3, ImGui::GetTextLineHeight()*3 + ImGui::GetStyle().ItemSpacing.y); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. - for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) - { - char buf[300], *buf_p = buf; - ImVec2 triangles_pos[3]; - for (int n = 0; n < 3; n++, vtx_i++) + ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + while (clipper.Step()) + for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) { - ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; - triangles_pos[n] = v.pos; - buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + char buf[300], *buf_p = buf; + ImVec2 triangles_pos[3]; + for (int n = 0; n < 3; n++, vtx_i++) + { + ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; + triangles_pos[n] = v.pos; + buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + } + ImGui::Selectable(buf, false); + if (ImGui::IsItemHovered()) + overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle } - ImGui::Selectable(buf, false); - if (ImGui::IsItemHovered()) - overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle - } - clipper.End(); ImGui::TreePop(); } overlay_draw_list->PopClipRect(); diff --git a/imgui.h b/imgui.h index c201b077e..c6618c589 100644 --- a/imgui.h +++ b/imgui.h @@ -1049,36 +1049,32 @@ struct ImColor }; // Helper: Manually clip large list of items. -// If you are displaying thousands of even spaced items and you have a random access to the list, you can perform clipping yourself to save on CPU. +// If you are displaying thousands of evenly spaced items and you have a random access to the list, you can perform clipping yourself to save on CPU. +// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. // Usage: -// ImGuiListClipper clipper(count, ImGui::GetTextLineHeightWithSpacing()); -// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) // display only visible items -// ImGui::Text("line number %d", i); -// clipper.End(); -// NB: 'count' is only used to clamp the result, if you don't know your count you can use INT_MAX +// ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced. +// while (clipper.Step()) +// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) +// ImGui::Text("line number %d", i); +// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height. +// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. +// - Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3. +// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. struct ImGuiListClipper { + float StartPosY; float ItemsHeight; - int ItemsCount, DisplayStart, DisplayEnd; + int ItemsCount, StepNo, DisplayStart, DisplayEnd; - ImGuiListClipper() { ItemsHeight = 0.0f; ItemsCount = DisplayStart = DisplayEnd = -1; } - ImGuiListClipper(int count, float height) { ItemsCount = -1; Begin(count, height); } - ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // user forgot to call End() + // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). + // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing(). + // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step(). + ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). + ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false. - void Begin(int count, float height) // items_height: generally pass GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing() - { - IM_ASSERT(ItemsCount == -1); - ItemsCount = count; - ItemsHeight = height; - ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + DisplayStart * ItemsHeight); // advance cursor - } - void End() - { - IM_ASSERT(ItemsCount >= 0); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (ItemsCount - DisplayEnd) * ItemsHeight); // advance cursor - ItemsCount = -1; - } + IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. + IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. + IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. }; //----------------------------------------------------------------------------- diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6c311c90b..9ff0cb169 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2014,24 +2014,33 @@ struct ExampleAppConsole ImGui::PopStyleVar(); ImGui::Separator(); - // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end()); - // NB- if you have thousands of entries this approach may be too inefficient. You can seek and display only the lines that are visible - CalcListClipping() is a helper to compute this information. - // If your items are of variable size you may want to implement code similar to what CalcListClipping() does. Or split your data into fixed height items to allow random-seeking into your list. ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); if (ImGui::BeginPopupContextWindow()) { if (ImGui::Selectable("Clear")) ClearLog(); ImGui::EndPopup(); } + + // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end()); + // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items. + // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements. + // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with: + // ImGuiListClipper clipper(Items.Size); + // while (clipper.Step()) + // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list. + // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter, + // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code! + // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing for (int i = 0; i < Items.Size; i++) { const char* item = Items[i]; if (!filter.PassFilter(item)) continue; - ImVec4 col = ImColor(255,255,255); // A better implementation may store a type per-item. For the sample let's just parse the text. - if (strstr(item, "[error]")) col = ImColor(255,100,100); - else if (strncmp(item, "# ", 2) == 0) col = ImColor(255,200,150); + ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text. + if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f); + else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f); ImGui::PushStyleColor(ImGuiCol_Text, col); ImGui::TextUnformatted(item); ImGui::PopStyleColor(); @@ -2441,10 +2450,10 @@ static void ShowExampleAppLongText(bool* p_open) { // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); - ImGuiListClipper clipper(lines, ImGui::GetTextLineHeightWithSpacing()); // Here we changed spacing is zero anyway so we could use GetTextLineHeight(), but _WithSpacing() is typically more correct - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog\n", i); - clipper.End(); + ImGuiListClipper clipper(lines); + while (clipper.Step()) + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); ImGui::PopStyleVar(); break; } @@ -2452,7 +2461,7 @@ static void ShowExampleAppLongText(bool* p_open) // Multiple calls to Text(), not clipped (slow) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); for (int i = 0; i < lines; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog\n", i); + ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); ImGui::PopStyleVar(); break; } From 28b09199de92c4e1b7e15c4797b2c4243909f4ea Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 19:25:42 +0200 Subject: [PATCH 073/105] ImGuiListClipper: removed assert (#662) --- imgui.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6db38d719..27c88caae 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1644,9 +1644,7 @@ void ImGuiListClipper::End() { if (ItemsCount < 0) return; - float cur_y = ImGui::GetCursorPosY(); (void)cur_y; - float expected_display_end_y = StartPosY + DisplayEnd * ItemsHeight; - IM_ASSERT(fabsf(cur_y - expected_display_end_y) < 1.0f); // if this triggers, it probably means your items have varying height (in which case you can't use this helper) or the explicit height you have passed was incorrect. + // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. if (ItemsCount < INT_MAX) SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor ItemsCount = -1; From f291f2c5dd65b5ae7e96c7dc34944fd55be82e0e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 19:44:03 +0200 Subject: [PATCH 074/105] InputText(): Fixed cursor rendering on first character when framepadding is 0.0 (following #601) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 27c88caae..02d8b7303 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8034,9 +8034,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Draw blinking cursor bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll; - ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x, cursor_screen_pos.y-1.5f); + ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f); if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) - draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.Max, GetColorU32(ImGuiCol_Text)); + draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) if (is_editable) From 787be01e61c407937ffc3482cbaa29dd6a21885e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 20:03:18 +0200 Subject: [PATCH 075/105] ImGuiListClipper comments (#660, #661, #662) --- imgui.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.h b/imgui.h index c6618c589..376217629 100644 --- a/imgui.h +++ b/imgui.h @@ -1049,16 +1049,17 @@ struct ImColor }; // Helper: Manually clip large list of items. -// If you are displaying thousands of evenly spaced items and you have a random access to the list, you can perform clipping yourself to save on CPU. -// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. +// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all. +// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. +// ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null. // Usage: // ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced. // while (clipper.Step()) // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) // ImGui::Text("line number %d", i); -// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height. +// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor). // - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. -// - Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3. +// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.) // - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. struct ImGuiListClipper { From 47d10944a59284faf86146b3d1fb30ff91723e96 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 20:07:02 +0200 Subject: [PATCH 076/105] Build fix --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 02d8b7303..6ee82661a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1645,7 +1645,7 @@ void ImGuiListClipper::End() if (ItemsCount < 0) return; // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. - if (ItemsCount < INT_MAX) + if (ItemsCount < IM_INT_MAX) SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor ItemsCount = -1; StepNo = 3; From 69a29e4715d463e22a58bb0766275168efa1586a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 20:14:07 +0200 Subject: [PATCH 077/105] Added NewLine() (very shy reminder that #97 isn't done) --- imgui.cpp | 11 +++++++++++ imgui.h | 1 + imgui_demo.cpp | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6ee82661a..822edcb94 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9122,6 +9122,17 @@ void ImGui::SameLine(float pos_x, float spacing_w) window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; } +void ImGui::NewLine() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + if (window->DC.CurrentLineHeight > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. + ItemSize(ImVec2(0,0)); + else + ItemSize(ImVec2(0.0f, GImGui->FontSize)); +} + void ImGui::NextColumn() { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui.h b/imgui.h index 376217629..7697e120f 100644 --- a/imgui.h +++ b/imgui.h @@ -191,6 +191,7 @@ namespace ImGui // Cursor / Layout IMGUI_API void Separator(); // horizontal line IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally + IMGUI_API void NewLine(); // undo a SameLine() IMGUI_API void Spacing(); // add spacing IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size IMGUI_API void Indent(); // move content position toward the right by style.IndentSpacing pixels diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9ff0cb169..c5f90a28f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -384,14 +384,14 @@ void ImGui::ShowTestWindow(bool* p_open) static int pressed_count = 0; for (int i = 0; i < 8; i++) { - if (i > 0) - ImGui::SameLine(); ImGui::PushID(i); int frame_padding = -1 + i; // -1 = uses default padding if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding, ImColor(0,0,0,255))) pressed_count += 1; ImGui::PopID(); + ImGui::SameLine(); } + ImGui::NewLine(); ImGui::Text("Pressed %d times.", pressed_count); ImGui::TreePop(); } From 0e51f91c5e46e8935cf653507b7a2406c8b1524a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 May 2016 20:27:52 +0200 Subject: [PATCH 078/105] Including limits.h again to get INT_MAX, assuming previous report of missing limits.h was erroneous (#1, yes, issue ONE!) --- imgui.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 822edcb94..d920b6e57 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -611,6 +611,7 @@ #include // sqrtf, fabsf, fmodf, powf, cosf, sinf, floorf, ceilf #include // NULL, malloc, free, qsort, atoi #include // vsnprintf, sscanf, printf +#include // INT_MIN, INT_MAX #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t #else @@ -863,9 +864,6 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) #define IM_F32_TO_INT8(_VAL) ((int)((_VAL) * 255.0f + 0.5f)) -#define IM_INT_MIN (-2147483647-1) -#define IM_INT_MAX (2147483647) - // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. #ifdef _WIN32 #define IM_NEWLINE "\r\n" @@ -1645,7 +1643,7 @@ void ImGuiListClipper::End() if (ItemsCount < 0) return; // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. - if (ItemsCount < IM_INT_MAX) + if (ItemsCount < INT_MAX) SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor ItemsCount = -1; StepNo = 3; @@ -1735,8 +1733,8 @@ ImGuiWindow::ImGuiWindow(const char* name) ParentWindow = NULL; FocusIdxAllCounter = FocusIdxTabCounter = -1; - FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = IM_INT_MAX; - FocusIdxAllRequestNext = FocusIdxTabRequestNext = IM_INT_MAX; + FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; + FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX; } ImGuiWindow::~ImGuiWindow() @@ -1900,7 +1898,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_ // Process keyboard input at this point: TAB, Shift-TAB switch focus // We can always TAB out of a widget that doesn't allow tabbing in. - if (tab_stop && window->FocusIdxAllRequestNext == IM_INT_MAX && window->FocusIdxTabRequestNext == IM_INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab)) + if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab)) { // Modulo on index will be applied at the end of frame once we've got the total counter of items. window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); @@ -4050,10 +4048,10 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); // Prepare for focus requests - window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == IM_INT_MAX || window->FocusIdxAllCounter == -1) ? IM_INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1); - window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == IM_INT_MAX || window->FocusIdxTabCounter == -1) ? IM_INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1); + window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1); + window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1); window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1; - window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = IM_INT_MAX; + window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX; // Apply scrolling if (window->ScrollTarget.x < FLT_MAX) @@ -5147,7 +5145,7 @@ void ImGui::SetKeyboardFocusHere(int offset) { ImGuiWindow* window = GetCurrentWindow(); window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset; - window->FocusIdxTabRequestNext = IM_INT_MAX; + window->FocusIdxTabRequestNext = INT_MAX; } void ImGui::SetStateStorage(ImGuiStorage* tree) @@ -6936,10 +6934,10 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_ ImGui::BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = ImGui::DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? IM_INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); + bool value_changed = ImGui::DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); ImGui::PopItemWidth(); ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= ImGui::DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? IM_INT_MAX : v_max, display_format_max ? display_format_max : display_format); + value_changed |= ImGui::DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); ImGui::PopItemWidth(); ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); From 1dfafeb602fd3afbba5d73a997ab6d89d38d9038 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 May 2016 09:36:27 +0200 Subject: [PATCH 079/105] CheckStacksSize() added literal strings in IM_ASSERT calls to reach end-user on common failure --- imgui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d920b6e57..44f9927a8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3617,12 +3617,12 @@ static void CheckStacksSize(ImGuiWindow* window, bool write) // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) ImGuiContext& g = *GImGui; int* p_backup = &window->DC.StackSizesBackup[0]; - { int current = window->IDStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopID() - { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot EndGroup() - { int current = g.CurrentPopupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot EndPopup()/EndMenu() - { int current = g.ColorModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopStyleColor() - { int current = g.StyleModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopStyleVar() - { int current = g.FontStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current); p_backup++; } // User forgot PopFont() + { int current = window->IDStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushID/PopID Mismatch!"); p_backup++; } // User forgot PopID() + { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // User forgot EndGroup() + { int current = g.CurrentPopupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++; }// User forgot EndPopup()/EndMenu() + { int current = g.ColorModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // User forgot PopStyleColor() + { int current = g.StyleModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // User forgot PopStyleVar() + { int current = g.FontStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushFont/PopFont Mismatch!"); p_backup++; } // User forgot PopFont() IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); } From b4302187dd0e93e905d4319297e7b35868839590 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 May 2016 19:47:13 +0200 Subject: [PATCH 080/105] ImFontAtlas: Tweak to allow MergeMode to apply on a font that isn't the previous one, by setting the DstFont field. --- imgui_draw.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 57b13bf82..9f3c265b0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1141,7 +1141,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); - new_font_cfg.DstFont = Fonts.back(); + if (!new_font_cfg.DstFont) + new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) { new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize); @@ -1151,7 +1152,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) // Invalidate texture ClearTexData(); - return Fonts.back(); + return new_font_cfg.DstFont; } // Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder) From 47911d92b2ccb496bb8de3ddca831e34b141abca Mon Sep 17 00:00:00 2001 From: Jeongseok Lee Date: Fri, 20 May 2016 07:04:54 -0400 Subject: [PATCH 081/105] Fix minor typo in examples/README.txt --- examples/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/README.txt b/examples/README.txt index df6fe879c..df2e86dab 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -71,7 +71,7 @@ apple_example/ sdl_opengl_example/ SDL2 + OpenGL example. -sdl_opengl_example/ +sdl_opengl3_example/ SDL2 + OpenGL3 example. allegro5_example/ From 81bf5aeb09cd5cb45fc43711a7f33ef518b5cf21 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 20:07:51 +0200 Subject: [PATCH 082/105] Minor bits --- imgui.cpp | 8 ++++---- imgui.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 44f9927a8..2dfa23178 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3796,7 +3796,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bool window_pos_set_by_api = false, window_size_set_by_api = false; 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. + const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that. if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) @@ -3857,12 +3857,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->Active = true; window->IndexWithinParent = 0; window->BeginCount = 0; - window->DrawList->Clear(); window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); window->LastFrameActive = current_frame; window->IDStack.resize(1); - // Setup texture, outer clipping rectangle + // Clear draw list, setup texture, outer clipping rectangle + window->DrawList->Clear(); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); ImRect fullscreen_rect(GetVisibleRect()); if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup))) @@ -4438,7 +4438,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) // Steal focus on active widgets if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it.. if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window) - ImGui::SetActiveID(0); + SetActiveID(0); // Bring to front if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window) diff --git a/imgui.h b/imgui.h index 7697e120f..71782c7b3 100644 --- a/imgui.h +++ b/imgui.h @@ -250,7 +250,7 @@ namespace ImGui IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); IMGUI_API void BulletTextV(const char* fmt, va_list args); IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); - IMGUI_API bool SmallButton(const char* label); + IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding From 102d03a7eb09e6eb8f4bfdc3df41edae03b74d04 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 20:50:15 +0200 Subject: [PATCH 083/105] Resizing window doesn't rely on MouseDelta anymore, but rather recompute expected size based absolute mouse coords. (#668) Storing ActiveIdClickOffset to generalize pattern already used by columns. --- imgui.cpp | 10 ++++++---- imgui_demo.cpp | 4 +--- imgui_internal.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2dfa23178..58e41fac0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3993,7 +3993,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) { window->Pos = window->PosFloat = parent_window->DC.CursorPos; - window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user. + window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin(). } bool window_pos_center = false; @@ -4108,7 +4108,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } else if (held) { - window->SizeFull = ImMax(window->SizeFull + g.IO.MouseDelta, style.WindowMinSize); + // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position + window->SizeFull = ImMax((g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos, style.WindowMinSize); if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkSettingsDirty(); } @@ -5423,6 +5424,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { SetActiveID(id, window); // Hold on ID FocusWindow(window); + g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { @@ -9188,7 +9190,7 @@ static float GetDraggedColumnOffset(int column_index) IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. IM_ASSERT(g.ActiveId == window->DC.ColumnsSetID + ImGuiID(column_index)); - float x = g.IO.MousePos.x + g.ActiveClickDeltaToCenter.x - window->Pos.x; + float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(column_index+1)-g.Style.ColumnsMinSpacing); return (float)(int)x; @@ -9293,7 +9295,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) if (held) { if (g.ActiveIdIsJustActivated) - g.ActiveClickDeltaToCenter.x = x - g.IO.MousePos.x; + g.ActiveIdClickOffset.x -= 4; // Store from center of column line x = GetDraggedColumnOffset(i); SetColumnOffset(i, x); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c5f90a28f..c77adc9b0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1807,10 +1807,8 @@ static void ShowExampleAppFixedOverlay(bool* p_open) ImGui::End(); } -static void ShowExampleAppManipulatingWindowTitle(bool* p_open) +static void ShowExampleAppManipulatingWindowTitle(bool*) { - (void)p_open; - // By default, Windows are uniquely identified by their title. // You can use the "##" and "###" markers to manipulate the display/ID. Read FAQ at the top of this file! diff --git a/imgui_internal.h b/imgui_internal.h index 6c90e53a6..b4db72288 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -373,6 +373,7 @@ struct ImGuiContext bool ActiveIdIsAlive; bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Set only by active widget + ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId @@ -410,7 +411,6 @@ struct ImGuiContext ImFont InputTextPasswordFont; ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode - ImVec2 ActiveClickDeltaToCenter; float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings ImVec2 DragLastMouseDelta; float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio @@ -458,6 +458,7 @@ struct ImGuiContext ActiveIdIsAlive = false; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; + ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; MovedWindow = NULL; MovedWindowMoveId = 0; @@ -475,7 +476,6 @@ struct ImGuiContext SetNextTreeNodeOpenCond = 0; ScalarAsInputTextId = 0; - ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f); DragCurrentValue = 0.0f; DragLastMouseDelta = ImVec2(0.0f, 0.0f); DragSpeedDefaultRatio = 0.01f; From 713730af0c79d11ff2d431dcb66dc54ff10a4ad0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 20:55:28 +0200 Subject: [PATCH 084/105] Minor sizing refactor, should be no-op. Making it a commit for further bisection since sizing code is super brittle. (#668) --- imgui.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 58e41fac0..8ac239772 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3953,7 +3953,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; if (window->AutoFitFramesY > 0) window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - window->Size = window->TitleBarRect().GetSize(); } else { @@ -3971,17 +3970,13 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkSettingsDirty(); } - window->Size = window->SizeFull; } - // Minimum window size + // Apply window size constraints and final size if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) - { window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize); - if (!window->Collapsed) - window->Size = window->SizeFull; - } - + window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; + // POSITION // Position child window From 753bf5cefef87f7e1c5240a8b86004b3f431eff9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 22:35:05 +0200 Subject: [PATCH 085/105] Comments --- imgui.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/imgui.h b/imgui.h index 71782c7b3..3b624d08d 100644 --- a/imgui.h +++ b/imgui.h @@ -1030,6 +1030,7 @@ struct ImGuiTextEditCallbackData }; // ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) +// Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API. // Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. // None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. struct ImColor @@ -1092,12 +1093,8 @@ struct ImGuiListClipper // Draw callbacks for advanced uses. // NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that) -// Draw callback may be useful for example, if you want to render a complex 3D scene inside a UI element, change your GPU render state, etc. -// The expected behavior from your rendering loop is: -// if (cmd.UserCallback != NULL) -// cmd.UserCallback(parent_list, cmd); -// else -// RenderTriangles() +// Draw callback may be useful for example, A) Change your GPU render state, B) render a complex 3D scene inside a UI element (without an intermediate texture/render target), etc. +// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()' typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); // Typically, 1 command = 1 gpu draw call (unless command is a callback) @@ -1112,7 +1109,7 @@ struct ImDrawCmd ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } }; -// Vertex index (override with, e.g. '#define ImDrawIdx unsigned int' in ImConfig) +// Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h) #ifndef ImDrawIdx typedef unsigned short ImDrawIdx; #endif From b7ebeb1610d27868b78206bf28cf5b5f7ee68013 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 22:53:08 +0200 Subject: [PATCH 086/105] Added SetNextWindowSizeConstraint() + demo code (#668) --- imgui.cpp | 48 +++++++++++++++++++++++++++++++++++++++++------- imgui.h | 15 ++++++++++++++- imgui_demo.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ imgui_internal.h | 6 ++++++ 4 files changed, 103 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8ac239772..6f79ef82f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -457,7 +457,6 @@ The list below consist mostly of notes of things to do before they are requested/discussed by users (at that point it usually happens on the github) - doc: add a proper documentation+regression testing system (#435) - - window: maximum window size settings (per-axis). for large popups in particular user may not want the popup to fill all space. - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass. - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify. @@ -3416,7 +3415,7 @@ static inline void ClearSetNextWindowData() { ImGuiContext& g = *GImGui; g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0; - g.SetNextWindowFocus = false; + g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false; } static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) @@ -3731,6 +3730,31 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl return window; } +static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size) +{ + ImGuiContext& g = *GImGui; + if (g.SetNextWindowSizeConstraint) + { + // Using -1,-1 on either X/Y axis to preserve the current size. + ImRect cr = g.SetNextWindowSizeConstraintRect; + new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; + new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; + if (g.SetNextWindowSizeConstraintCallback) + { + ImGuiSizeConstraintCallbackData data; + data.UserData = g.SetNextWindowSizeConstraintCallbackUserData; + data.Pos = window->Pos; + data.CurrentSize = window->SizeFull; + data.DesiredSize = new_size; + g.SetNextWindowSizeConstraintCallback(&data); + new_size = data.DesiredSize; + } + } + if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) + new_size = ImMax(new_size, g.Style.WindowMinSize); + window->SizeFull = new_size; +} + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -3972,9 +3996,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } } - // Apply window size constraints and final size - if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) - window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize); + // Apply minimum/maximum window size constraints and final size + ApplySizeFullWithConstraint(window, window->SizeFull); window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; // POSITION @@ -4096,7 +4119,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) { // Manual auto-fit when double-clicking - window->SizeFull = size_auto_fit; + ApplySizeFullWithConstraint(window, size_auto_fit); if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkSettingsDirty(); SetActiveID(0); @@ -4104,7 +4127,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us else if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - window->SizeFull = ImMax((g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos, style.WindowMinSize); + ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkSettingsDirty(); } @@ -4177,6 +4200,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Setup drawing context window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; + window->DC.GroupOffsetX = 0.0f; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y); window->DC.CursorPos = window->DC.CursorStartPos; @@ -4268,6 +4292,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (first_begin_of_the_frame) window->Accessed = false; window->BeginCount++; + g.SetNextWindowSizeConstraint = false; // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar). @@ -4906,6 +4931,15 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond) g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always; } +void ImGui::SetNextWindowSizeConstraint(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) +{ + ImGuiContext& g = *GImGui; + g.SetNextWindowSizeConstraint = true; + g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max); + g.SetNextWindowSizeConstraintCallback = custom_callback; + g.SetNextWindowSizeConstraintCallbackUserData = custom_callback_user_data; +} + void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 3b624d08d..9c2cc2886 100644 --- a/imgui.h +++ b/imgui.h @@ -52,7 +52,8 @@ struct ImGuiStorage; // Simple custom key value storage struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" struct ImGuiTextBuffer; // Text buffer for logging/accumulating text -struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom callbacks (advanced) +struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use) +struct ImGuiSizeConstraintCallbackData;// Structure used to constraint window size in custom ways when using custom ImGuiSizeConstraintCallback (rare/advanced use) struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiContext; // ImGui context (opaque) @@ -73,6 +74,7 @@ typedef int ImGuiInputTextFlags; // flags for InputText*() // e typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); +typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); // Others helpers at bottom of the file: // class ImVector<> // Lightweight std::vector like class. @@ -138,6 +140,7 @@ namespace ImGui IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() IMGUI_API void SetNextWindowPosCenter(ImGuiSetCond cond = 0); // set next window position to be centered on screen. call before Begin() IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() + IMGUI_API void SetNextWindowSizeConstraint(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowContentWidth(float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() @@ -1029,6 +1032,16 @@ struct ImGuiTextEditCallbackData bool HasSelection() const { return SelectionStart != SelectionEnd; } }; +// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraint(). Callback is called during the next Begin(). +// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraint() parameters are enough. +struct ImGuiSizeConstraintCallbackData +{ + void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraint() + ImVec2 Pos; // Read-only. Window position, for reference. + ImVec2 CurrentSize; // Read-only. Current window size. + ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. +}; + // ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) // Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API. // Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c77adc9b0..242ea7072 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -46,6 +46,7 @@ #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) +#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) //----------------------------------------------------------------------------- // DEMO CODE @@ -59,6 +60,7 @@ static void ShowExampleAppLayout(bool* p_open); static void ShowExampleAppPropertyEditor(bool* p_open); static void ShowExampleAppLongText(bool* p_open); static void ShowExampleAppAutoResize(bool* p_open); +static void ShowExampleAppConstrainedResize(bool* p_open); static void ShowExampleAppFixedOverlay(bool* p_open); static void ShowExampleAppManipulatingWindowTitle(bool* p_open); static void ShowExampleAppCustomRendering(bool* p_open); @@ -105,6 +107,7 @@ void ImGui::ShowTestWindow(bool* p_open) static bool show_app_property_editor = false; static bool show_app_long_text = false; static bool show_app_auto_resize = false; + static bool show_app_constrained_resize = false; static bool show_app_fixed_overlay = false; static bool show_app_manipulating_window_title = false; static bool show_app_custom_rendering = false; @@ -120,6 +123,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); + if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay); if (show_app_manipulating_window_title) ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title); if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); @@ -183,6 +187,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::MenuItem("Property editor", NULL, &show_app_property_editor); ImGui::MenuItem("Long text display", NULL, &show_app_long_text); ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize); + ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize); ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay); ImGui::MenuItem("Manipulating window title", NULL, &show_app_manipulating_window_title); ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); @@ -1793,6 +1798,43 @@ static void ShowExampleAppAutoResize(bool* p_open) ImGui::End(); } +static void ShowExampleAppConstrainedResize(bool* p_open) +{ + struct CustomConstraints // Helper functions to demonstrate programmatic constraints + { + static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } + static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } + }; + + static int type = 0; + if (type == 0) ImGui::SetNextWindowSizeConstraint(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only + if (type == 1) ImGui::SetNextWindowSizeConstraint(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only + if (type == 2) ImGui::SetNextWindowSizeConstraint(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 + if (type == 3) ImGui::SetNextWindowSizeConstraint(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 + if (type == 4) ImGui::SetNextWindowSizeConstraint(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square + if (type == 5) ImGui::SetNextWindowSizeConstraint(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step + + if (ImGui::Begin("Example: Constrained Resize", p_open)) + { + const char* desc[] = + { + "Resize vertical only", + "Resize horizontal only", + "Width > 100, Height > 100", + "Width 300-400", + "Custom: Always Square", + "Custom: Fixed Steps (100)", + }; + ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); + if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200,200)); ImGui::SameLine(); + if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500,500)); ImGui::SameLine(); + if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800,200)); + for (int i = 0; i < 10; i++) + ImGui::Text("Hello, sailor! Making this line long enough for the example."); + } + ImGui::End(); +} + static void ShowExampleAppFixedOverlay(bool* p_open) { ImGui::SetNextWindowPos(ImVec2(10,10)); diff --git a/imgui_internal.h b/imgui_internal.h index b4db72288..c787dbd11 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -394,6 +394,10 @@ struct ImGuiContext ImGuiSetCond SetNextWindowSizeCond; ImGuiSetCond SetNextWindowContentSizeCond; ImGuiSetCond SetNextWindowCollapsedCond; + ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true + ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback; + void* SetNextWindowSizeConstraintCallbackUserData; + bool SetNextWindowSizeConstraint; bool SetNextWindowFocus; bool SetNextTreeNodeOpenVal; ImGuiSetCond SetNextTreeNodeOpenCond; @@ -472,6 +476,8 @@ struct ImGuiContext SetNextWindowContentSizeCond = 0; SetNextWindowCollapsedCond = 0; SetNextWindowFocus = false; + SetNextWindowSizeConstraintCallback = NULL; + SetNextWindowSizeConstraintCallbackUserData = NULL; SetNextTreeNodeOpenVal = false; SetNextTreeNodeOpenCond = 0; From 3a776d93f2beb6d36b00d555e0b249228ad0d54e Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 23:03:21 +0200 Subject: [PATCH 087/105] Fixed compile issue (bloody git stashes) (#668) --- imgui.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 6f79ef82f..ae1e3445d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4200,7 +4200,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Setup drawing context window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; - window->DC.GroupOffsetX = 0.0f; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y); window->DC.CursorPos = window->DC.CursorStartPos; From e3d8055d90bad09f473d32768aa0419200624816 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 21 May 2016 23:13:11 +0200 Subject: [PATCH 088/105] Speculative 64-bit warning fix (#668) --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 242ea7072..d71343b30 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1803,7 +1803,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open) struct CustomConstraints // Helper functions to demonstrate programmatic constraints { static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } - static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } + static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } }; static int type = 0; From 65b1ae6ecc2d764c0ede14a0e0c987ec633068e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 22 May 2016 10:20:58 +0200 Subject: [PATCH 089/105] Comments (#335) --- imgui.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ae1e3445d..45188fc3a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -153,9 +153,10 @@ 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2016/05/12 (1.49) - title bar (using TitleBg/TitleBgActive colors) isn't rendered over a window background (WindowBg color) anymore. - If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. - This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given that color and the WindowBg color. + - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. + If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. + However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. + This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; @@ -578,7 +579,7 @@ - keyboard: full keyboard navigation and focus. (#323) - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - - input: rework IO system to be able to pass actual ordered/timestamped events. + - input: rework IO system to be able to pass actual ordered/timestamped events. (~#335, #71) - input: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style). - input: support track pad style scrolling & slider edit. - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) @@ -591,6 +592,7 @@ - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack. - examples: directx9: save/restore device state more thoroughly. - examples: window minimize, maximize (#583) + - optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335) - optimization: use another hash function than crc32, e.g. FNV1a - optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)? - optimization: turn some the various stack vectors into statically-sized arrays From 213025f3cde2a4afdb95eb016a5eb8faa2cd6cfd Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 11:14:02 +0200 Subject: [PATCH 090/105] BeginMenu: a menu that becomes disabled when open gets closed down, facilitate user's code (#126) --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 45188fc3a..072f2dcfd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8778,7 +8778,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR(); float extra = ImClamp(fabsf(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues - tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus + tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale? tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f); moving_within_opened_triangle = ImIsPointInTriangle(g.IO.MousePos, ta, tb, tc); //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? 0x80008000 : 0x80000080); window->DrawList->PopClipRect(); // Debug @@ -8795,7 +8795,8 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others want_open = true; - + if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' + want_close = true; if (want_close && IsPopupOpen(id)) ClosePopupToLevel(GImGui->CurrentPopupStack.Size); From 8f4b123e1bf08314d071444b1260148c75448397 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 14:02:14 +0200 Subject: [PATCH 091/105] SetNextWindowSizeConstraint -> SetNextWindowSizeConstraints (#668) --- imgui.cpp | 2 +- imgui.h | 8 ++++---- imgui_demo.cpp | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 072f2dcfd..d677f2a65 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4932,7 +4932,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond) g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always; } -void ImGui::SetNextWindowSizeConstraint(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) +void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; g.SetNextWindowSizeConstraint = true; diff --git a/imgui.h b/imgui.h index 9c2cc2886..bc5fd2b6d 100644 --- a/imgui.h +++ b/imgui.h @@ -140,7 +140,7 @@ namespace ImGui IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() IMGUI_API void SetNextWindowPosCenter(ImGuiSetCond cond = 0); // set next window position to be centered on screen. call before Begin() IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() - IMGUI_API void SetNextWindowSizeConstraint(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. + IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowContentWidth(float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() @@ -1032,11 +1032,11 @@ struct ImGuiTextEditCallbackData bool HasSelection() const { return SelectionStart != SelectionEnd; } }; -// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraint(). Callback is called during the next Begin(). -// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraint() parameters are enough. +// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). +// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. struct ImGuiSizeConstraintCallbackData { - void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraint() + void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() ImVec2 Pos; // Read-only. Window position, for reference. ImVec2 CurrentSize; // Read-only. Current window size. ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d71343b30..a38e836f7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1807,12 +1807,12 @@ static void ShowExampleAppConstrainedResize(bool* p_open) }; static int type = 0; - if (type == 0) ImGui::SetNextWindowSizeConstraint(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only - if (type == 1) ImGui::SetNextWindowSizeConstraint(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only - if (type == 2) ImGui::SetNextWindowSizeConstraint(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 - if (type == 3) ImGui::SetNextWindowSizeConstraint(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 - if (type == 4) ImGui::SetNextWindowSizeConstraint(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square - if (type == 5) ImGui::SetNextWindowSizeConstraint(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step + if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only + if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only + if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 + if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 + if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square + if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step if (ImGui::Begin("Example: Constrained Resize", p_open)) { From b5521a81d4c6a144a004f67320d9553099019340 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 14:18:46 +0200 Subject: [PATCH 092/105] Demo: fixed multi-selection tree nodes demo to not replace selection when clicking on single-item that's already part of selection (#581) --- imgui_demo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a38e836f7..6fb75a9cd 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -275,9 +275,9 @@ void ImGui::ShowTestWindow(bool* p_open) { // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. if (ImGui::GetIO().KeyCtrl) - selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else - selection_mask = (1 << node_clicked); // Click to single-select + selection_mask ^= (1 << node_clicked); // CTRL+click to toggle + else if (!(selection_mask & (1 << node_clicked))) // If there is already a selection don't replace we clicked node is part of it + selection_mask = (1 << node_clicked); // Click to single-select } ImGui::TreePop(); } From 2acb61e3a1c7e5585a2532ad03178eaf30de818f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 16:52:59 +0200 Subject: [PATCH 093/105] Comments --- imgui.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/imgui.h b/imgui.h index bc5fd2b6d..3a0426b88 100644 --- a/imgui.h +++ b/imgui.h @@ -195,10 +195,10 @@ namespace ImGui IMGUI_API void Separator(); // horizontal line IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally IMGUI_API void NewLine(); // undo a SameLine() - IMGUI_API void Spacing(); // add spacing + IMGUI_API void Spacing(); // add vertical spacing IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size - IMGUI_API void Indent(); // move content position toward the right by style.IndentSpacing pixels - IMGUI_API void Unindent(); // move content position back to the left (cancel Indent) + IMGUI_API void Indent(); // move content position toward the right by style.IndentSpacing + IMGUI_API void Unindent(); // move content position back to the left by style.IndentSpacing IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) IMGUI_API void EndGroup(); IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position @@ -208,7 +208,7 @@ namespace ImGui IMGUI_API void SetCursorPosX(float x); // " IMGUI_API void SetCursorPosY(float y); // " IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() @@ -216,7 +216,7 @@ namespace ImGui IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y // Columns - // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress. + // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1). IMGUI_API void NextColumn(); // next column IMGUI_API int GetColumnIndex(); // get current column index @@ -252,7 +252,7 @@ namespace ImGui IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance you by the same distance as an empty TreeNode() call. IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); IMGUI_API void BulletTextV(const char* fmt, va_list args); - IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); + IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); @@ -458,7 +458,7 @@ namespace ImGui // Obsolete (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - static inline bool CollapsingHeader(const char* label, const char* str_id, bool display_frame = true, bool default_open = false) { (void)str_id; (void)display_frame; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ + static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ static inline void OpenNextNode(bool open) { ImGui::SetNextTreeNodeOpen(open, 0); } // OBSOLETE 1.34+ @@ -659,6 +659,7 @@ enum ImGuiAlign_ }; // Enumeration for ColorEditMode() +// FIXME-OBSOLETE: Will be replaced by future color/picker api enum ImGuiColorEditMode_ { ImGuiColorEditMode_UserSelect = -2, From 806a1461989bdcc87162cb99a764845689b81911 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 17:12:13 +0200 Subject: [PATCH 094/105] TreeNodeEx(): ImGuiTreeNodeFlags_AlwaysOpen->ImGuiTreeNodeFlags_Leaf, + added ImGuiTreeNodeFlags_Bullet (#324, #581) --- imgui.cpp | 8 ++++---- imgui.h | 9 +++++---- imgui_demo.cpp | 39 ++++++++++++++++++++++++++------------- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d677f2a65..1ec4cd2da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5776,7 +5776,7 @@ void ImGui::LogButtons() bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { - if (flags & ImGuiTreeNodeFlags_AlwaysOpen) + if (flags & ImGuiTreeNodeFlags_Leaf) return true; // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) @@ -5871,7 +5871,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - if (pressed && !(flags & ImGuiTreeNodeFlags_AlwaysOpen)) + if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) { bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) @@ -5915,9 +5915,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) RenderFrame(bb.Min, bb.Max, col, false); - if (flags & ImGuiTreeNodeFlags_AlwaysOpen) + if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); - else + else if (!(flags & ImGuiTreeNodeFlags_Leaf)) RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f, false); if (g.LogEnabled) LogRenderedText(text_pos, ">"); diff --git a/imgui.h b/imgui.h index 3a0426b88..15af60fd6 100644 --- a/imgui.h +++ b/imgui.h @@ -541,10 +541,11 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. - ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). - //ImGuiTreeNodeFlags_UnindentArrow = 1 << 9, // FIXME: TODO: Unindent tree so that Label is aligned to current X position - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). + ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow + //ImGuiTreeNodeFlags_UnindentArrow = 1 << 10, // FIXME: TODO: Unindent tree so that Label is aligned to current X position + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Automatically scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6fb75a9cd..c78f6965d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -253,22 +253,34 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("With selectable nodes")) { - ShowHelpMarker("Click to select, CTRL+Click to toggle, click on arrows to open"); - static int selection_mask = 0x02; // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. - int node_clicked = -1; + ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); + ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. + static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. + int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. for (int i = 0; i < 6; i++) { + // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; - if (i >= 3) - node_flags |= ImGuiTreeNodeFlags_AlwaysOpen; - bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable %s %d", (i >= 3) ? "Leaf" : "Node", i); - if (ImGui::IsItemClicked()) - node_clicked = i; - if (node_open) + if (i < 3) { - ImGui::Text("Selectable Blah blah"); - ImGui::Text("Blah blah"); - ImGui::TreePop(); + // Node + bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; + if (node_open) + { + ImGui::Text("Blah blah\nBlah Blah"); + ImGui::TreePop(); + } + } + else + { + // Leaf: Here we use the ImGuiTreeNodeFlags_Leaf functionality + ImGuiTreeNodeFlags_NoTreePushOnOpen to avoid testing return value and doing a TreePop + // The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or a simple Text() element offset by GetTreeNodeToLabelSpacing() + node_flags |= ImGuiTreeNodeFlags_Leaf|ImGuiTreeNodeFlags_NoTreePushOnOpen; + ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; } } if (node_clicked != -1) @@ -276,9 +288,10 @@ void ImGui::ShowTestWindow(bool* p_open) // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. if (ImGui::GetIO().KeyCtrl) selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else if (!(selection_mask & (1 << node_clicked))) // If there is already a selection don't replace we clicked node is part of it + else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection selection_mask = (1 << node_clicked); // Click to single-select } + ImGui::PopStyleVar(); ImGui::TreePop(); } ImGui::TreePop(); From 793f5f8cdba94af35748f0b69a25716aae8346ec Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 17:54:40 +0200 Subject: [PATCH 095/105] Comments --- imgui.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui.h b/imgui.h index 15af60fd6..24da799f9 100644 --- a/imgui.h +++ b/imgui.h @@ -249,8 +249,8 @@ namespace ImGui IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, recommended for long chunks of text IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args); - IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance you by the same distance as an empty TreeNode() call. - IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); + IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses + IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for Bullet()+Text() IMGUI_API void BulletTextV(const char* fmt, va_list args); IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) @@ -267,7 +267,7 @@ namespace ImGui IMGUI_API bool ColorButton(const ImVec4& col, bool small_height = false, bool outline_border = true); IMGUI_API bool ColorEdit3(const char* label, float col[3]); // Hint: 'float col[3]' function argument is same as 'float* col'. You can pass address of first element out of a contiguous set, e.g. &myvector.x IMGUI_API bool ColorEdit4(const char* label, float col[4], bool show_alpha = true); // " - IMGUI_API void ColorEditMode(ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and should be obsoleted. + IMGUI_API void ColorEditMode(ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and will be obsoleted/replaced. IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); @@ -323,9 +323,9 @@ namespace ImGui IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); - IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layout purpose + IMGUI_API void TreePush(const char* str_id = NULL); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " - IMGUI_API void TreePop(); + IMGUI_API void TreePop(); // ~ Unindent()+PopId() IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. IMGUI_API float GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags = 0); // return horizontal distance between cursor and text label due to collapsing node. == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop(). @@ -530,7 +530,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; -// Flags for ImGui::TreeNode*(), ImGui::CollapsingHeader*() +// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() enum ImGuiTreeNodeFlags_ { ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected @@ -545,7 +545,7 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow //ImGuiTreeNodeFlags_UnindentArrow = 1 << 10, // FIXME: TODO: Unindent tree so that Label is aligned to current X position //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Automatically scroll on TreePop() if node got just open and contents is not visible + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; From a0a48f6e59772d709f1768a6aeb67023df234179 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 18:15:54 +0200 Subject: [PATCH 096/105] Added TreeAdvanceToLabelPos() (#581) --- imgui.cpp | 17 +++++++++-------- imgui.h | 3 ++- imgui_demo.cpp | 6 ++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1ec4cd2da..fec7c37b2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6043,19 +6043,20 @@ bool ImGui::TreeNode(const char* label) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - return TreeNodeBehavior(window->GetID(label), 0, label, NULL); } -float ImGui::GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags) +void ImGui::TreeAdvanceToLabelPos() { ImGuiContext& g = *GImGui; - float off_from_start; - if (flags & ImGuiTreeNodeFlags_Framed) - off_from_start = g.FontSize + (g.Style.FramePadding.x * 3.0f) - ((float)(int)(g.CurrentWindow->WindowPadding.x*0.5f) - 1); - else - off_from_start = g.FontSize + (g.Style.FramePadding.x * 2.0f); - return off_from_start; + g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing(); +} + +// Horizontal distance preceeding label when using TreeNode() or Bullet() +float ImGui::GetTreeNodeToLabelSpacing() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + (g.Style.FramePadding.x * 2.0f); } void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond) diff --git a/imgui.h b/imgui.h index 24da799f9..c455cb717 100644 --- a/imgui.h +++ b/imgui.h @@ -326,8 +326,9 @@ namespace ImGui IMGUI_API void TreePush(const char* str_id = NULL); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); // ~ Unindent()+PopId() + IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() + IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceeding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. - IMGUI_API float GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags = 0); // return horizontal distance between cursor and text label due to collapsing node. == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c78f6965d..3d92424d7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -275,10 +275,8 @@ void ImGui::ShowTestWindow(bool* p_open) } else { - // Leaf: Here we use the ImGuiTreeNodeFlags_Leaf functionality + ImGuiTreeNodeFlags_NoTreePushOnOpen to avoid testing return value and doing a TreePop - // The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or a simple Text() element offset by GetTreeNodeToLabelSpacing() - node_flags |= ImGuiTreeNodeFlags_Leaf|ImGuiTreeNodeFlags_NoTreePushOnOpen; - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); + // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). + ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Selectable Leaf %d", i); if (ImGui::IsItemClicked()) node_clicked = i; } From 61c294bb52c234c3b777762b70f56551198797e6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 18:40:00 +0200 Subject: [PATCH 097/105] Added optional Indent() Unindent() width (#324, #581) --- imgui.cpp | 14 +++++++------- imgui.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fec7c37b2..a31498fac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -546,12 +546,12 @@ - drag float: up/down axis - drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits) - tree node / optimization: avoid formatting when clipped. - - tree node: clarify spacing, perhaps provide API to query exact spacing. provide API to draw the primitive. same with Bullet(). - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling. - - tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings + - tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings? - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits? - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249) + - tree node: tweak color scheme to distinguish headers from selected tree node (#581) + - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - settings: write more decent code to allow saving/loading new fields - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file - style: add window shadows. @@ -9375,19 +9375,19 @@ void ImGui::Columns(int columns_count, const char* id, bool border) } } -void ImGui::Indent() +void ImGui::Indent(float indent_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.IndentX += g.Style.IndentSpacing; + window->DC.IndentX += (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; } -void ImGui::Unindent() +void ImGui::Unindent(float indent_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.IndentX -= g.Style.IndentSpacing; + window->DC.IndentX -= (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; } diff --git a/imgui.h b/imgui.h index c455cb717..251cef085 100644 --- a/imgui.h +++ b/imgui.h @@ -197,8 +197,8 @@ namespace ImGui IMGUI_API void NewLine(); // undo a SameLine() IMGUI_API void Spacing(); // add vertical spacing IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size - IMGUI_API void Indent(); // move content position toward the right by style.IndentSpacing - IMGUI_API void Unindent(); // move content position back to the left by style.IndentSpacing + IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if >0 + IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if >0 IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) IMGUI_API void EndGroup(); IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position From 1483a69c111552b0fbd653096105a616d9980bbb Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 19:30:01 +0200 Subject: [PATCH 098/105] Demo: Tree: showing how to align tree node label with current x position (#324, #581) --- imgui.cpp | 2 +- imgui.h | 5 ++--- imgui_demo.cpp | 14 +++++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a31498fac..703fb7cf8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5847,7 +5847,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; } - const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing + const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); diff --git a/imgui.h b/imgui.h index 251cef085..804934223 100644 --- a/imgui.h +++ b/imgui.h @@ -544,9 +544,8 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow - //ImGuiTreeNodeFlags_UnindentArrow = 1 << 10, // FIXME: TODO: Unindent tree so that Label is aligned to current X position - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3d92424d7..d98b7fff9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -251,16 +251,22 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("With selectable nodes")) + if (ImGui::TreeNode("Advanced, with Selectable nodes")) { ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); - ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. + static bool align_label_with_current_x_position = false; + ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position); + ImGui::Text("Hello!"); + if (align_label_with_current_x_position) + ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); + static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. + ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. for (int i = 0; i < 6; i++) { // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. - ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0); if (i < 3) { // Node @@ -290,6 +296,8 @@ void ImGui::ShowTestWindow(bool* p_open) selection_mask = (1 << node_clicked); // Click to single-select } ImGui::PopStyleVar(); + if (align_label_with_current_x_position) + ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); ImGui::TreePop(); } ImGui::TreePop(); From d5a12866fe6d9b0dbe6e7323b11af27b6a84e1f9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 14:00:35 +0200 Subject: [PATCH 099/105] Comments (#676, #655) --- imgui.cpp | 1 + imgui.h | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 703fb7cf8..7f89e9bde 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -162,6 +162,7 @@ float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); } + If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). diff --git a/imgui.h b/imgui.h index 804934223..c894860ec 100644 --- a/imgui.h +++ b/imgui.h @@ -145,10 +145,10 @@ namespace ImGui IMGUI_API void SetNextWindowContentWidth(float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() - IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set current window position - call within Begin()/End(). may incur tearing - IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set current window size. set to ImVec2(0,0) to force an auto-fit. may incur tearing - IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set current window collapsed state - IMGUI_API void SetWindowFocus(); // set current window to be focused / front-most + IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. + IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. + IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). + IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0); // set named window collapsed state From 45dacbf084e897c317d034275fbd070ed71c0709 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 17:50:23 +0200 Subject: [PATCH 100/105] Fixed GetWindowContentRegionMax() being off by ScrollSize amount when SizeExplicit is set + caching ContentsRegionRect. Relates to horizontal scrollbar, explicit contents size --- imgui.cpp | 19 +++++++++++-------- imgui_internal.h | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7f89e9bde..3c310dd64 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4201,6 +4201,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } } + // Update ContentsRegionMax. All the variable it depends on are set above in this function. + window->ContentsRegionRect.Min.x = -window->Scroll.x + window->WindowPadding.x; + window->ContentsRegionRect.Min.x = -window->Scroll.y + window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y; + window->ContentsRegionRect.Max.x = (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : window->Size.x - window->ScrollbarSizes.x) - window->Scroll.x - window->WindowPadding.x; + window->ContentsRegionRect.Max.y = (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : window->Size.y - window->ScrollbarSizes.y) - window->Scroll.y - window->WindowPadding.y; + // Setup drawing context window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; window->DC.ColumnsOffsetX = 0.0f; @@ -4970,12 +4976,10 @@ void ImGui::SetNextWindowFocus() } // In window space (not screen space!) -// FIXME-OPT: Could cache and maintain it (pretty much only change on columns change) ImVec2 ImGui::GetContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); - ImVec2 content_region_size = ImVec2(window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : window->Size.x - window->ScrollbarSizes.x, window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : window->Size.y - window->ScrollbarSizes.y); - ImVec2 mx = content_region_size - window->Scroll - window->WindowPadding; + ImVec2 mx = window->ContentsRegionRect.Max; if (window->DC.ColumnsCount != 1) mx.x = ImGui::GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; return mx; @@ -4996,20 +5000,19 @@ float ImGui::GetContentRegionAvailWidth() ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GetCurrentWindowRead(); - return ImVec2(-window->Scroll.x, -window->Scroll.y + window->TitleBarHeight() + window->MenuBarHeight()) + window->WindowPadding; + return window->ContentsRegionRect.Min; } ImVec2 ImGui::GetWindowContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); - ImVec2 content_region_size = ImVec2(window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : window->Size.x, window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : window->Size.y); - ImVec2 m = content_region_size - window->Scroll - window->WindowPadding - window->ScrollbarSizes; - return m; + return window->ContentsRegionRect.Max; } float ImGui::GetWindowContentRegionWidth() { - return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ContentsRegionRect.Max.x - window->ContentsRegionRect.Min.x; } float ImGui::GetTextLineHeight() diff --git a/imgui_internal.h b/imgui_internal.h index c787dbd11..c67eab928 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -607,6 +607,7 @@ struct IMGUI_API ImGuiWindow ImVec2 SizeFull; // Size when non collapsed ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() + ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect ImGuiID MoveID; // == window->GetID("#MOVE") ImVec2 Scroll; From dff078365fb8473ffdd6cc060386fdefa30d1e5c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 18:08:51 +0200 Subject: [PATCH 101/105] Fix selectable/tree node not reaching right-side of contents size when horizontal scrolling is active and no explicit size is known --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3c310dd64..3f73781c8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4203,9 +4203,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Update ContentsRegionMax. All the variable it depends on are set above in this function. window->ContentsRegionRect.Min.x = -window->Scroll.x + window->WindowPadding.x; - window->ContentsRegionRect.Min.x = -window->Scroll.y + window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y; - window->ContentsRegionRect.Max.x = (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : window->Size.x - window->ScrollbarSizes.x) - window->Scroll.x - window->WindowPadding.x; - window->ContentsRegionRect.Max.y = (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : window->Size.y - window->ScrollbarSizes.y) - window->Scroll.y - window->WindowPadding.y; + window->ContentsRegionRect.Min.x = -window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); + window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : ImMax(window->SizeContents.x, window->Size.x - window->ScrollbarSizes.x)); + window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : ImMax(window->SizeContents.y, window->Size.y - window->ScrollbarSizes.y)); // Setup drawing context window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; From 784e1ef053baa87410f1e397d379d3494d9e9181 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 18:12:25 +0200 Subject: [PATCH 102/105] CollapsingHeader() with close button adapt to horizontal scrolling (#600) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 3f73781c8..0e9ee8276 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5958,7 +5958,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. ImGuiContext& g = *GImGui; float button_sz = g.FontSize * 0.5f; - if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(window->DC.LastItemRect.Max.x - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) + if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) *p_open = false; } From dcef7dedce84b780d7f9c42b4effec6153210197 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 18:24:02 +0200 Subject: [PATCH 103/105] Comments (#590) --- imgui.cpp | 2 ++ imgui.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 0e9ee8276..2567d604d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5933,6 +5933,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l return is_open; } +// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). +// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui.h b/imgui.h index c894860ec..a3db5b064 100644 --- a/imgui.h +++ b/imgui.h @@ -329,7 +329,7 @@ namespace ImGui IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceeding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. - IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop(). + IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header // Widgets: Selectable / Lists From 9886c1b43d79b60f5502e0293f099ecdfe501f6c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 18:37:26 +0200 Subject: [PATCH 104/105] Undo modification of ContentsRegionRect.Max, too many side-effects (undo dff078365fb8473ffdd6cc060386fdefa30d1e5c) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2567d604d..e92e807bd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4204,8 +4204,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Update ContentsRegionMax. All the variable it depends on are set above in this function. window->ContentsRegionRect.Min.x = -window->Scroll.x + window->WindowPadding.x; window->ContentsRegionRect.Min.x = -window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); - window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : ImMax(window->SizeContents.x, window->Size.x - window->ScrollbarSizes.x)); - window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : ImMax(window->SizeContents.y, window->Size.y - window->ScrollbarSizes.y)); + window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x)); + window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y)); // Setup drawing context window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; From 0fb51b6b4bca115074b7c4bb8cf5815081d53812 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 29 May 2016 18:58:41 +0200 Subject: [PATCH 105/105] Removed various superflous ImGui:: prefixes in internal code --- imgui.cpp | 554 +++++++++++++++++++++++++++--------------------------- 1 file changed, 275 insertions(+), 279 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e92e807bd..90e6a24dc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1927,7 +1927,7 @@ ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y) ImGuiContext& g = *GImGui; ImVec2 content_max; if (size.x < 0.0f || size.y < 0.0f) - content_max = g.CurrentWindow->Pos + ImGui::GetContentRegionMax(); + content_max = g.CurrentWindow->Pos + GetContentRegionMax(); if (size.x <= 0.0f) size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x; if (size.y <= 0.0f) @@ -1942,7 +1942,7 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) ImGuiWindow* window = GetCurrentWindowRead(); if (wrap_pos_x == 0.0f) - wrap_pos_x = ImGui::GetContentRegionMax().x + window->Pos.x; + wrap_pos_x = GetContentRegionMax().x + window->Pos.x; else if (wrap_pos_x > 0.0f) wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space @@ -2834,7 +2834,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons // Perform CPU side clipping for single clipped element to avoid using scissor state ImVec2 pos = pos_min; - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f); + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); if (!clip_max) clip_max = &pos_max; bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); @@ -3504,26 +3504,26 @@ void ImGui::EndPopup() // driven by click position. bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) { - if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(mouse_button)) - ImGui::OpenPopupEx(str_id, false); - return ImGui::BeginPopup(str_id); + if (IsItemHovered() && IsMouseClicked(mouse_button)) + OpenPopupEx(str_id, false); + return BeginPopup(str_id); } bool ImGui::BeginPopupContextWindow(bool also_over_items, const char* str_id, int mouse_button) { if (!str_id) str_id = "window_context_menu"; - if (ImGui::IsMouseHoveringWindow() && ImGui::IsMouseClicked(mouse_button)) - if (also_over_items || !ImGui::IsAnyItemHovered()) - ImGui::OpenPopupEx(str_id, true); - return ImGui::BeginPopup(str_id); + if (IsMouseHoveringWindow() && IsMouseClicked(mouse_button)) + if (also_over_items || !IsAnyItemHovered()) + OpenPopupEx(str_id, true); + return BeginPopup(str_id); } bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) { if (!str_id) str_id = "void_context_menu"; - if (!ImGui::IsMouseHoveringAnyWindow() && ImGui::IsMouseClicked(mouse_button)) - ImGui::OpenPopupEx(str_id, true); - return ImGui::BeginPopup(str_id); + if (!IsMouseHoveringAnyWindow() && IsMouseClicked(mouse_button)) + OpenPopupEx(str_id, true); + return BeginPopup(str_id); } bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) @@ -3531,7 +3531,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindow* window = GetCurrentWindow(); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; - const ImVec2 content_avail = ImGui::GetContentRegionAvail(); + const ImVec2 content_avail = GetContentRegionAvail(); ImVec2 size = ImFloor(size_arg); if (size.x <= 0.0f) { @@ -3580,7 +3580,7 @@ void ImGui::EndChild() else { // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting. - ImVec2 sz = ImGui::GetWindowSize(); + ImVec2 sz = GetWindowSize(); if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f sz.x = ImMax(4.0f, sz.x); if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) @@ -4330,12 +4330,12 @@ void ImGui::End() ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImGui::Columns(1, "#CloseColumns"); + Columns(1, "#CloseColumns"); PopClipRect(); // inner window clip rectangle // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging - ImGui::LogFinish(); + LogFinish(); // Pop // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin(). @@ -4516,7 +4516,7 @@ float ImGui::CalcItemWidth() if (w < 0.0f) { // 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. - float width_to_right_edge = ImGui::GetContentRegionAvail().x; + float width_to_right_edge = GetContentRegionAvail().x; w = ImMax(1.0f, width_to_right_edge + w); } w = (float)(int)w; @@ -4981,7 +4981,7 @@ ImVec2 ImGui::GetContentRegionMax() ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max; if (window->DC.ColumnsCount != 1) - mx.x = ImGui::GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; + mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; return mx; } @@ -5173,7 +5173,7 @@ void ImGui::SetScrollHere(float center_y_ratio) { ImGuiWindow* window = GetCurrentWindow(); float target_y = window->DC.CursorPosPrevLine.y + (window->DC.PrevLineHeight * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. - ImGui::SetScrollFromPosY(target_y - window->Pos.y, center_y_ratio); + SetScrollFromPosY(target_y - window->Pos.y, center_y_ratio); } void ImGui::SetKeyboardFocusHere(int offset) @@ -5216,9 +5216,9 @@ void ImGui::Text(const char* fmt, ...) void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) { - ImGui::PushStyleColor(ImGuiCol_Text, col); + PushStyleColor(ImGuiCol_Text, col); TextV(fmt, args); - ImGui::PopStyleColor(); + PopStyleColor(); } void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) @@ -5231,9 +5231,9 @@ void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) void ImGui::TextDisabledV(const char* fmt, va_list args) { - ImGui::PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]); + PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]); TextV(fmt, args); - ImGui::PopStyleColor(); + PopStyleColor(); } void ImGui::TextDisabled(const char* fmt, ...) @@ -5246,9 +5246,9 @@ void ImGui::TextDisabled(const char* fmt, ...) void ImGui::TextWrappedV(const char* fmt, va_list args) { - ImGui::PushTextWrapPos(0.0f); + PushTextWrapPos(0.0f); TextV(fmt, args); - ImGui::PopTextWrapPos(); + PopTextWrapPos(); } void ImGui::TextWrapped(const char* fmt, ...) @@ -5280,7 +5280,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. const char* line = text; - const float line_height = ImGui::GetTextLineHeight(); + const float line_height = GetTextLineHeight(); const ImVec2 text_pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrentLineTextBaseOffset); const ImRect clip_rect = window->ClipRect; ImVec2 text_size(0,0); @@ -5311,7 +5311,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) // Lines to render if (line < text_end) { - ImRect line_rect(pos, pos + ImVec2(ImGui::GetWindowWidth(), line_height)); + ImRect line_rect(pos, pos + ImVec2(GetWindowWidth(), line_height)); while (line < text_end) { const char* line_end = strchr(line, '\n'); @@ -5377,7 +5377,7 @@ void ImGui::AlignFirstTextHeightToWidgets() // Declare a dummy item size to that upcoming items that are smaller will center-align on the newly expanded line height. ImGuiContext& g = *GImGui; ItemSize(ImVec2(0, g.FontSize + g.Style.FramePadding.y*2), g.Style.FramePadding.y); - ImGui::SameLine(0, 0); + SameLine(0, 0); } // Add a label+text combo aligned to other label+value widgets @@ -5475,7 +5475,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. - if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && ImGui::IsMouseClicked(0, true)) + if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true)) pressed = true; } } @@ -5538,7 +5538,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags // Automatically close popups //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) - // ImGui::CloseCurrentPopup(); + // CloseCurrentPopup(); return pressed; } @@ -5583,23 +5583,23 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) // Upper-right button to close a window. bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); + ImGuiWindow* window = GetCurrentWindow(); const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); bool hovered, held; - bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held); + bool pressed = ButtonBehavior(bb, id, &hovered, &held); // Render - const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); const ImVec2 center = bb.GetCenter(); window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12); const float cross_extent = (radius * 0.7071f) - 1.0f; if (hovered) { - window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), ImGui::GetColorU32(ImGuiCol_Text)); - window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), ImGui::GetColorU32(ImGuiCol_Text)); + window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); + window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); } return pressed; @@ -5644,9 +5644,9 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I // Default to using texture ID as ID. User can still push string/integer prefixes. // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV. - ImGui::PushID((void *)user_texture_id); + PushID((void *)user_texture_id); const ImGuiID id = window->GetID("#image"); - ImGui::PopID(); + PopID(); const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2); @@ -5731,7 +5731,7 @@ void ImGui::LogFinish() if (!g.LogEnabled) return; - ImGui::LogText(IM_NEWLINE); + LogText(IM_NEWLINE); g.LogEnabled = false; if (g.LogFile != NULL) { @@ -5754,20 +5754,16 @@ void ImGui::LogButtons() { ImGuiContext& g = *GImGui; - ImGui::PushID("LogButtons"); - const bool log_to_tty = ImGui::Button("Log To TTY"); - ImGui::SameLine(); - const bool log_to_file = ImGui::Button("Log To File"); - ImGui::SameLine(); - const bool log_to_clipboard = ImGui::Button("Log To Clipboard"); - ImGui::SameLine(); - - ImGui::PushItemWidth(80.0f); - ImGui::PushAllowKeyboardFocus(false); - ImGui::SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL); - ImGui::PopAllowKeyboardFocus(); - ImGui::PopItemWidth(); - ImGui::PopID(); + PushID("LogButtons"); + const bool log_to_tty = Button("Log To TTY"); SameLine(); + const bool log_to_file = Button("Log To File"); SameLine(); + const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); + PushItemWidth(80.0f); + PushAllowKeyboardFocus(false); + SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL); + PopAllowKeyboardFocus(); + PopItemWidth(); + PopID(); // Start logging at the end of the function so that the buttons don't appear in the log if (log_to_tty) @@ -6131,7 +6127,7 @@ void ImGui::Bullet() ItemSize(bb); if (!ItemAdd(bb, NULL)) { - ImGui::SameLine(0, style.FramePadding.x*2); + SameLine(0, style.FramePadding.x*2); return; } @@ -6594,7 +6590,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max) { float v_deg = (*v_rad) * 360.0f / (2*IM_PI); - bool value_changed = ImGui::SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); + bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); *v_rad = v_deg * (2*IM_PI) / 360.0f; return value_changed; } @@ -6604,7 +6600,7 @@ bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const cha if (!display_format) display_format = "%.0f"; float v_f = (float)*v; - bool value_changed = ImGui::SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); + bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); *v = (int)v_f; return value_changed; } @@ -6614,7 +6610,7 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, if (!display_format) display_format = "%.0f"; float v_f = (float)*v; - bool value_changed = ImGui::VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); + bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); *v = (int)v_f; return value_changed; } @@ -6628,21 +6624,21 @@ bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_mi ImGuiContext& g = *GImGui; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { - ImGui::PushID(i); - value_changed |= ImGui::SliderFloat("##v", &v[i], v_min, v_max, display_format, power); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); - ImGui::PopItemWidth(); + PushID(i); + value_changed |= SliderFloat("##v", &v[i], v_min, v_max, display_format, power); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); } - ImGui::PopID(); + PopID(); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); return value_changed; } @@ -6670,21 +6666,21 @@ bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int ImGuiContext& g = *GImGui; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { - ImGui::PushID(i); - value_changed |= ImGui::SliderInt("##v", &v[i], v_min, v_max, display_format); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); - ImGui::PopItemWidth(); + PushID(i); + value_changed |= SliderInt("##v", &v[i], v_min, v_max, display_format); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); } - ImGui::PopID(); + PopID(); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); return value_changed; } @@ -6728,7 +6724,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } float v_cur = g.DragCurrentValue; - const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0, 1.0f); + const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) { float speed = v_speed; @@ -6850,21 +6846,21 @@ bool ImGui::DragFloatN(const char* label, float* v, int components, float v_spee ImGuiContext& g = *GImGui; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { - ImGui::PushID(i); - value_changed |= ImGui::DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); - ImGui::PopItemWidth(); + PushID(i); + value_changed |= DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); } - ImGui::PopID(); + PopID(); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); return value_changed; } @@ -6891,20 +6887,20 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu return false; ImGuiContext& g = *GImGui; - ImGui::PushID(label); - ImGui::BeginGroup(); + PushID(label); + BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = ImGui::DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power); - ImGui::PopItemWidth(); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= ImGui::DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power); - ImGui::PopItemWidth(); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); + bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); + value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); - ImGui::PopID(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + PopID(); return value_changed; } @@ -6915,7 +6911,7 @@ bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_m if (!display_format) display_format = "%.0f"; float v_f = (float)*v; - bool value_changed = ImGui::DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); + bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); *v = (int)v_f; return value_changed; } @@ -6928,21 +6924,21 @@ bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, i ImGuiContext& g = *GImGui; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { - ImGui::PushID(i); - value_changed |= ImGui::DragInt("##v", &v[i], v_speed, v_min, v_max, display_format); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); - ImGui::PopItemWidth(); + PushID(i); + value_changed |= DragInt("##v", &v[i], v_speed, v_min, v_max, display_format); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); } - ImGui::PopID(); + PopID(); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); return value_changed; } @@ -6969,20 +6965,20 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_ return false; ImGuiContext& g = *GImGui; - ImGui::PushID(label); - ImGui::BeginGroup(); + PushID(label); + BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = ImGui::DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); - ImGui::PopItemWidth(); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= ImGui::DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); - ImGui::PopItemWidth(); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); + bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); + value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); - ImGui::PopID(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + PopID(); return value_changed; } @@ -7042,9 +7038,9 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge const float v0 = values_getter(data, (v_idx + values_offset) % values_count); const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); if (plot_type == ImGuiPlotType_Lines) - ImGui::SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1); + SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1); else if (plot_type == ImGuiPlotType_Histogram) - ImGui::SetTooltip("%d: %8.4g", v_idx, v0); + SetTooltip("%d: %8.4g", v_idx, v0); v_hovered = v_idx; } @@ -7215,7 +7211,7 @@ bool ImGui::Checkbox(const char* label, bool* v) bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) { bool v = ((*flags & flags_value) == flags_value); - bool pressed = ImGui::Checkbox(label, &v); + bool pressed = Checkbox(label, &v); if (pressed) { if (v) @@ -7286,7 +7282,7 @@ bool ImGui::RadioButton(const char* label, bool active) bool ImGui::RadioButton(const char* label, int* v, int v_button) { - const bool pressed = ImGui::RadioButton(label, *v == v_button); + const bool pressed = RadioButton(label, *v == v_button); if (pressed) { *v = v_button; @@ -7567,18 +7563,18 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; const ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); ImGuiWindow* draw_window = window; if (is_multiline) { - ImGui::BeginGroup(); - if (!ImGui::BeginChildFrame(id, frame_bb.GetSize())) + BeginGroup(); + if (!BeginChildFrame(id, frame_bb.GetSize())) { - ImGui::EndChildFrame(); - ImGui::EndGroup(); + EndChildFrame(); + EndGroup(); return false; } draw_window = GetCurrentWindow(); @@ -7605,7 +7601,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 password_font->FallbackGlyph = glyph; password_font->FallbackXAdvance = glyph->XAdvance; IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexXAdvance.empty() && password_font->IndexLookup.empty()); - ImGui::PushFont(password_font); + PushFont(password_font); } // NB: we are only allowed to access 'edit_state' if we are the active widget. @@ -8090,13 +8086,13 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (is_multiline) { - ImGui::Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line - ImGui::EndChildFrame(); - ImGui::EndGroup(); + Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line + EndChildFrame(); + EndGroup(); } if (is_password) - ImGui::PopFont(); + PopFont(); // Log as text if (g.LogEnabled && !is_password) @@ -8135,11 +8131,11 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data const ImGuiStyle& style = g.Style; const ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding*2.0f; if (step_ptr) - ImGui::PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); + PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); char buf[64]; DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf)); @@ -8148,35 +8144,35 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal)) extra_flags |= ImGuiInputTextFlags_CharsDecimal; extra_flags |= ImGuiInputTextFlags_AutoSelectAll; - if (ImGui::InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) + if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) value_changed = DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, scalar_format); // Step buttons if (step_ptr) { - ImGui::PopItemWidth(); - ImGui::SameLine(0, style.ItemInnerSpacing.x); + PopItemWidth(); + SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { DataTypeApplyOp(data_type, '-', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } - ImGui::SameLine(0, style.ItemInnerSpacing.x); + SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { DataTypeApplyOp(data_type, '+', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } } - ImGui::PopID(); + PopID(); if (label_size.x > 0) { - ImGui::SameLine(0, style.ItemInnerSpacing.x); + SameLine(0, style.ItemInnerSpacing.x); RenderText(ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + style.FramePadding.y), label); ItemSize(label_size, style.FramePadding.y); } - ImGui::EndGroup(); + EndGroup(); return value_changed; } @@ -8206,22 +8202,22 @@ bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal ImGuiContext& g = *GImGui; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { - ImGui::PushID(i); - value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); - ImGui::PopItemWidth(); + PushID(i); + value_changed |= InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); } - ImGui::PopID(); + PopID(); window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); return value_changed; } @@ -8249,22 +8245,22 @@ bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextF ImGuiContext& g = *GImGui; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); PushMultiItemsWidths(components); for (int i = 0; i < components; i++) { - ImGui::PushID(i); - value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, extra_flags); - ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); - ImGui::PopItemWidth(); + PushID(i); + value_changed |= InputInt("##v", &v[i], 0, 0, extra_flags); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); } - ImGui::PopID(); + PopID(); window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); - ImGui::TextUnformatted(label, FindRenderedTextEnd(label)); - ImGui::EndGroup(); + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); return value_changed; } @@ -8408,35 +8404,35 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi popup_y2 = frame_bb.Min.y; } ImRect popup_rect(ImVec2(frame_bb.Min.x, popup_y1), ImVec2(frame_bb.Max.x, popup_y2)); - ImGui::SetNextWindowPos(popup_rect.Min); - ImGui::SetNextWindowSize(popup_rect.GetSize()); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + SetNextWindowPos(popup_rect.Min); + SetNextWindowSize(popup_rect.GetSize()); + PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); if (BeginPopupEx(label, flags)) { // Display items - ImGui::Spacing(); + Spacing(); for (int i = 0; i < items_count; i++) { - ImGui::PushID((void*)(intptr_t)i); + PushID((void*)(intptr_t)i); const bool item_selected = (i == *current_item); const char* item_text; if (!items_getter(data, i, &item_text)) item_text = "*Unknown item*"; - if (ImGui::Selectable(item_text, item_selected)) + if (Selectable(item_text, item_selected)) { SetActiveID(0); value_changed = true; *current_item = i; } if (item_selected && popup_opened_now) - ImGui::SetScrollHere(); - ImGui::PopID(); + SetScrollHere(); + PopID(); } - ImGui::EndPopup(); + EndPopup(); } - ImGui::PopStyleVar(); + PopStyleVar(); } return value_changed; } @@ -8465,7 +8461,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // Fill horizontal space. ImVec2 window_padding = window->WindowPadding; - float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? ImGui::GetWindowContentRegionMax().x : ImGui::GetContentRegionMax().x; + float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x; float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x); ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y); ImRect bb_with_spacing(pos, pos + size_draw); @@ -8508,22 +8504,22 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) { PushColumnClipRect(); - bb_with_spacing.Max.x -= (ImGui::GetContentRegionMax().x - max_x); + bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); } - if (flags & ImGuiSelectableFlags_Disabled) ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); RenderTextClipped(bb.Min, bb_with_spacing.Max, label, NULL, &label_size); - if (flags & ImGuiSelectableFlags_Disabled) ImGui::PopStyleColor(); + if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups if (pressed && !(flags & ImGuiSelectableFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) - ImGui::CloseCurrentPopup(); + CloseCurrentPopup(); return pressed; } bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { - if (ImGui::Selectable(label, *p_selected, flags, size_arg)) + if (Selectable(label, *p_selected, flags, size_arg)) { *p_selected = !*p_selected; return true; @@ -8539,22 +8535,22 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) if (window->SkipItems) return false; - const ImGuiStyle& style = ImGui::GetStyle(); - const ImGuiID id = ImGui::GetID(label); + const ImGuiStyle& style = GetStyle(); + const ImGuiID id = GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); window->DC.LastItemRect = bb; - ImGui::BeginGroup(); + BeginGroup(); if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - ImGui::BeginChildFrame(id, frame_bb.GetSize()); + BeginChildFrame(id, frame_bb.GetSize()); return true; } @@ -8570,24 +8566,24 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). ImVec2 size; size.x = 0.0f; - size.y = ImGui::GetTextLineHeightWithSpacing() * height_in_items_f + ImGui::GetStyle().ItemSpacing.y; - return ImGui::ListBoxHeader(label, size); + size.y = GetTextLineHeightWithSpacing() * height_in_items_f + GetStyle().ItemSpacing.y; + return ListBoxHeader(label, size); } void ImGui::ListBoxFooter() { ImGuiWindow* parent_window = GetParentWindow(); const ImRect bb = parent_window->DC.LastItemRect; - const ImGuiStyle& style = ImGui::GetStyle(); + const ImGuiStyle& style = GetStyle(); - ImGui::EndChildFrame(); + EndChildFrame(); // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect) // We call SameLine() to restore DC.CurrentLine* data - ImGui::SameLine(); + SameLine(); parent_window->DC.CursorPos = bb.Min; ItemSize(bb, style.FramePadding.y); - ImGui::EndGroup(); + EndGroup(); } bool ImGui::ListBox(const char* label, int* current_item, const char** items, int items_count, int height_items) @@ -8598,12 +8594,12 @@ bool ImGui::ListBox(const char* label, int* current_item, const char** items, in bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) { - if (!ImGui::ListBoxHeader(label, items_count, height_in_items)) + if (!ListBoxHeader(label, items_count, height_in_items)) return false; // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. bool value_changed = false; - ImGuiListClipper clipper(items_count, ImGui::GetTextLineHeightWithSpacing()); + ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { @@ -8612,15 +8608,15 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v if (!items_getter(data, i, &item_text)) item_text = "*Unknown item*"; - ImGui::PushID(i); - if (ImGui::Selectable(item_text, item_selected)) + PushID(i); + if (Selectable(item_text, item_selected)) { *current_item = i; value_changed = true; } - ImGui::PopID(); + PopID(); } - ImGui::ListBoxFooter(); + ListBoxFooter(); return value_changed; } @@ -8635,14 +8631,14 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, ImGui::GetContentRegionAvail().x - w); + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - bool pressed = ImGui::Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f)); + bool pressed = Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f)); if (shortcut_size.x > 0.0f) { - ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); - ImGui::PopStyleColor(); + PopStyleColor(); } if (selected) @@ -8653,7 +8649,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) { - if (ImGui::MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) + if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) { if (p_selected) *p_selected = !*p_selected; @@ -8665,15 +8661,15 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool ImGui::BeginMainMenuBar() { ImGuiContext& g = *GImGui; - ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); - ImGui::SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.FontBaseSize + g.Style.FramePadding.y * 2.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); - if (!ImGui::Begin("##MainMenuBar", NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_MenuBar) - || !ImGui::BeginMenuBar()) + SetNextWindowPos(ImVec2(0.0f, 0.0f)); + SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.FontBaseSize + g.Style.FramePadding.y * 2.0f)); + PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); + if (!Begin("##MainMenuBar", NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_MenuBar) + || !BeginMenuBar()) { - ImGui::End(); - ImGui::PopStyleVar(2); + End(); + PopStyleVar(2); return false; } g.CurrentWindow->DC.MenuBarOffsetX += g.Style.DisplaySafeAreaPadding.x; @@ -8682,9 +8678,9 @@ bool ImGui::BeginMainMenuBar() void ImGui::EndMainMenuBar() { - ImGui::EndMenuBar(); - ImGui::End(); - ImGui::PopStyleVar(2); + EndMenuBar(); + End(); + PopStyleVar(2); } bool ImGui::BeginMenuBar() @@ -8696,14 +8692,14 @@ bool ImGui::BeginMenuBar() return false; IM_ASSERT(!window->DC.MenuBarAppending); - ImGui::BeginGroup(); // Save position - ImGui::PushID("##menubar"); + BeginGroup(); // Save position + PushID("##menubar"); ImRect rect = window->MenuBarRect(); PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false); window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.MenuBarAppending = true; - ImGui::AlignFirstTextHeightToWidgets(); + AlignFirstTextHeightToWidgets(); return true; } @@ -8716,10 +8712,10 @@ void ImGui::EndMenuBar() IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); IM_ASSERT(window->DC.MenuBarAppending); PopClipRect(); - ImGui::PopID(); + PopID(); window->DC.MenuBarOffsetX = window->DC.CursorPos.x - window->MenuBarRect().Min.x; window->DC.GroupStack.back().AdvanceCursor = false; - ImGui::EndGroup(); + EndGroup(); window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.MenuBarAppending = false; } @@ -8748,22 +8744,22 @@ bool ImGui::BeginMenu(const char* label, bool enabled) { popup_pos = ImVec2(pos.x - window->WindowPadding.x, pos.y - style.FramePadding.y + window->MenuBarHeight()); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); + PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); float w = label_size.x; - pressed = ImGui::Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); - ImGui::PopStyleVar(); - ImGui::SameLine(); + pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + PopStyleVar(); + SameLine(); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); } else { popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame - float extra_w = ImMax(0.0f, ImGui::GetContentRegionAvail().x - w); - pressed = ImGui::Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); - if (!enabled) ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); + pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); RenderCollapseTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), false); - if (!enabled) ImGui::PopStyleColor(); + if (!enabled) PopStyleColor(); } bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); @@ -8810,17 +8806,17 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) { // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. - ImGui::OpenPopup(label); + OpenPopup(label); return false; } menu_is_open |= want_open; if (want_open) - ImGui::OpenPopup(label); + OpenPopup(label); if (menu_is_open) { - ImGui::SetNextWindowPos(popup_pos, ImGuiSetCond_Always); + SetNextWindowPos(popup_pos, ImGuiSetCond_Always); ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); menu_is_open = BeginPopupEx(label, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } @@ -8830,7 +8826,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) void ImGui::EndMenu() { - ImGui::EndPopup(); + EndPopup(); } // A little colored square. Return true when clicked. @@ -8855,7 +8851,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); if (hovered) - ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8(col.x), IM_F32_TO_INT8(col.y), IM_F32_TO_INT8(col.z), IM_F32_TO_INT8(col.z)); + SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8(col.x), IM_F32_TO_INT8(col.y), IM_F32_TO_INT8(col.z), IM_F32_TO_INT8(col.z)); return pressed; } @@ -8867,7 +8863,7 @@ bool ImGui::ColorEdit3(const char* label, float col[3]) col4[1] = col[1]; col4[2] = col[2]; col4[3] = 1.0f; - const bool value_changed = ImGui::ColorEdit4(label, col4, false); + const bool value_changed = ColorEdit4(label, col4, false); col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2]; @@ -8894,15 +8890,15 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) float f[4] = { col[0], col[1], col[2], col[3] }; if (edit_mode == ImGuiColorEditMode_HSV) - ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); + ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); int i[4] = { IM_F32_TO_INT8(f[0]), IM_F32_TO_INT8(f[1]), IM_F32_TO_INT8(f[2]), IM_F32_TO_INT8(f[3]) }; int components = alpha ? 4 : 3; bool value_changed = false; - ImGui::BeginGroup(); - ImGui::PushID(label); + BeginGroup(); + PushID(label); const bool hsv = (edit_mode == 1); switch (edit_mode) @@ -8925,17 +8921,17 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) }; const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; - ImGui::PushItemWidth(w_item_one); + PushItemWidth(w_item_one); for (int n = 0; n < components; n++) { if (n > 0) - ImGui::SameLine(0, style.ItemInnerSpacing.x); + SameLine(0, style.ItemInnerSpacing.x); if (n + 1 == components) - ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]); + PushItemWidth(w_item_last); + value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]); } - ImGui::PopItemWidth(); - ImGui::PopItemWidth(); + PopItemWidth(); + PopItemWidth(); } break; case ImGuiColorEditMode_HEX: @@ -8947,8 +8943,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", i[0], i[1], i[2], i[3]); else ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); - ImGui::PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); - if (ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) + PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); + if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) { value_changed |= true; char* p = buf; @@ -8960,24 +8956,24 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) else sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); } - ImGui::PopItemWidth(); + PopItemWidth(); } break; } - ImGui::SameLine(0, style.ItemInnerSpacing.x); + SameLine(0, style.ItemInnerSpacing.x); const ImVec4 col_display(col[0], col[1], col[2], 1.0f); - if (ImGui::ColorButton(col_display)) + if (ColorButton(col_display)) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! // Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8(col[0]), IM_F32_TO_INT8(col[1]), IM_F32_TO_INT8(col[2]), IM_F32_TO_INT8(col[3])); + if (IsItemHovered()) + SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8(col[0]), IM_F32_TO_INT8(col[1]), IM_F32_TO_INT8(col[2]), IM_F32_TO_INT8(col[3])); if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) { - ImGui::SameLine(0, style.ItemInnerSpacing.x); + SameLine(0, style.ItemInnerSpacing.x); const char* button_titles[3] = { "RGB", "HSV", "HEX" }; if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups)) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! @@ -8986,15 +8982,15 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) const char* label_display_end = FindRenderedTextEnd(label); if (label != label_display_end) { - ImGui::SameLine(0, (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) ? -1.0f : style.ItemInnerSpacing.x); - ImGui::TextUnformatted(label, label_display_end); + SameLine(0, (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) ? -1.0f : style.ItemInnerSpacing.x); + TextUnformatted(label, label_display_end); } // Convert back for (int n = 0; n < 4; n++) f[n] = i[n] / 255.0f; if (edit_mode == 1) - ImGui::ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); + ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); if (value_changed) { @@ -9005,8 +9001,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) col[3] = f[3]; } - ImGui::PopID(); - ImGui::EndGroup(); + PopID(); + EndGroup(); return value_changed; } @@ -9045,7 +9041,7 @@ void ImGui::Separator() ImGuiContext& g = *GImGui; if (g.LogEnabled) - ImGui::LogText(IM_NEWLINE "--------------------------------"); + LogText(IM_NEWLINE "--------------------------------"); if (window->DC.ColumnsCount > 1) { @@ -9103,7 +9099,7 @@ void ImGui::BeginGroup() void ImGui::EndGroup() { ImGuiWindow* window = GetCurrentWindow(); - ImGuiStyle& style = ImGui::GetStyle(); + ImGuiStyle& style = GetStyle(); IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls @@ -9180,14 +9176,14 @@ void ImGui::NextColumn() ImGuiContext& g = *GImGui; if (window->DC.ColumnsCount > 1) { - ImGui::PopItemWidth(); + PopItemWidth(); PopClipRect(); window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = ImGui::GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent); } else @@ -9203,7 +9199,7 @@ void ImGui::NextColumn() window->DC.CurrentLineTextBaseOffset = 0.0f; PushColumnClipRect(); - ImGui::PushItemWidth(ImGui::GetColumnWidth() * 0.65f); // FIXME: Move on columns setup + PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup } } @@ -9299,7 +9295,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) { if (window->DC.ColumnsCurrent != 0) ItemSize(ImVec2(0,0)); // Advance to column 0 - ImGui::PopItemWidth(); + PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); @@ -9342,9 +9338,9 @@ void ImGui::Columns(int columns_count, const char* id, bool border) // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. - ImGui::PushID(0x11223347 + (id ? 0 : columns_count)); + PushID(0x11223347 + (id ? 0 : columns_count)); window->DC.ColumnsSetID = window->GetID(id ? id : "columns"); - ImGui::PopID(); + PopID(); // Set state for first column window->DC.ColumnsCurrent = 0; @@ -9373,7 +9369,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) } window->DrawList->ChannelsSplit(window->DC.ColumnsCount); PushColumnClipRect(); - ImGui::PushItemWidth(ImGui::GetColumnWidth() * 0.65f); + PushItemWidth(GetColumnWidth() * 0.65f); } else { @@ -9400,7 +9396,7 @@ void ImGui::Unindent(float indent_w) void ImGui::TreePush(const char* str_id) { ImGuiWindow* window = GetCurrentWindow(); - ImGui::Indent(); + Indent(); window->DC.TreeDepth++; PushID(str_id ? str_id : "#TreePush"); } @@ -9408,7 +9404,7 @@ void ImGui::TreePush(const char* str_id) void ImGui::TreePush(const void* ptr_id) { ImGuiWindow* window = GetCurrentWindow(); - ImGui::Indent(); + Indent(); window->DC.TreeDepth++; PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); } @@ -9416,7 +9412,7 @@ void ImGui::TreePush(const void* ptr_id) void ImGui::TreePushRawID(ImGuiID id) { ImGuiWindow* window = GetCurrentWindow(); - ImGui::Indent(); + Indent(); window->DC.TreeDepth++; window->IDStack.push_back(id); } @@ -9424,24 +9420,24 @@ void ImGui::TreePushRawID(ImGuiID id) void ImGui::TreePop() { ImGuiWindow* window = GetCurrentWindow(); - ImGui::Unindent(); + Unindent(); window->DC.TreeDepth--; PopID(); } void ImGui::Value(const char* prefix, bool b) { - ImGui::Text("%s: %s", prefix, (b ? "true" : "false")); + Text("%s: %s", prefix, (b ? "true" : "false")); } void ImGui::Value(const char* prefix, int v) { - ImGui::Text("%s: %d", prefix, v); + Text("%s: %d", prefix, v); } void ImGui::Value(const char* prefix, unsigned int v) { - ImGui::Text("%s: %d", prefix, v); + Text("%s: %d", prefix, v); } void ImGui::Value(const char* prefix, float v, const char* float_format) @@ -9450,33 +9446,33 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) { char fmt[64]; ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format); - ImGui::Text(fmt, prefix, v); + Text(fmt, prefix, v); } else { - ImGui::Text("%s: %.3f", prefix, v); + Text("%s: %.3f", prefix, v); } } // FIXME: May want to remove those helpers? void ImGui::ValueColor(const char* prefix, const ImVec4& v) { - ImGui::Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w); - ImGui::SameLine(); - ImGui::ColorButton(v, true); + Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w); + SameLine(); + ColorButton(v, true); } void ImGui::ValueColor(const char* prefix, unsigned int v) { - ImGui::Text("%s: %08X", prefix, v); - ImGui::SameLine(); + Text("%s: %08X", prefix, v); + SameLine(); ImVec4 col; col.x = (float)((v >> 0) & 0xFF) / 255.0f; col.y = (float)((v >> 8) & 0xFF) / 255.0f; col.z = (float)((v >> 16) & 0xFF) / 255.0f; col.w = (float)((v >> 24) & 0xFF) / 255.0f; - ImGui::ColorButton(col, true); + ColorButton(col, true); } //-----------------------------------------------------------------------------