From 468fcd7b304f2017d44dd54aeeed1dcad197a4ff Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 31 Mar 2015 00:15:23 +0100 Subject: [PATCH 01/37] Fixed mouse wheel scrolling (broken 2 commits ago 9d16b85ed2f72c0644889825d28f6c56e0abf79b) --- imgui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 83d5b41f..5c0c65be 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1968,7 +1968,6 @@ void ImGui::NewFrame() float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); float scale = new_font_scale / window->FontWindowScale; window->FontWindowScale = new_font_scale; - g.FontSize = window->CalcFontSize(); const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; window->Pos += offset; @@ -1983,7 +1982,7 @@ void ImGui::NewFrame() if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) { const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5; - window->NextScrollY -= g.IO.MouseWheel * g.FontSize * scroll_lines; + window->NextScrollY -= g.IO.MouseWheel * window->CalcFontSize() * scroll_lines; } } } From eb3e640fa645340d4d9478efb596410f75ae90e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 31 Mar 2015 00:41:15 +0100 Subject: [PATCH 02/37] Fixed style.DisplaySafeAreaPadding handling from being applied on window that never were auto-fit --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5c0c65be..c6c366de 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3103,7 +3103,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Clamp into view if (!(window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Tooltip)) { - if (window->AutoFitFrames == 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. + if (window->AutoFitFrames <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. { ImVec2 clip_min = style.DisplaySafeAreaPadding; ImVec2 clip_max = g.IO.DisplaySize - style.DisplaySafeAreaPadding; From c0699958ce292c38ed994d81a9db68499a3c3b06 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 1 Apr 2015 15:05:06 +0100 Subject: [PATCH 03/37] Fix for Coverity static analysis --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c6c366de..d0bba01d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8201,7 +8201,7 @@ void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) ImVector& rects = *(ImVector*)p_rects; if (pass == 0) { - stbrp_rect r; + stbrp_rect r = { 0 }; r.w = (TEX_DATA_W*2)+1; r.h = TEX_DATA_H+1; rects.push_back(r); From a4cf50affeb480035228762d687012f0b74fce0d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 1 Apr 2015 15:08:42 +0100 Subject: [PATCH 04/37] Fix uninitialized fields - MouseCursor set by first call to NewFrame() --- imgui.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index d0bba01d..5cf379c6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1012,6 +1012,7 @@ struct ImGuiDrawContext LastItemID = 0; LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); LastItemHoveredAndUsable = LastItemHoveredRect = false; + ColorEditMode = ImGuiColorEditMode_RGB; StateStorage = NULL; ColumnsStartX = 0.0f; @@ -1192,6 +1193,8 @@ struct ImGuiState memset(Tooltip, 0, sizeof(Tooltip)); PrivateClipboard = NULL; + MouseCursor = ImGuiMouseCursor_Arrow; + LogEnabled = false; LogFile = NULL; LogClipboard = NULL; From fc1b0b090c5c628644f352e67f858f11b0d2b047 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 1 Apr 2015 15:26:36 +0100 Subject: [PATCH 05/37] Update README.md Coverity badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4d2167bd..ffb4faed 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ImGui ===== [![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) +[![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) [![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) [![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) From e03d2b2900e9179c78c3d4fa281e7beb0d72d567 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 1 Apr 2015 15:56:58 +0100 Subject: [PATCH 06/37] ImVec2/ImVec4 no-parameters constructs init to 0.0f. Saner. Couldn't measure perf differences in a simple stress test compiled in Debug mode --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 283960a2..d237e09e 100644 --- a/imgui.h +++ b/imgui.h @@ -53,7 +53,7 @@ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); struct ImVec2 { float x, y; - ImVec2() {} + ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } #ifdef IM_VEC2_CLASS_EXTRA @@ -64,7 +64,7 @@ struct ImVec2 struct ImVec4 { float x, y, z, w; - ImVec4() {} + ImVec4() { x = y = z = w = 0.0f; } ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } #ifdef IM_VEC4_CLASS_EXTRA From b61b3117726cb8bccef83aad522ec47282b4747d Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 2 Apr 2015 10:56:59 +0100 Subject: [PATCH 07/37] Fixed Begin() returning true on collapsed windows that loaded settings #176 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5cf379c6..51ee2e66 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3408,7 +3408,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->Visible = false; // Return false if we don't intend to display anything to allow user to perform an early out optimization - window->SkipItems = (window->Collapsed || !window->Visible) && window->AutoFitFrames == 0; + window->SkipItems = (window->Collapsed || !window->Visible) && window->AutoFitFrames <= 0; return !window->SkipItems; } From 503b8c20de28373f8d6c6e5837983833fc9ae234 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 2 Apr 2015 17:48:22 +0100 Subject: [PATCH 08/37] Delete font clear pointer in ImGui state to get a clear crasah instead of a dangling pointer. #181 --- imgui.cpp | 10 ++++++++++ imgui.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 51ee2e66..6f87da2b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8264,6 +8264,16 @@ ImFont::ImFont() Clear(); } +ImFont::~ImFont() +{ + // Invalidate active font so that the user gets a clear crash instead of a dangling pointer. + // If you want to delete fonts you need to do it between Render() and NewFrame(). + ImGuiState& g = *GImGui; + if (g.Font == this) + g.Font = NULL; + Clear(); +} + void ImFont::Clear() { FontSize = 0.0f; diff --git a/imgui.h b/imgui.h index d237e09e..8035090e 100644 --- a/imgui.h +++ b/imgui.h @@ -998,7 +998,7 @@ struct ImFont // Methods IMGUI_API ImFont(); - IMGUI_API ~ImFont() { Clear(); } + IMGUI_API ~ImFont(); IMGUI_API void Clear(); IMGUI_API void BuildLookupTable(); IMGUI_API const Glyph* FindGlyph(unsigned short c) const; From 31fd72bde14eb07794553b484295ab927091af82 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 2 Apr 2015 21:21:35 +0100 Subject: [PATCH 09/37] Internal renaming --- imgui.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6f87da2b..33ae6537 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1135,7 +1135,7 @@ struct ImGuiState // Widget state ImGuiTextEditState InputTextState; - ImGuiID SliderAsInputTextId; + ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiStorage ColorEditModeStorage; // for user selection ImGuiID ActiveComboID; float ScrollbarClickDeltaToGrabCenter; // distance between mouse and center of grab box, normalized in parent space @@ -1187,7 +1187,7 @@ struct ImGuiState SetNextTreeNodeOpenedVal = false; SetNextTreeNodeOpenedCond = 0; - SliderAsInputTextId = 0; + ScalarAsInputTextId = 0; ActiveComboID = 0; ScrollbarClickDeltaToGrabCenter = 0.0f; memset(Tooltip, 0, sizeof(Tooltip)); @@ -4986,24 +4986,24 @@ static bool SliderFloatAsInputText(const char* label, float* v, ImGuiID id, int char text_buf[64]; ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v); - SetActiveId(g.SliderAsInputTextId); + SetActiveId(g.ScalarAsInputTextId); g.HoveredId = 0; // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) window->FocusItemUnregister(); bool value_changed = ImGui::InputText(label, text_buf, IM_ARRAYSIZE(text_buf), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); - if (g.SliderAsInputTextId == 0) + if (g.ScalarAsInputTextId == 0) { // First frame IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) - g.SliderAsInputTextId = g.ActiveId; + g.ScalarAsInputTextId = g.ActiveId; g.HoveredId = id; } - else if (g.ActiveId != g.SliderAsInputTextId) + else if (g.ActiveId != g.ScalarAsInputTextId) { // Release - g.SliderAsInputTextId = 0; + g.ScalarAsInputTextId = 0; } if (value_changed) { @@ -5221,10 +5221,10 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (tab_focus_requested || is_ctrl_down || !is_finite) { start_text_input = true; - g.SliderAsInputTextId = 0; + g.ScalarAsInputTextId = 0; } } - if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId)) + if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) return SliderFloatAsInputText(label, v, id, decimal_precision); ItemSize(total_bb, style.FramePadding.y); From 74f2e53b3b476aece5b61fcd026092486af80400 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 2 Apr 2015 22:38:37 +0100 Subject: [PATCH 10/37] Slider: fix in the unlikely case that style.GrabMinSize is larger than a slider. --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 33ae6537..c091b9a0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3450,7 +3450,7 @@ static void Scrollbar(ImGuiWindow* window) // The grabable box size generally represent the amount visible (vs the total scrollable amount) // But we maintain a minimum size in pixel to allow for the user to still aim inside. - const float grab_h_pixels = ImMax(style.GrabMinSize, scrollbar_height * ImSaturate(window->Size.y / ImMax(window->SizeContents.y, window->Size.y))); + const float grab_h_pixels = ImMin(ImMax(scrollbar_height * ImSaturate(window->Size.y / ImMax(window->SizeContents.y, window->Size.y)), style.GrabMinSize), scrollbar_height); const float grab_h_norm = grab_h_pixels / scrollbar_height; // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). @@ -5046,9 +5046,9 @@ static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGu const float slider_sz = horizontal ? slider_bb.GetWidth() : slider_bb.GetHeight(); float grab_sz; if (decimal_precision > 0 || !is_finite) - grab_sz = style.GrabMinSize; + grab_sz = ImMin(style.GrabMinSize, slider_sz); else - grab_sz = ImMax(1.0f * (slider_sz / (v_max-v_min+1.0f)), style.GrabMinSize); // Integer sliders, if possible have the grab size represent 1 unit + grab_sz = ImMin(ImMax(1.0f * (slider_sz / (v_max-v_min+1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit const float slider_usable_sz = slider_sz - grab_sz; const float slider_usable_pos_min = (horizontal ? slider_bb.Min.x : slider_bb.Min.y) + grab_sz*0.5f; const float slider_usable_pos_max = (horizontal ? slider_bb.Max.x : slider_bb.Max.y) - grab_sz*0.5f; @@ -5191,7 +5191,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); 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)); - // NB- we don't call ItemSize() yet becausae we may turn into a text edit box below + // NB- we don't call ItemSize() yet because we may turn into a text edit box below if (!ItemAdd(total_bb, &id)) { ItemSize(total_bb, style.FramePadding.y); From 153db919170157dd65b8e2792d1c6b4434869228 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 2 Apr 2015 22:39:37 +0100 Subject: [PATCH 11/37] Slider: don't call RenderText() on empty label. --- imgui.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c091b9a0..8a92ae2f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5230,15 +5230,16 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c ItemSize(total_bb, style.FramePadding.y); // Actual slider behavior + render grab - bool value_changed = SliderBehavior(frame_bb, inner_bb, id, v, v_min, v_max, power, decimal_precision, true); + const bool value_changed = SliderBehavior(frame_bb, inner_bb, id, v, v_min, v_max, power, decimal_precision, true); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; - char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true); RenderTextClipped(ImVec2(ImMax(frame_bb.Min.x + style.FramePadding.x, inner_bb.GetCenter().x - value_text_size.x*0.5f), frame_bb.Min.y + style.FramePadding.y), value_buf, value_buf_end, &value_text_size, frame_bb.Max); - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); return value_changed; } From e6792f84d45994556a33d6b01a0a643e17152df8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 10:22:18 +0100 Subject: [PATCH 12/37] Comments and organization of imgui.h --- imgui.cpp | 6 +++--- imgui.h | 44 ++++++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8a92ae2f..e34a1952 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5294,11 +5294,11 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float return value_changed; } -bool ImGui::SliderAngle(const char* label, float* v, float v_degrees_min, float v_degrees_max) +bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max) { - float v_deg = *v * 360.0f / (2*PI); + float v_deg = (*v_rad) * 360.0f / (2*PI); bool value_changed = ImGui::SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); - *v = v_deg * (2*PI) / 360.0f; + *v_rad = v_deg * (2*PI) / 360.0f; return value_changed; } diff --git a/imgui.h b/imgui.h index 8035090e..fbd0a092 100644 --- a/imgui.h +++ b/imgui.h @@ -284,25 +284,36 @@ namespace ImGui 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,1), 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); + IMGUI_API bool RadioButton(const char* label, int* v, int v_button); + IMGUI_API bool Combo(const char* label, int* current_item, const char** items, int items_count, int height_in_items = -1); + 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 void ColorEditMode(ImGuiColorEditMode mode); + 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), size_t 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), size_t stride = sizeof(float)); + IMGUI_API void PlotHistogram(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)); + + // Widgets: Sliders (tip: ctrl+click on a slider to input text) IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderAngle(const char* label, float* v, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); // *v in radians + IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f"); IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format = "%.0f"); IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format = "%.0f"); IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format = "%.0f"); IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); - 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), size_t 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), size_t stride = sizeof(float)); - IMGUI_API void PlotHistogram(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 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); - IMGUI_API bool RadioButton(const char* label, int* v, int v_button); + + // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1); @@ -312,15 +323,8 @@ namespace ImGui IMGUI_API bool InputInt2(const char* label, int v[2]); IMGUI_API bool InputInt3(const char* label, int v[3]); IMGUI_API bool InputInt4(const char* label, int v[4]); - IMGUI_API bool Combo(const char* label, int* current_item, const char** items, int items_count, int height_in_items = -1); - 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 void ColorEditMode(ImGuiColorEditMode mode); - // Trees + // 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* str_id, const char* fmt, ...); // " IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...); // " @@ -331,7 +335,7 @@ namespace ImGui IMGUI_API void TreePop(); IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened. - // Selectable / Lists + // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, const ImVec2& size = ImVec2(0,0)); IMGUI_API bool Selectable(const char* label, bool* p_selected, const ImVec2& size = ImVec2(0,0)); IMGUI_API bool ListBox(const char* label, int* current_item, const char** items, int items_count, int height_in_items = -1); @@ -340,7 +344,7 @@ namespace ImGui IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " IMGUI_API void ListBoxFooter(); // terminate the scrolling region - // Value() Helpers: output single value in "name: value" format. Tip: freely declare your own within the ImGui namespace! + // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare your own within the ImGui namespace!) IMGUI_API void Value(const char* prefix, bool b); IMGUI_API void Value(const char* prefix, int v); IMGUI_API void Value(const char* prefix, unsigned int v); @@ -348,7 +352,7 @@ namespace ImGui IMGUI_API void Color(const char* prefix, const ImVec4& v); IMGUI_API void Color(const char* prefix, unsigned int v); - // Logging: All text output from your interface are redirected to tty/file/clipboard. Tree nodes are automatically opened. + // Logging: all text output from interface is redirected to tty/file/clipboard. Tree nodes are automatically opened. 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 From 2d157d3af03011421db6ebe97513c10d5291c414 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 11:25:44 +0100 Subject: [PATCH 13/37] ColorEdit4(): hide components prefix if there's no space for them. --- imgui.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e34a1952..755a65b6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6857,22 +6857,24 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); + const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); + ImGui::PushItemWidth(w_item_one); - value_changed |= ImGui::SliderInt("##X", &ix, 0, 255, hsv ? "H:%3.0f" : "R:%3.0f"); + value_changed |= ImGui::SliderInt("##X", &ix, 0, 255, hide_prefix ? "%3.0f" : hsv ? "H:%3.0f" : "R:%3.0f"); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); - value_changed |= ImGui::SliderInt("##Y", &iy, 0, 255, hsv ? "S:%3.0f" : "G:%3.0f"); + value_changed |= ImGui::SliderInt("##Y", &iy, 0, 255, hide_prefix ? "%3.0f" : hsv ? "S:%3.0f" : "G:%3.0f"); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); if (alpha) { - value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hsv ? "V:%3.0f" : "B:%3.0f"); + value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hide_prefix ? "%3.0f" : hsv ? "V:%3.0f" : "B:%3.0f"); ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::SliderInt("##W", &iw, 0, 255, "A:%3.0f"); + value_changed |= ImGui::SliderInt("##W", &iw, 0, 255, hide_prefix ? "%3.0f" : "A:%3.0f"); } else { ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hsv ? "V:%3.0f" : "B:%3.0f"); + value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hide_prefix ? "%3.0f" : hsv ? "V:%3.0f" : "B:%3.0f"); } ImGui::PopItemWidth(); ImGui::PopItemWidth(); From 6aed651f77f9a4bec88b46465bb004ce035e1917 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 11:49:02 +0100 Subject: [PATCH 14/37] ColorEdit4(): tweak code to be a little less ugly (still not a beauty contest winner..) --- imgui.cpp | 88 +++++++++++++++++++++++-------------------------------- 1 file changed, 37 insertions(+), 51 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 755a65b6..1c4c65bc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6825,19 +6825,12 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) if (edit_mode == ImGuiColorEditMode_UserSelect || edit_mode == ImGuiColorEditMode_UserSelectShowButton) edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3; - float fx = col[0]; - float fy = col[1]; - float fz = col[2]; - float fw = col[3]; - const ImVec4 col_display(fx, fy, fz, 1.0f); + float f[4] = { col[0], col[1], col[2], col[3] }; if (edit_mode == ImGuiColorEditMode_HSV) - ImGui::ColorConvertRGBtoHSV(fx, fy, fz, fx, fy, fz); + ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - int ix = (int)(fx * 255.0f + 0.5f); - int iy = (int)(fy * 255.0f + 0.5f); - int iz = (int)(fz * 255.0f + 0.5f); - int iw = (int)(fw * 255.0f + 0.5f); + int i[4] = { (int)(f[0] * 255.0f + 0.5f), (int)(f[1] * 255.0f + 0.5f), (int)(f[2] * 255.0f + 0.5f), (int)(f[3] * 255.0f + 0.5f) }; int components = alpha ? 4 : 3; bool value_changed = false; @@ -6845,36 +6838,35 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) ImGui::BeginGroup(); ImGui::PushID(label); - bool hsv = (edit_mode == 1); + const bool hsv = (edit_mode == 1); switch (edit_mode) { case ImGuiColorEditMode_RGB: case ImGuiColorEditMode_HSV: { - // 0: RGB 0..255 Sliders - // 1: HSV 0..255 Sliders + // RGB/HSV 0..255 Sliders const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x); const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); + const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; + const char* fmt_table[3][4] = + { + { "%3.0f", "%3.0f", "%3.0f", "%3.0f" }, + { "R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f" }, + { "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" } + }; + const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; ImGui::PushItemWidth(w_item_one); - value_changed |= ImGui::SliderInt("##X", &ix, 0, 255, hide_prefix ? "%3.0f" : hsv ? "H:%3.0f" : "R:%3.0f"); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); - value_changed |= ImGui::SliderInt("##Y", &iy, 0, 255, hide_prefix ? "%3.0f" : hsv ? "S:%3.0f" : "G:%3.0f"); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); - if (alpha) + for (int n = 0; n < components; n++) { - value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hide_prefix ? "%3.0f" : hsv ? "V:%3.0f" : "B:%3.0f"); - ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); - ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::SliderInt("##W", &iw, 0, 255, hide_prefix ? "%3.0f" : "A:%3.0f"); - } - else - { - ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hide_prefix ? "%3.0f" : hsv ? "V:%3.0f" : "B:%3.0f"); + if (n > 0) + ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + if (n + 1 == components) + ImGui::PushItemWidth(w_item_last); + value_changed |= ImGui::SliderInt(ids[n], &i[n], 0, 255, fmt[n]); } ImGui::PopItemWidth(); ImGui::PopItemWidth(); @@ -6882,46 +6874,42 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) break; case ImGuiColorEditMode_HEX: { - // 2: RGB Hexadecimal + // RGB Hexadecimal Input const float w_slider_all = w_full - square_sz; char buf[64]; if (alpha) - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ix, iy, iz, iw); + 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", ix, iy, iz); + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); ImGui::PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); - value_changed |= ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal); + value_changed |= ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); ImGui::PopItemWidth(); char* p = buf; while (*p == '#' || ImCharIsSpace(*p)) p++; // Treat at unsigned (%X is unsigned) - ix = iy = iz = iw = 0; + i[0] = i[1] = i[2] = i[3] = 0; if (alpha) - sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&ix, (unsigned int*)&iy, (unsigned int*)&iz, (unsigned int*)&iw); + sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); else - sscanf(p, "%02X%02X%02X", (unsigned int*)&ix, (unsigned int*)&iy, (unsigned int*)&iz); + sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); } break; } ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + + const ImVec4 col_display(col[0], col[1], col[2], 1.0f); if (ImGui::ColorButton(col_display)) - { - // Don't set local copy of 'edit_mode' right away! - g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); - } + g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) { ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); const char* button_titles[3] = { "RGB", "HSV", "HEX" }; if (ImGui::Button(button_titles[edit_mode])) - { - // Don't set local copy of 'edit_mode' right away! - g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); - } + g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! ImGui::SameLine(); } else @@ -6932,20 +6920,18 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); // Convert back - fx = ix / 255.0f; - fy = iy / 255.0f; - fz = iz / 255.0f; - fw = iw / 255.0f; + for (int n = 0; n < 4; n++) + f[n] = i[n] / 255.0f; if (edit_mode == 1) - ImGui::ColorConvertHSVtoRGB(fx, fy, fz, fx, fy, fz); + ImGui::ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); if (value_changed) { - col[0] = fx; - col[1] = fy; - col[2] = fz; + col[0] = f[0]; + col[1] = f[1]; + col[2] = f[2]; if (alpha) - col[3] = fw; + col[3] = f[3]; } ImGui::PopID(); From d25578efd8d9d4115b0ea8ffadaea61317eaa84e Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 12:11:41 +0100 Subject: [PATCH 15/37] Examples: initializing float + missing comment. --- examples/directx11_example/main.cpp | 3 ++- examples/directx9_example/main.cpp | 3 ++- examples/opengl3_example/main.cpp | 2 +- examples/opengl_example/main.cpp | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 80e20fb9..5e70a482 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -149,6 +149,7 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); + //ImGuiIO& io = ImGui::GetIO(); //ImFont* my_font0 = io.Fonts->AddFontDefault(); //ImFont* my_font1 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/Karla-Regular.ttf", 16.0f); @@ -176,7 +177,7 @@ int main(int, char**) // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" { - static float f; + static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_col); diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index b564dbc3..98bc4261 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -73,6 +73,7 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); + //ImGuiIO& io = ImGui::GetIO(); //ImFont* my_font0 = io.Fonts->AddFontDefault(); //ImFont* my_font1 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("../../extra_fonts/Karla-Regular.ttf", 16.0f); @@ -103,7 +104,7 @@ int main(int, char**) // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" { - static float f; + static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_col); diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 0e718741..effadff4 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -48,7 +48,7 @@ int main(int, char**) // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" { - static float f; + static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); diff --git a/examples/opengl_example/main.cpp b/examples/opengl_example/main.cpp index 3ff10fe3..4b68a8c9 100644 --- a/examples/opengl_example/main.cpp +++ b/examples/opengl_example/main.cpp @@ -42,7 +42,7 @@ int main(int, char**) // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" { - static float f; + static float f = 0.0f; ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); From 1247ce251fbb9317ac4d97993a319743af533447 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 14:07:52 +0100 Subject: [PATCH 16/37] Added DragFloat(), DragInt() work in progress #180 --- imgui.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++---- imgui.h | 12 +++- 2 files changed, 161 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1c4c65bc..09032680 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -135,6 +135,7 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. + - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. - 2015/03/17 (1.36) - renamed GetItemRectMin()/GetItemRectMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete). - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete). @@ -559,6 +560,8 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input + Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); + 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_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f); @@ -566,8 +569,6 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); - Colors[ImGuiCol_CheckHovered] = ImVec4(0.60f, 0.40f, 0.40f, 0.45f); - Colors[ImGuiCol_CheckActive] = ImVec4(0.65f, 0.50f, 0.50f, 0.55f); Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); @@ -649,9 +650,11 @@ void ImGuiIO::AddInputCharacter(ImWchar c) const float PI = 3.14159265358979323846f; #ifdef INT_MAX -#define IM_INT_MAX INT_MAX +#define IM_INT_MIN INT_MIN +#define IM_INT_MAX INT_MAX #else -#define IM_INT_MAX 2147483647 +#define IM_INT_MIN (-2147483647-1) +#define IM_INT_MAX (2147483647) #endif // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. @@ -1138,6 +1141,9 @@ struct ImGuiState ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiStorage ColorEditModeStorage; // for user selection ImGuiID ActiveComboID; + ImVec2 DragLastMouseDelta; + float DragSpeedScaleSlow; + float DragSpeedScaleFast; float ScrollbarClickDeltaToGrabCenter; // distance between mouse and center of grab box, normalized in parent space char Tooltip[1024]; char* PrivateClipboard; // if no custom clipboard handler is defined @@ -1189,6 +1195,9 @@ struct ImGuiState ScalarAsInputTextId = 0; ActiveComboID = 0; + DragLastMouseDelta = ImVec2(0.0f, 0.0f); + DragSpeedScaleSlow = 0.01f; + DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = 0.0f; memset(Tooltip, 0, sizeof(Tooltip)); PrivateClipboard = NULL; @@ -3716,6 +3725,8 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; + case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; + case ImGuiCol_FrameBgActive: return "FrameBgActive"; case ImGuiCol_TitleBg: return "TitleBg"; case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; @@ -3723,8 +3734,6 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; case ImGuiCol_ComboBg: return "ComboBg"; - case ImGuiCol_CheckHovered: return "CheckHovered"; - case ImGuiCol_CheckActive: return "CheckActive"; case ImGuiCol_CheckMark: return "CheckMark"; case ImGuiCol_SliderGrab: return "SliderGrab"; case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; @@ -5207,11 +5216,11 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c int decimal_precision = 3; ParseFormat(display_format, decimal_precision); - const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); - // Tabbing or CTRL-clicking through slider turns into an input box + // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; + const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) { SetActiveId(id); @@ -5427,6 +5436,138 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const return SliderIntN(label, v, 4, v_min, v_max, display_format); } +// FIXME-WIP: Work in progress. May change API / behavior. +static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_step, float v_min, float v_max) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + const ImGuiStyle& style = g.Style; + + // Draw frame + const ImU32 frame_col = window->Color(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); + + bool value_changed = false; + + // Process clicking on the slider + if (g.ActiveId == id) + { + if (g.IO.MouseDown[0]) + { + const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0); + + if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) + { + float step = v_step; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + step = v_step * g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + step = v_step * g.DragSpeedScaleSlow; + + *v += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step; + *v = ImClamp(*v, v_min, v_max); + + g.DragLastMouseDelta.x = mouse_drag_delta.x; + value_changed = true; + } + } + else + { + SetActiveId(0); + } + } + + return value_changed; +} + +bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, float v_max, const char* display_format) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = ImGui::CalcItemWidth(); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); + const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); + 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)); + + // NB- we don't call ItemSize() yet because we may turn into a text edit box below + if (!ItemAdd(total_bb, &id)) + { + ItemSize(total_bb, style.FramePadding.y); + return false; + } + + const bool hovered = IsHovered(frame_bb, id); + if (hovered) + g.HoveredId = id; + + if (!display_format) + display_format = "%.3f"; + int decimal_precision = 3; + ParseFormat(display_format, decimal_precision); + + // Tabbing or CTRL-clicking on Drag turns it into an input box + bool start_text_input = false; + const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); + if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) + { + SetActiveId(id); + FocusWindow(window); + g.DragLastMouseDelta = ImVec2(0.f, 0.f); + + const bool is_ctrl_down = g.IO.KeyCtrl; + if (tab_focus_requested || is_ctrl_down) + { + start_text_input = true; + g.ScalarAsInputTextId = 0; + } + } + if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) + return SliderFloatAsInputText(label, v, id, decimal_precision); + + ItemSize(total_bb, style.FramePadding.y); + + // Actual drag behavior + const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_step, v_min, v_max); + + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. + char value_buf[64]; + const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true); + RenderTextClipped(ImVec2(ImMax(frame_bb.Min.x + style.FramePadding.x, inner_bb.GetCenter().x - value_text_size.x*0.5f), frame_bb.Min.y + style.FramePadding.y), value_buf, value_buf_end, &value_text_size, frame_bb.Max); + + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); + + return value_changed; +} + +bool ImGui::DragFloat(const char* label, float* v, float v_step, const char* display_format) +{ + return ImGui::DragFloat(label, v, v_step, -FLT_MAX, FLT_MAX, display_format); +} + +bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, const char* display_format) +{ + if (!display_format) + display_format = "%.0f"; + float v_f = (float)*v; + bool value_changed = ImGui::DragFloat(label, &v_f, (float)v_step, (float)v_min, (float)v_max, display_format); + *v = (int)v_f; + return value_changed; +} + +bool ImGui::DragInt(const char* label, int* v, int v_step, const char* display_format) +{ + return ImGui::DragInt(label, v, v_step, IM_INT_MIN, IM_INT_MAX, display_format); +} + enum ImGuiPlotType { ImGuiPlotType_Lines, @@ -5598,7 +5739,7 @@ bool ImGui::Checkbox(const char* label, bool* v) if (pressed) *v = !(*v); - RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); if (*v) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); @@ -5659,7 +5800,7 @@ bool ImGui::RadioButton(const char* label, bool active) bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held, true); - window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16); + window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); if (active) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); @@ -6866,7 +7007,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); if (n + 1 == components) ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::SliderInt(ids[n], &i[n], 0, 255, fmt[n]); + value_changed |= ImGui::DragInt(ids[n], &i[n], 1, 0, 255, fmt[n]); } ImGui::PopItemWidth(); ImGui::PopItemWidth(); diff --git a/imgui.h b/imgui.h index fbd0a092..f0220421 100644 --- a/imgui.h +++ b/imgui.h @@ -300,6 +300,12 @@ namespace ImGui 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), size_t stride = sizeof(float)); IMGUI_API void PlotHistogram(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)); + // Widgets: Drags (tip: ctrl+click on a drag box to input text) + IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = -FLT_MAX, float v_max = FLT_MAX, const char* display_format = "%.3f"); + IMGUI_API bool DragFloat(const char* label, float* v, float v_step, const char* display_format); + IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = -0x7fffffff-1, int v_max = 0x7fffffff, const char* display_format = "%.0f"); + IMGUI_API bool DragInt(const char* label, int* v, int v_step, const char* display_format = "%.0f"); + // Widgets: Sliders (tip: ctrl+click on a slider to input text) IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); @@ -484,6 +490,8 @@ enum ImGuiCol_ ImGuiCol_Border, ImGuiCol_BorderShadow, ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input + ImGuiCol_FrameBgHovered, + ImGuiCol_FrameBgActive, ImGuiCol_TitleBg, ImGuiCol_TitleBgCollapsed, ImGuiCol_ScrollbarBg, @@ -491,8 +499,6 @@ enum ImGuiCol_ ImGuiCol_ScrollbarGrabHovered, ImGuiCol_ScrollbarGrabActive, ImGuiCol_ComboBg, - ImGuiCol_CheckHovered, - ImGuiCol_CheckActive, ImGuiCol_CheckMark, ImGuiCol_SliderGrab, ImGuiCol_SliderGrabActive, @@ -553,7 +559,7 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_TextInput, ImGuiMouseCursor_Move, // Unused by ImGui ImGuiMouseCursor_ResizeNS, // Unused by ImGui - ImGuiMouseCursor_ResizeEW, // Unused by ImGui + ImGuiMouseCursor_ResizeEW, ImGuiMouseCursor_ResizeNESW, // Unused by ImGui ImGuiMouseCursor_ResizeNWSE, ImGuiMouseCursor_Count_ From f7e35ce1209fd75c85a444e8aef021cb12c52561 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 14:20:04 +0100 Subject: [PATCH 17/37] ShowTestWindow() renamed sliders examples to say "slider" --- imgui.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 09032680..fb11ef48 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9728,7 +9728,7 @@ void ImGui::ShowTestWindow(bool* opened) static char str0[128] = "Hello, world!"; static int i0=123; static float f0=0.001f; - ImGui::InputText("string", str0, IM_ARRAYSIZE(str0)); + ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); ImGui::InputInt("input int", &i0); ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); @@ -9739,19 +9739,17 @@ void ImGui::ShowTestWindow(bool* opened) static int i1=0; static int i2=42; - ImGui::SliderInt("int 0..3", &i1, 0, 3); - ImGui::SliderInt("int -100..100", &i2, -100, 100); + ImGui::SliderInt("slider int 0..3", &i1, 0, 3); + ImGui::SliderInt("slider int -100..100", &i2, -100, 100); static float f1=1.123f; static float f2=0; - static float f3=0; - static float f4=123456789.0f; - ImGui::SliderFloat("float", &f1, 0.0f, 2.0f); - ImGui::SliderFloat("log float", &f2, 0.0f, 10.0f, "%.4f", 2.0f); - ImGui::SliderFloat("signed log float", &f3, -10.0f, 10.0f, "%.4f", 3.0f); - ImGui::SliderFloat("unbound float", &f4, -FLT_MAX, FLT_MAX, "%.4f"); + static float f3=123456789.0f; + ImGui::SliderFloat("slider float", &f1, 0.0f, 2.0f); + ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f); + ImGui::SliderFloat("slider unbound", &f3, -FLT_MAX, FLT_MAX, "%.4f"); static float angle = 0.0f; - ImGui::SliderAngle("angle", &angle); + ImGui::SliderAngle("slider angle", &angle); static float col1[3] = { 1.0f,0.0f,0.2f }; static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; From dc52938627fb2cf82eb8db366aa2671f3142d963 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 14:22:00 +0100 Subject: [PATCH 18/37] InputInt2(), InputInt3(), InputInt4(): fixed label vertical alignment --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index fb11ef48..a50562a4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6577,6 +6577,7 @@ static bool InputIntN(const char* label, int* v, int components) ImGui::PopItemWidth(); ImGui::PopID(); + window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, style.FramePadding.y); ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); ImGui::EndGroup(); From f3967f1183cbf34f9a6a32d168c402e24e05b7d0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 14:32:46 +0100 Subject: [PATCH 19/37] Combo() adding frame padding inside the combo box. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a50562a4..ceace398 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1277,7 +1277,7 @@ public: float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0 : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; } ImRect TitleBarRect() const { return ImRect(Pos, Pos + ImVec2(SizeFull.x, TitleBarHeight())); } - ImVec2 WindowPadding() const { return ((Flags & ImGuiWindowFlags_ChildWindow) && !(Flags & ImGuiWindowFlags_ShowBorders)) ? ImVec2(0,0) : GImGui->Style.WindowPadding; } + ImVec2 WindowPadding() const { return ((Flags & ImGuiWindowFlags_ChildWindow) && !(Flags & ImGuiWindowFlags_ShowBorders) && !(Flags & ImGuiWindowFlags_ComboBox)) ? ImVec2(0,0) : GImGui->Style.WindowPadding; } ImU32 Color(ImGuiCol idx, float a=1.f) const { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * a; return ImGui::ColorConvertFloat4ToU32(c); } ImU32 Color(const ImVec4& col) const { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); } }; @@ -6708,11 +6708,12 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi const ImVec2 backup_pos = ImGui::GetCursorPos(); const float popup_off_x = 0.0f;//style.ItemInnerSpacing.x; - const float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + style.WindowPadding.y; + const float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); const ImRect popup_rect(ImVec2(frame_bb.Min.x+popup_off_x, frame_bb.Max.y), ImVec2(frame_bb.Max.x+popup_off_x, frame_bb.Max.y + popup_height)); ImGui::SetCursorPos(popup_rect.Min - window->Pos); const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); ImGui::BeginChild("#ComboBox", popup_rect.GetSize(), false, flags); ImGui::Spacing(); @@ -6740,6 +6741,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi ImGui::PopID(); } ImGui::EndChild(); + ImGui::PopStyleVar(); ImGui::SetCursorPos(backup_pos); if (!combo_item_active && g.ActiveId != 0) From aac99819d67079c4aa5b5ba64c6f946df704e8e7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 14:40:15 +0100 Subject: [PATCH 20/37] Selectable() render into AutoFitPadding but do not extend it, fixing small visual gap Followup 2e26196aba66dc0fa304043764aa6f6499beee0f / #1 --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ceace398..3a8dbfca 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6768,8 +6768,9 @@ bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg) const float w = ImMax(label_size.x, window->Pos.x + ImGui::GetContentRegionMax().x - style.AutoFitPadding.x - window->DC.CursorPos.x); const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : w, size_arg.y != 0.0f ? size_arg.y : label_size.y); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(bb); + bb.Max.x += style.AutoFitPadding.x; // Selectables are meant to be tightly packed together. So for both rendering and collision we extend to compensate for spacing. ImRect bb_with_spacing = bb; From 61d886e14baf0c8063a61b7467f074aca1c56ad5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 15:10:07 +0100 Subject: [PATCH 21/37] SliderFloat() removed support for unbound/infinite slider, inconsistent. Use InputFloat()/DragFloat() --- imgui.cpp | 275 +++++++++++++++++++++++++++--------------------------- 1 file changed, 136 insertions(+), 139 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3a8dbfca..a08a35c2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -136,6 +136,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. - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. + - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. - 2015/03/17 (1.36) - renamed GetItemRectMin()/GetItemRectMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete). - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete). @@ -5049,12 +5050,11 @@ static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGu // Draw frame RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding); - const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); const bool is_non_linear = fabsf(power - 1.0f) > 0.0001f; const float slider_sz = horizontal ? slider_bb.GetWidth() : slider_bb.GetHeight(); float grab_sz; - if (decimal_precision > 0 || !is_finite) + if (decimal_precision > 0) grab_sz = ImMin(style.GrabMinSize, slider_sz); else grab_sz = ImMin(ImMax(1.0f * (slider_sz / (v_max-v_min+1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit @@ -5064,117 +5064,114 @@ static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGu bool value_changed = false; - if (is_finite) + // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f + float linear_zero_pos = 0.0f; // 0.0->1.0f + if (v_min * v_max < 0.0f) { - // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f - float linear_zero_pos = 0.0f; // 0.0->1.0f - if (v_min * v_max < 0.0f) - { - // Different sign - const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power); - const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power); - linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0); - } - else - { - // Same sign - linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; - } - - // Process clicking on the slider - if (g.ActiveId == id) - { - if (g.IO.MouseDown[0]) - { - const float mouse_abs_pos = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float normalized_pos = ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f); - if (!horizontal) - normalized_pos = 1.0f - normalized_pos; - - float new_value; - if (is_non_linear) - { - // Account for logarithmic scale on both sides of the zero - if (normalized_pos < linear_zero_pos) - { - // Negative: rescale to the negative range before powering - float a = 1.0f - (normalized_pos / linear_zero_pos); - a = powf(a, power); - new_value = ImLerp(ImMin(v_max,0.f), v_min, a); - } - else - { - // Positive: rescale to the positive range before powering - float a; - if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) - a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); - else - a = normalized_pos; - a = powf(a, power); - new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); - } - } - else - { - // Linear slider - new_value = ImLerp(v_min, v_max, normalized_pos); - } - - // Round past decimal precision - // 0->1, 1->0.1, 2->0.01, etc. - // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 - const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); - const float remainder = fmodf(new_value, min_step); - if (remainder <= min_step*0.5f) - new_value -= remainder; - else - new_value += (min_step - remainder); - - if (*v != new_value) - { - *v = new_value; - value_changed = true; - } - } - else - { - SetActiveId(0); - } - } - - // Calculate slider grab positioning - float grab_t; - if (is_non_linear) - { - float v_clamped = ImClamp(*v, v_min, v_max); - if (v_clamped < 0.0f) - { - const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); - grab_t = (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; - } - else - { - const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); - grab_t = linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); - } - } - else - { - // Linear slider - grab_t = (ImClamp(*v, v_min, v_max) - v_min) / (v_max - v_min); - } - - // Draw - if (!horizontal) - grab_t = 1.0f - grab_t; - const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); - ImRect grab_bb; - if (horizontal) - grab_bb = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + 2.0f), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - 2.0f)); - else - grab_bb = ImRect(ImVec2(frame_bb.Min.x + 2.0f, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - 2.0f, grab_pos + grab_sz*0.5f)); - window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab)); + // Different sign + const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power); + const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power); + linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0); } + else + { + // Same sign + linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; + } + + // Process clicking on the slider + if (g.ActiveId == id) + { + if (g.IO.MouseDown[0]) + { + const float mouse_abs_pos = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + float normalized_pos = ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f); + if (!horizontal) + normalized_pos = 1.0f - normalized_pos; + + float new_value; + if (is_non_linear) + { + // Account for logarithmic scale on both sides of the zero + if (normalized_pos < linear_zero_pos) + { + // Negative: rescale to the negative range before powering + float a = 1.0f - (normalized_pos / linear_zero_pos); + a = powf(a, power); + new_value = ImLerp(ImMin(v_max,0.f), v_min, a); + } + else + { + // Positive: rescale to the positive range before powering + float a; + if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) + a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); + else + a = normalized_pos; + a = powf(a, power); + new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); + } + } + else + { + // Linear slider + new_value = ImLerp(v_min, v_max, normalized_pos); + } + + // Round past decimal precision + // 0->1, 1->0.1, 2->0.01, etc. + // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 + const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); + const float remainder = fmodf(new_value, min_step); + if (remainder <= min_step*0.5f) + new_value -= remainder; + else + new_value += (min_step - remainder); + + if (*v != new_value) + { + *v = new_value; + value_changed = true; + } + } + else + { + SetActiveId(0); + } + } + + // Calculate slider grab positioning + float grab_t; + if (is_non_linear) + { + float v_clamped = ImClamp(*v, v_min, v_max); + if (v_clamped < 0.0f) + { + const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); + grab_t = (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; + } + else + { + const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); + grab_t = linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); + } + } + else + { + // Linear slider + grab_t = (ImClamp(*v, v_min, v_max) - v_min) / (v_max - v_min); + } + + // Draw + if (!horizontal) + grab_t = 1.0f - grab_t; + const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); + ImRect grab_bb; + if (horizontal) + grab_bb = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + 2.0f), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - 2.0f)); + else + grab_bb = ImRect(ImVec2(frame_bb.Min.x + 2.0f, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - 2.0f, grab_pos + grab_sz*0.5f)); + window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab)); return value_changed; } @@ -5216,8 +5213,6 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c int decimal_precision = 3; ParseFormat(display_format, decimal_precision); - const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); - // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); @@ -5227,7 +5222,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c FocusWindow(window); const bool is_ctrl_down = g.IO.KeyCtrl; - if (tab_focus_requested || is_ctrl_down || !is_finite) + if (tab_focus_requested || is_ctrl_down) { start_text_input = true; g.ScalarAsInputTextId = 0; @@ -6685,7 +6680,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - + ImGui::PushID((int)id); bool menu_toggled = false; if (hovered) @@ -9729,31 +9724,32 @@ void ImGui::ShowTestWindow(bool* opened) static int item2 = -1; ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items)); - static char str0[128] = "Hello, world!"; - static int i0=123; - static float f0=0.001f; - ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); - ImGui::InputInt("input int", &i0); - ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); + { + static char str0[128] = "Hello, world!"; + static int i0=123; + static float f0=0.001f; + ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); + ImGui::InputInt("input int", &i0); + ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); - static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - //ImGui::InputFloat2("input float2", vec4a); - ImGui::InputFloat3("input float3", vec4a); - //ImGui::InputFloat4("input float4", vec4a); + static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; + ImGui::InputFloat3("input float3", vec4a); + } - static int i1=0; - static int i2=42; - ImGui::SliderInt("slider int 0..3", &i1, 0, 3); - ImGui::SliderInt("slider int -100..100", &i2, -100, 100); + { + static int i1=0; + static int i2=42; + ImGui::SliderInt("slider int 0..3", &i1, 0, 3); + ImGui::SliderInt("slider int -100..100", &i2, -100, 100); - static float f1=1.123f; - static float f2=0; - static float f3=123456789.0f; - ImGui::SliderFloat("slider float", &f1, 0.0f, 2.0f); - ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f); - ImGui::SliderFloat("slider unbound", &f3, -FLT_MAX, FLT_MAX, "%.4f"); - static float angle = 0.0f; - ImGui::SliderAngle("slider angle", &angle); + static float f1=1.123f; + static float f2=0; + static float f3=123456789.0f; + ImGui::SliderFloat("slider float", &f1, 0.0f, 2.0f); + ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f); + static float angle = 0.0f; + ImGui::SliderAngle("slider angle", &angle); + } static float col1[3] = { 1.0f,0.0f,0.2f }; static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; @@ -9812,12 +9808,13 @@ void ImGui::ShowTestWindow(bool* opened) if (i > 0) ImGui::SameLine(); ImGui::PushID(i); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(i/7.0f, 0.6f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(i/7.0f, 0.7f, 0.5f)); ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImColor::HSV(i/7.0f, 1.0f, 1.0f)); ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); if (ImGui::IsItemActive() || ImGui::IsItemHovered()) ImGui::SetTooltip("%.3f", values[i]); - ImGui::PopStyleColor(3); + ImGui::PopStyleColor(4); ImGui::PopID(); } ImGui::PopID(); From 916a8955ec46af391c8761dd6eb436311272efd9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 15:13:59 +0100 Subject: [PATCH 22/37] DragFloat(): passing min>=max (e.g. 0.0f) for range makes the drag unbound #180, removed extra APIs --- imgui.cpp | 14 +++----------- imgui.h | 6 ++---- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a08a35c2..9cbb93a5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5460,7 +5460,9 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo step = v_step * g.DragSpeedScaleSlow; *v += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step; - *v = ImClamp(*v, v_min, v_max); + + if (v_min < v_max) + *v = ImClamp(*v, v_min, v_max); g.DragLastMouseDelta.x = mouse_drag_delta.x; value_changed = true; @@ -5543,11 +5545,6 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl return value_changed; } -bool ImGui::DragFloat(const char* label, float* v, float v_step, const char* display_format) -{ - return ImGui::DragFloat(label, v, v_step, -FLT_MAX, FLT_MAX, display_format); -} - bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, const char* display_format) { if (!display_format) @@ -5558,11 +5555,6 @@ bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, return value_changed; } -bool ImGui::DragInt(const char* label, int* v, int v_step, const char* display_format) -{ - return ImGui::DragInt(label, v, v_step, IM_INT_MIN, IM_INT_MAX, display_format); -} - enum ImGuiPlotType { ImGuiPlotType_Lines, diff --git a/imgui.h b/imgui.h index f0220421..56bfc277 100644 --- a/imgui.h +++ b/imgui.h @@ -301,10 +301,8 @@ namespace ImGui IMGUI_API void PlotHistogram(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)); // Widgets: Drags (tip: ctrl+click on a drag box to input text) - IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = -FLT_MAX, float v_max = FLT_MAX, const char* display_format = "%.3f"); - IMGUI_API bool DragFloat(const char* label, float* v, float v_step, const char* display_format); - IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = -0x7fffffff-1, int v_max = 0x7fffffff, const char* display_format = "%.0f"); - IMGUI_API bool DragInt(const char* label, int* v, int v_step, const char* display_format = "%.0f"); + IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = 0.0f, int v_max = 0.0f, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound // Widgets: Sliders (tip: ctrl+click on a slider to input text) IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders From 962aa4c3965da535b8bd39e1fe5c42d081bd0b56 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 15:15:12 +0100 Subject: [PATCH 23/37] DragFloat() double-clicking turns into an input box (along with Ctrl+clicking) #180 --- imgui.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9cbb93a5..162a6c53 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5512,14 +5512,13 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); - if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) + if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] | g.IO.MouseDoubleClicked[0]))) { SetActiveId(id); FocusWindow(window); g.DragLastMouseDelta = ImVec2(0.f, 0.f); - const bool is_ctrl_down = g.IO.KeyCtrl; - if (tab_focus_requested || is_ctrl_down) + if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0]) { start_text_input = true; g.ScalarAsInputTextId = 0; From c93f34238ec468b0c6bdc49f984fefd00741dd95 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 15:18:12 +0100 Subject: [PATCH 24/37] DragFloat() examples #180 --- imgui.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 162a6c53..fe5dd928 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9727,6 +9727,18 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::InputFloat3("input float3", vec4a); } + { + static int i1=50; + static int i2=42; + ImGui::DragInt("drag int", &i1, 1); + ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100); + + static float f1=1.00f; + static float f2=0.0067f; + ImGui::DragFloat("drag float", &f1, 1.0f); + ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f"); + } + { static int i1=0; static int i2=42; From 28a45877aa9d5eb2bbd3c7e820f3b38252d20804 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Apr 2015 16:21:24 +0100 Subject: [PATCH 25/37] DragFloat() comment examples, not ready for prime-time #180 --- imgui.cpp | 2 ++ imgui.h | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fe5dd928..fd07b676 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9727,6 +9727,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::InputFloat3("input float3", vec4a); } + /* { static int i1=50; static int i2=42; @@ -9738,6 +9739,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::DragFloat("drag float", &f1, 1.0f); ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f"); } + */ { static int i1=0; diff --git a/imgui.h b/imgui.h index 56bfc277..bb40839a 100644 --- a/imgui.h +++ b/imgui.h @@ -300,10 +300,6 @@ namespace ImGui 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), size_t stride = sizeof(float)); IMGUI_API void PlotHistogram(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)); - // Widgets: Drags (tip: ctrl+click on a drag box to input text) - IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound - IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = 0.0f, int v_max = 0.0f, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound - // Widgets: Sliders (tip: ctrl+click on a slider to input text) IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); @@ -317,6 +313,11 @@ namespace ImGui IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); + // Widgets: Drags (tip: ctrl+click on a drag box to input text) + // ImGui 1.38+ work-in-progress, may change name or API. + IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = 0.0f, int v_max = 0.0f, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound + // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); From f5310a2f2d29305e4a33af33b333820aa71e7382 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 4 Apr 2015 19:03:39 +0100 Subject: [PATCH 26/37] Comments --- imconfig.h | 2 +- imgui.h | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/imconfig.h b/imconfig.h index a07a1331..625a8943 100644 --- a/imconfig.h +++ b/imconfig.h @@ -31,7 +31,7 @@ //---- Include imgui_user.h at the end of imgui.h //#define IMGUI_INCLUDE_IMGUI_USER_H -//---- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. +//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. /* #define IM_VEC2_CLASS_EXTRA \ ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ diff --git a/imgui.h b/imgui.h index bb40839a..fcda9b59 100644 --- a/imgui.h +++ b/imgui.h @@ -56,7 +56,7 @@ struct ImVec2 ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } -#ifdef IM_VEC2_CLASS_EXTRA +#ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif }; @@ -67,7 +67,7 @@ struct ImVec4 ImVec4() { x = y = z = w = 0.0f; } ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } -#ifdef IM_VEC4_CLASS_EXTRA +#ifdef IM_VEC4_CLASS_EXTRA // Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec4. IM_VEC4_CLASS_EXTRA #endif }; @@ -147,7 +147,7 @@ public: // - struct ImFont // TTF font loader, bake glyphs into bitmap // ImGui end-user API -// In a namespace so that user can add extra functions (e.g. Value() helpers for your vector or common types) +// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) namespace ImGui { // Main @@ -555,12 +555,12 @@ enum ImGuiColorEditMode_ enum ImGuiMouseCursor_ { ImGuiMouseCursor_Arrow = 0, - ImGuiMouseCursor_TextInput, - ImGuiMouseCursor_Move, // Unused by ImGui - ImGuiMouseCursor_ResizeNS, // Unused by ImGui - ImGuiMouseCursor_ResizeEW, - ImGuiMouseCursor_ResizeNESW, // Unused by ImGui - ImGuiMouseCursor_ResizeNWSE, + ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. + ImGuiMouseCursor_Move, // Unused + ImGuiMouseCursor_ResizeNS, // Unused + ImGuiMouseCursor_ResizeEW, // When hovering over a column + ImGuiMouseCursor_ResizeNESW, // Unused + ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Count_ }; @@ -882,6 +882,7 @@ IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; // At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged in the future. // If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives. // You can interleave normal ImGui:: calls and adding primitives to the current draw list. +// All positions are in screen coordinates (0,0=top-left, 1 pixel per unit). Primitives are always added to the list and not culled (culling is done at render time and at a higher-level by ImGui:: functions). // Note that this only gives you access to rendering polygons. If your intent is to create custom widgets and the publicly exposed functions/data aren't sufficient, you can add code in imgui_user.inl struct ImDrawList { From 73e2d56accf5fc7dbad1e12116c35007bb8f46a8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Apr 2015 10:45:10 +0100 Subject: [PATCH 27/37] Examples: OpenGL fixed-pipeline: added glBindTexture(0), via Anton M --- examples/opengl_example/imgui_impl_glfw.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 8c9cb216..0243d513 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -87,6 +87,7 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); + glBindTexture(GL_TEXTURE_2D, 0); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); From fe64da6197020eac89773d77ae87e2415609e92c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Apr 2015 11:19:31 +0100 Subject: [PATCH 28/37] Allow SetWindowFocus(NULL) to remove focus --- imgui.cpp | 17 ++++++++++++++--- imgui.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fd07b676..8062ddb6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3519,6 +3519,10 @@ static void FocusWindow(ImGuiWindow* window) // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing. g.FocusedWindow = window; + // Passing NULL allow to disable keyboard focus + if (!window) + return; + // And move its root window to the top of the pile if (window->RootWindow) window = window->RootWindow; @@ -3903,9 +3907,16 @@ void ImGui::SetWindowFocus() void ImGui::SetWindowFocus(const char* name) { - ImGuiWindow* window = FindWindowByName(name); - if (window) - FocusWindow(window); + if (name) + { + ImGuiWindow* window = FindWindowByName(name); + if (window) + FocusWindow(window); + } + else + { + FocusWindow(NULL); + } } void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond) diff --git a/imgui.h b/imgui.h index fcda9b59..02965f73 100644 --- a/imgui.h +++ b/imgui.h @@ -191,7 +191,7 @@ namespace ImGui IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond = 0); // set named window position - call within Begin()/End(). may incur tearing IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond = 0); // set named window size. set to ImVec2(0,0) to force an auto-fit. may incur tearing IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0); // set named window collapsed state - IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most + IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. IMGUI_API float GetScrollPosY(); // get scrolling position [0..GetScrollMaxY()] IMGUI_API float GetScrollMaxY(); // get maximum scrolling position == ContentSize.Y - WindowSize.Y From c38c54af524280b4c7b1ddbbc8f2a6492d2c123e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Apr 2015 11:25:07 +0100 Subject: [PATCH 29/37] Clicking on void loses keyboard-focus so application can use TAB back --- imgui.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8062ddb6..c6c0334b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2153,12 +2153,20 @@ void ImGui::Render() g.CurrentWindow->Visible = false; ImGui::End(); - // Select window for move/focus when we're done with all our widgets (we use the root window ID here) - if (g.ActiveId == 0 && g.HoveredId == 0 && g.HoveredRootWindow != NULL && g.IO.MouseClicked[0]) + if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) { - IM_ASSERT(g.MovedWindow == NULL); - g.MovedWindow = g.HoveredWindow; - SetActiveId(g.HoveredRootWindow->MoveID); + if (g.HoveredRootWindow != NULL) + { + // Select window for move/focus when we're done with all our widgets (we use the root window ID here) + IM_ASSERT(g.MovedWindow == NULL); + g.MovedWindow = g.HoveredWindow; + SetActiveId(g.HoveredRootWindow->MoveID); + } + else if (g.FocusedWindow != NULL) + { + // Clicking on void disable focus + FocusWindow(NULL); + } } // Sort the window list so that all child windows are after their parent From 46769406dc923895825e844867c28ef1798142fa Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Apr 2015 10:59:49 +0100 Subject: [PATCH 30/37] Update README.txt --- examples/README.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/README.txt b/examples/README.txt index e6ce70c9..c675a1d7 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,3 +1,9 @@ +Those are standalone ready-to-build applications to demonstrate ImGui. +Unfortunately in 2015 it is still a massive pain to create and maintain portable build files. +I choose to provide Visual Studio 10 .sln files and Makefile for Linux/OSX. +Please let me know if they don't work with your setup! +You can probably just import the .cpp files into your own system and figure out the linkage from there. + opengl_example/ OpenGL example, using GLFW + fixed pipeline. From a8a5ba9d1ed7a17027ce050f27bbaa2a010ebd54 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Apr 2015 11:15:18 +0100 Subject: [PATCH 31/37] Update README.txt --- extra_fonts/README.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra_fonts/README.txt b/extra_fonts/README.txt index 90153a32..c3a9e7a3 100644 --- a/extra_fonts/README.txt +++ b/extra_fonts/README.txt @@ -1,8 +1,9 @@ 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. --------------------------------- - EXTRA FONTS FOR IMGUI + INCLUDED FONTS --------------------------------- DroidSans.ttf From 6e4d3dac1ae14fb4403a810e1c4d47e95b3d770f Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Apr 2015 11:54:53 +0100 Subject: [PATCH 32/37] Examples: Fixed ShowExampleAppManipulatingWindowTitle() not doing the right thing, broken in ff35d24bcc110b8a698b18d35bbc282811d4006c --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c6c0334b..f709a25a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10424,7 +10424,7 @@ static void ShowExampleAppManipulatingWindowTitle(bool* opened) // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" char buf[128]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "Animated title %c %d##AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand()); + ImFormatString(buf, IM_ARRAYSIZE(buf), "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand()); ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiSetCond_FirstUseEver); ImGui::Begin(buf); ImGui::Text("This window has a changing title."); From e09e2cbd28833badd1264a4125eccc11ecba411b Mon Sep 17 00:00:00 2001 From: heroboy Date: Tue, 7 Apr 2015 19:36:58 +0800 Subject: [PATCH 33/37] set pixel shader and vertex shader to NULL Previous graphic render may use shaders,so set pixel shader and vertex shader to NULL to force use fixed pipeline. --- examples/directx9_example/imgui_impl_dx9.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index b726e50e..635e2c6c 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -57,7 +57,8 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_ } } g_pVB->Unlock(); - + g_pd3dDevice->SetPixelShader(NULL); + g_pd3dDevice->SetVertexShader(NULL); g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); From d9ff617ff810c680ce56fcf6e6a0dc7a01f90a81 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Apr 2015 12:56:52 +0100 Subject: [PATCH 34/37] Examples: Formatting #187 --- examples/directx9_example/imgui_impl_dx9.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 635e2c6c..c55ffebb 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -57,12 +57,12 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_ } } g_pVB->Unlock(); - g_pd3dDevice->SetPixelShader(NULL); - g_pd3dDevice->SetVertexShader(NULL); g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); - // Setup render state: alpha-blending, no face culling, no depth testing + // 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 ); From 33ef3992f7972e7fc4476e15db6d04e7e168a1f8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Apr 2015 13:36:11 +0100 Subject: [PATCH 35/37] Added IO.MetricsVertices counter --- imgui.cpp | 2 ++ imgui.h | 1 + 2 files changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index f709a25a..5a904c43 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1670,6 +1670,7 @@ static inline void AddDrawListToRenderList(ImVector& out_render_lis if (draw_list->commands.back().vtx_count == 0) draw_list->commands.pop_back(); out_render_list.push_back(draw_list); + GImGui->IO.MetricsVertices += (int)draw_list->vtx_buffer.size(); } } @@ -2203,6 +2204,7 @@ void ImGui::Render() } // Gather windows to render + g.IO.MetricsVertices = 0; for (size_t i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].resize(0); for (size_t i = 0; i != g.Windows.size(); i++) diff --git a/imgui.h b/imgui.h index 02965f73..0d58ee5e 100644 --- a/imgui.h +++ b/imgui.h @@ -669,6 +669,7 @@ struct ImGuiIO bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input) bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input) float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames + int MetricsVertices; // Vertices processed during last call to Render() //------------------------------------------------------------------ // [Internal] ImGui will maintain those fields for you From 8211081c5485b78a864205ae12f73cea5a33531a Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Apr 2015 13:37:30 +0100 Subject: [PATCH 36/37] Added (not exposed) DisableHideTextAfterDoubleHash to disable ## processing. --- imgui.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5a904c43..1dfcf435 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1115,6 +1115,7 @@ struct ImGuiState ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Only valid if ActiveID is the "#MOVE" identifier of a window. float SettingsDirtyTimer; ImVector Settings; + int DisableHideTextAfterDoubleHash; ImVector ColorModifiers; ImVector StyleModifiers; ImVector FontStack; @@ -1183,6 +1184,7 @@ struct ImGuiState ActiveIdIsFocusedOnly = false; MovedWindow = NULL; SettingsDirtyTimer = 0.0f; + DisableHideTextAfterDoubleHash = 0; SetNextWindowPosVal = ImVec2(0.0f, 0.0f); SetNextWindowPosCond = 0; @@ -2266,8 +2268,18 @@ static const char* FindTextDisplayEnd(const char* text, const char* text_end = const char* text_display_end = text; if (!text_end) text_end = (const char*)-1; - while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) - text_display_end++; + + ImGuiState& g = *GImGui; + if (g.DisableHideTextAfterDoubleHash > 0) + { + while (text_display_end < text_end && *text_display_end != '\0') + text_display_end++; + } + else + { + while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) + text_display_end++; + } return text_display_end; } From d6922868625f2ea8d0d9621c1b1461fffb7f4905 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Apr 2015 13:42:35 +0100 Subject: [PATCH 37/37] Added ShowMetricsWindow() --- imgui.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ imgui.h | 7 +++--- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1dfcf435..9361deb0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9231,6 +9231,7 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) void ImGui::ShowUserGuide() {} void ImGui::ShowStyleEditor(ImGuiStyle*) {} void ImGui::ShowTestWindow(bool*) {} +void ImGui::ShowMetricsWindow(bool*) {} #else @@ -9371,12 +9372,15 @@ static void ShowExampleAppCustomRendering(bool* opened); void ImGui::ShowTestWindow(bool* opened) { // Examples apps + static bool show_app_metrics = false; static bool show_app_console = false; static bool show_app_long_text = false; static bool show_app_auto_resize = false; static bool show_app_fixed_overlay = false; static bool show_app_custom_rendering = false; static bool show_app_manipulating_window_title = false; + if (show_app_metrics) + ImGui::ShowMetricsWindow(&show_app_metrics); if (show_app_console) ShowExampleAppConsole(&show_app_console); if (show_app_long_text) @@ -10374,6 +10378,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::CollapsingHeader("App Examples")) { + ImGui::Checkbox("Metrics", &show_app_metrics); ImGui::Checkbox("Console", &show_app_console); ImGui::Checkbox("Long text display", &show_app_long_text); ImGui::Checkbox("Auto-resizing window", &show_app_auto_resize); @@ -10385,6 +10390,69 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::End(); } +void ImGui::ShowMetricsWindow(bool* opened) +{ + if (ImGui::Begin("ImGui Metrics", opened)) + { + ImGui::Text("ImGui %s", ImGui::GetVersion()); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::Text("%d vertices", ImGui::GetIO().MetricsVertices); + ImGui::Separator(); + + struct Funcs + { + static void NodeDrawList(ImDrawList* draw_list, const char* label) + { + bool opened = ImGui::TreeNode(draw_list, "%s: %d vtx, %d cmds", label, draw_list->vtx_buffer.size(), draw_list->commands.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 (!opened) + return; + for (const ImDrawCmd* pcmd = draw_list->commands.begin(); pcmd < draw_list->commands.end(); pcmd++) + if (pcmd->user_callback) + ImGui::BulletText("Callback %p, user_data %p", pcmd->user_callback, pcmd->user_callback_data); + else + ImGui::BulletText("Draw %d vtx, tex = %p", pcmd->vtx_count, pcmd->texture_id); + ImGui::TreePop(); + } + + static void NodeWindows(ImVector& windows, const char* label) + { + if (!ImGui::TreeNode(label, "%s (%d)", label, (int)windows.size())) + return; + for (int i = 0; i < (int)windows.size(); i++) + Funcs::NodeWindow(windows[i], "Window"); + ImGui::TreePop(); + } + + static void NodeWindow(ImGuiWindow* window, const char* label) + { + if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Visible, window)) + return; + NodeDrawList(window->DrawList, "DrawList"); + if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); + if (window->DC.ChildWindows.size() > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); + ImGui::TreePop(); + } + }; + + ImGuiState& g = *GImGui; // Access private state + g.DisableHideTextAfterDoubleHash++; // Not exposed (yet). Disable processing that hides text after '##' markers. + Funcs::NodeWindows(g.Windows, "Windows"); + if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", (int)g.RenderDrawLists[0].size())) + { + for (int i = 0; i < (int)g.RenderDrawLists[0].size(); i++) + Funcs::NodeDrawList(g.RenderDrawLists[0][i], "DrawList"); + ImGui::TreePop(); + } + g.DisableHideTextAfterDoubleHash--; + } + ImGui::End(); +} + static void ShowExampleAppAutoResize(bool* opened) { if (!ImGui::Begin("Example: Auto-Resizing Window", opened, ImGuiWindowFlags_AlwaysAutoResize)) diff --git a/imgui.h b/imgui.h index 0d58ee5e..e96e75d1 100644 --- a/imgui.h +++ b/imgui.h @@ -156,9 +156,10 @@ namespace ImGui IMGUI_API void NewFrame(); IMGUI_API void Render(); IMGUI_API void Shutdown(); - IMGUI_API void ShowUserGuide(); - IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); - IMGUI_API void ShowTestWindow(bool* open = NULL); + 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, demonstrate ImGui features + IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window // Window // See implementation in .cpp for details