From b82e99c0327456fdb14b7db1314314a8084696c9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 17 Jun 2019 11:06:36 +0200 Subject: [PATCH 001/200] ImDrawList: Fixed CloneOutput() helper crashing. Also removed unnecessary risk from ImDrawList::Clear(), draw lists are being clear before use each frame anyway. (#1860) --- docs/CHANGELOG.txt | 3 ++- imgui_draw.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cac9990d01b72..6ee2083ae4140 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,7 +42,8 @@ Breaking Changes: the new names and equivalent. Other Changes: -- ImDrawList::ChannelsSplit(), ImDrawListSlitter: Fixed an issue with merging draw commands between channel 0 and 1. (#2624) +- ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] +- ImDrawListSlitter, ImDrawList::ChannelsSplit(), : Fixed an issue with merging draw commands between channel 0 and 1. (#2624) ----------------------------------------------------------------------- diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 53fd4171b2b30..478819cc60109 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -365,7 +365,7 @@ void ImDrawList::Clear() CmdBuffer.resize(0); IdxBuffer.resize(0); VtxBuffer.resize(0); - Flags = _Data->InitialFlags; + Flags = _Data ? _Data->InitialFlags : ImDrawListFlags_None; _VtxCurrentOffset = 0; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; @@ -392,7 +392,7 @@ void ImDrawList::ClearFreeMemory() ImDrawList* ImDrawList::CloneOutput() const { - ImDrawList* dst = IM_NEW(ImDrawList(NULL)); + ImDrawList* dst = IM_NEW(ImDrawList(_Data)); dst->CmdBuffer = CmdBuffer; dst->IdxBuffer = IdxBuffer; dst->VtxBuffer = VtxBuffer; From e9b92d1cef0cea3e3d5520e03333efd8325e32c3 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 17 Jun 2019 11:32:00 +0200 Subject: [PATCH 002/200] Disable -Wpragmas warning in GCC to avoid relying on version checks, as unusual/forks/mods don't appear to always have same warning<>version. (#2618) + Fix version number in imgui.h --- imgui.cpp | 6 +++--- imgui.h | 9 +++++---- imgui_demo.cpp | 5 ++--- imgui_draw.cpp | 5 ++--- imgui_internal.h | 5 ++--- imgui_widgets.cpp | 5 ++--- misc/freetype/imgui_freetype.cpp | 1 + 7 files changed, 17 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a56500a3c3561..8eb3767011a51 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1020,6 +1020,8 @@ CODE #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #endif #elif defined(__GNUC__) +// We disable -Wpragmas because GCC doesn't provide an has_warning equivalent and some forks/patches may not following the warning/version association. +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' @@ -1027,9 +1029,7 @@ CODE #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif +#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. diff --git a/imgui.h b/imgui.h index 769d2786143f0..8131ac369a3e4 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.71 WIP +// dear imgui, v1.72 WIP // (headers) // See imgui.cpp file for documentation. @@ -83,9 +83,10 @@ Index of this file: #if __has_warning("-Wzero-as-null-pointer-constant") #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #endif -#elif defined(__GNUC__) && __GNUC__ >= 8 +#elif defined(__GNUC__) #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind +#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //----------------------------------------------------------------------------- @@ -2201,7 +2202,7 @@ struct ImFont #if defined(__clang__) #pragma clang diagnostic pop -#elif defined(__GNUC__) && __GNUC__ >= 8 +#elif defined(__GNUC__) #pragma GCC diagnostic pop #endif diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 30dd5acb4c98e..e4b89499f8a51 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -89,13 +89,12 @@ Index of this file: #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // #endif #elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#if (__GNUC__ >= 6) -#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub. -#endif +#pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub. #endif // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 478819cc60109..288d95aed007e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -72,13 +72,12 @@ Index of this file: #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #endif #elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wstack-protector" // warning: stack protector not protecting local variables: variable length buffer -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif +#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 60787bcb66882..81f9bf9ad9fa8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -56,9 +56,8 @@ Index of this file: #endif #elif defined(__GNUC__) #pragma GCC diagnostic push -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind +#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //----------------------------------------------------------------------------- diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 03882993a4ff1..3490586bc5afc 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -63,10 +63,9 @@ Index of this file: #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #endif #elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif +#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //------------------------------------------------------------------------- diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index a184d78b6b446..d0d2580d32138 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -36,6 +36,7 @@ #endif #if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #endif From ae2c9f71014727b8f80f74adfc18e701fe173403 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 10 Jun 2019 21:43:05 +0200 Subject: [PATCH 003/200] Internals: Columns: Poke into WorkRect and use them in the GetContentRegionMax() functions. This should be a no-op, but preparing us to transition toward using WorkRect instead of ContentRegionRect. Removed one use of ContentsRegionRect. --- imgui.cpp | 35 ++++++++++++++++++++++++----------- imgui_internal.h | 3 ++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8eb3767011a51..11bd76ea327f1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2249,8 +2249,8 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) ImGuiWindow* window = ImGui::GetCurrentWindow(); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (window->DC.CurrentColumns) - window->DC.CurrentColumns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + if (ImGuiColumns* columns = window->DC.CurrentColumns) + columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -3423,7 +3423,7 @@ void ImGui::UpdateMouseWheel() const bool scroll_allowed = !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs); if (scroll_allowed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f) && !g.IO.KeyCtrl) { - ImVec2 max_step = (window->ContentsRegionRect.GetSize() + window->WindowPadding * 2.0f) * 0.67f; + ImVec2 max_step = window->InnerRect.GetSize() * 0.67f; // Vertical Mouse Wheel Scrolling (hold Shift to scroll horizontally) if (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) @@ -5872,7 +5872,7 @@ void ImGui::End() ImGuiWindow* window = g.CurrentWindow; - if (window->DC.CurrentColumns != NULL) + if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle @@ -6649,7 +6649,7 @@ ImVec2 ImGui::GetContentRegionMax() ImGuiWindow* window = GImGui->CurrentWindow; ImVec2 mx = window->ContentsRegionRect.Max - window->Pos; if (window->DC.CurrentColumns) - mx.x = GetColumnOffset(window->DC.CurrentColumns->Current + 1) - window->WindowPadding.x; + mx.x = window->WorkRect.Max.x - window->Pos.x; return mx; } @@ -6659,7 +6659,7 @@ ImVec2 ImGui::GetContentRegionMaxAbs() ImGuiWindow* window = GImGui->CurrentWindow; ImVec2 mx = window->ContentsRegionRect.Max; if (window->DC.CurrentColumns) - mx.x = window->Pos.x + GetColumnOffset(window->DC.CurrentColumns->Current + 1) - window->WindowPadding.x; + mx.x = window->WorkRect.Max.x; return mx; } @@ -6672,19 +6672,19 @@ ImVec2 ImGui::GetContentRegionAvail() // In window space (not screen space!) ImVec2 ImGui::GetWindowContentRegionMin() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentsRegionRect.Min - window->Pos; } ImVec2 ImGui::GetWindowContentRegionMax() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentsRegionRect.Max - window->Pos; } float ImGui::GetWindowContentRegionWidth() { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentsRegionRect.GetWidth(); } @@ -8655,7 +8655,13 @@ void ImGui::NextColumn() window->DC.CurrLineTextBaseOffset = 0.0f; PushColumnClipRect(columns->Current); // FIXME-COLUMNS: Could it be an overwrite? - PushItemWidth(GetColumnWidth() * 0.65f); // FIXME-COLUMNS: Move on columns setup + + // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup. + float offset_0 = GetColumnOffset(columns->Current); + float offset_1 = GetColumnOffset(columns->Current + 1); + float width = offset_1 - offset_0; + PushItemWidth(width * 0.65f); + window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; } int ImGui::GetColumnIndex() @@ -8851,6 +8857,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostClipRect = window->ClipRect; + columns->HostWorkRect = window->WorkRect; columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffset.x = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); @@ -8888,7 +8895,12 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DrawList->ChannelsSetCurrent(1); PushColumnClipRect(0); } - PushItemWidth(GetColumnWidth() * 0.65f); + + float offset_0 = GetColumnOffset(columns->Current); + float offset_1 = GetColumnOffset(columns->Current + 1); + float width = offset_1 - offset_0; + PushItemWidth(width * 0.65f); + window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; } void ImGui::EndColumns() @@ -8960,6 +8972,7 @@ void ImGui::EndColumns() } columns->IsBeingResized = is_being_resized; + window->WorkRect = columns->HostWorkRect; window->DC.CurrentColumns = NULL; window->DC.ColumnsOffset.x = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); diff --git a/imgui_internal.h b/imgui_internal.h index 81f9bf9ad9fa8..599f360f3a93d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -703,6 +703,7 @@ struct ImGuiColumns float HostCursorPosY; // Backup of CursorPos at the time of BeginColumns() float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns() ImRect HostClipRect; // Backup of ClipRect at the time of BeginColumns() + ImRect HostWorkRect; // Backup of WorkRect at the time of BeginColumns() ImVector Columns; ImGuiColumns() { Clear(); } @@ -1298,7 +1299,7 @@ struct IMGUI_API ImGuiWindow // The best way to understand what those rectangles are is to use the 'Metrics -> Tools -> Show windows rectangles' viewer. // The main 'OuterRect', omitted as a field, is window->Rect(). ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window. - ImRect InnerRect; // Inner rectangle (omit title bar, menu bar) + ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar) ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect. ImRect WorkRect; // Cover the whole scrolling region, shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentsRegionRect over time (from 1.71+ onward). ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back(). From 0e37eaff8ae78ca1508e3a7da7217aac30cb349e Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Mon, 17 Jun 2019 15:17:24 +0200 Subject: [PATCH 004/200] Updated Ogre bindings (#2619) And support python --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5987c79aa066a..241eaadd457d3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -127,7 +127,7 @@ Languages: (third-party bindings) - Odin: [odin-dear_imgui](https://github.com/ThisDrunkDane/odin-dear_imgui) - Pascal: [imgui-pas](https://github.com/dpethes/imgui-pas) - PureBasic: [pb-cimgui](https://github.com/hippyau/pb-cimgui) -- Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy) +- Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy) or [ogre-imgui](https://github.com/OGRECave/ogre-imgui) - Ruby: [ruby-imgui](https://github.com/vaiorabbit/ruby-imgui) - Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) or [imgui-rust](https://github.com/nsf/imgui-rust) - Swift [swift-imgui](https://github.com/mnmly/Swift-imgui) @@ -142,7 +142,7 @@ Frameworks: - Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI) - GML/GameMakerStudio2: [ImGuiGML](https://marketplace.yoyogames.com/assets/6221/imguigml) - Irrlicht: [IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI) -- Ogre: [ogreimgui](https://bitbucket.org/LMCrashy/ogreimgui/src) +- Ogre: [ogre-imgui](https://github.com/OGRECave/ogre-imgui) - OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui) - OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c) - ORX: [ImGuiOrx](https://github.com/thegwydd/ImGuiOrx), [#1843](https://github.com/ocornut/imgui/pull/1843) From 342751c89e461530c4a0d3136c87cb80e10bd38e Mon Sep 17 00:00:00 2001 From: Vincent Hamm Date: Tue, 18 Jun 2019 01:55:33 -0700 Subject: [PATCH 005/200] Fiedx OpenGL ES 3.0 include for iOS and tvOS (#2631) --- examples/imgui_impl_opengl3.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 2bf4ea85b1f7f..9585215c41f0c 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -77,7 +77,7 @@ // Auto-detect GL version #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) -#if (defined(__APPLE__) && TARGET_OS_IOS) || (defined(__ANDROID__)) +#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" #elif defined(__EMSCRIPTEN__) #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" @@ -87,7 +87,11 @@ #if defined(IMGUI_IMPL_OPENGL_ES2) #include #elif defined(IMGUI_IMPL_OPENGL_ES3) +#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) +#include // Use GL ES 3 +#else #include // Use GL ES 3 +#endif #else // About Desktop OpenGL function loaders: // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. From 70fe409338b00940d8c811494a0e993875fbc4f8 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 17 Jun 2019 17:03:54 +0200 Subject: [PATCH 006/200] Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). --- docs/CHANGELOG.txt | 1 + imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6ee2083ae4140..d19dc5301941f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,7 @@ Breaking Changes: the new names and equivalent. Other Changes: +- Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawListSlitter, ImDrawList::ChannelsSplit(), : Fixed an issue with merging draw commands between channel 0 and 1. (#2624) diff --git a/imgui.cpp b/imgui.cpp index 11bd76ea327f1..532895333c6ee 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5618,7 +5618,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize); window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize)); window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size); - window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImFloor(window->WindowPadding.y * 0.5f), window->WindowBorderSize)); + window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize)); window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize); window->InnerClipRect.ClipWithFull(host_rect); From cc4d76cc239fbb3f2da8b1e00200a72470ef1ded Mon Sep 17 00:00:00 2001 From: Vincent Hamm Date: Sun, 16 Jun 2019 16:11:32 -0700 Subject: [PATCH 007/200] Implement SDL/dx11 sample --- .../example_sdl_directx11.vcxproj | 171 ++++++++++++++ .../example_sdl_directx11.vcxproj.filters | 57 +++++ examples/example_sdl_directx11/main.cpp | 220 ++++++++++++++++++ examples/imgui_impl_sdl.cpp | 8 + examples/imgui_impl_sdl.h | 1 + 5 files changed, 457 insertions(+) create mode 100644 examples/example_sdl_directx11/example_sdl_directx11.vcxproj create mode 100644 examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters create mode 100644 examples/example_sdl_directx11/main.cpp diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj new file mode 100644 index 0000000000000..ce1c5749e79f1 --- /dev/null +++ b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {9E1987E3-1F19-45CA-B9C9-D31E791836D8} + example_win32_directx11 + 8.1 + example_sdl_directx11 + + + + Application + true + Unicode + v140 + + + Application + true + Unicode + v140 + + + Application + false + true + Unicode + v140 + + + Application + false + true + Unicode + v140 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + + Level4 + Disabled + ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + + + true + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + $(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x86 + Console + + + + + Level4 + Disabled + ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + + + true + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x64 + Console + + + + + Level4 + MaxSpeed + true + true + ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + false + + + true + true + true + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + $(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x86 + Console + + + + + Level4 + MaxSpeed + true + true + ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + false + + + true + true + true + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x64 + Console + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters new file mode 100644 index 0000000000000..b2345067d6b8f --- /dev/null +++ b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {0587d7a3-f2ce-4d56-b84f-a0005d3bfce6} + + + {08e36723-ce4f-4cff-9662-c40801cf1acf} + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + sources + + + imgui + + + imgui + + + sources + + + imgui + + + sources + + + + + + sources + + + \ No newline at end of file diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl_directx11/main.cpp new file mode 100644 index 0000000000000..bf470d78f40a6 --- /dev/null +++ b/examples/example_sdl_directx11/main.cpp @@ -0,0 +1,220 @@ +// dear imgui: standalone example application for SDL2 + OpenGL +// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) + +#include "imgui.h" +#include "imgui_impl_sdl.h" +#include "imgui_impl_dx11.h" +#include +#include +#include +#include + +// Data +static ID3D11Device* g_pd3dDevice = NULL; +static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; +static IDXGISwapChain* g_pSwapChain = NULL; +static ID3D11RenderTargetView* g_mainRenderTargetView = NULL; + +// Forward declarations of helper functions +bool CreateDeviceD3D(HWND hWnd); +void CleanupDeviceD3D(); +void CreateRenderTarget(); +void CleanupRenderTarget(); + +int main(int, char**) +{ + // Setup SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) + { + printf("Error: %s\n", SDL_GetError()); + return -1; + } + + // Create window with graphics context + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + + SDL_SysWMinfo wmInfo; + SDL_VERSION(&wmInfo.version); + SDL_GetWindowWMInfo(window, &wmInfo); + + HWND hwnd = (HWND)wmInfo.info.win.window; + + // Initialize Direct3D + if (!CreateDeviceD3D(hwnd)) + { + CleanupDeviceD3D(); + return 1; + } + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + //io.ConfigViewportsNoAutoMerge = true; + //io.ConfigViewportsNoTaskBarIcon = true; + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); + + // Setup Platform/Renderer bindings + ImGui_ImplSDL2_InitForD3D(window); + ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'misc/fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); + + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + SDL_Event event; + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL2_ProcessEvent(&event); + if (event.type == SDL_QUIT) + done = true; + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) + done = true; + } + + // Start the Dear ImGui frame + ImGui_ImplDX11_NewFrame(); + ImGui_ImplSDL2_NewFrame(window); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); + g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + g_pSwapChain->Present(1, 0); // Present with vsync + //g_pSwapChain->Present(0, 0); // Present without vsync + } + + // Cleanup + ImGui_ImplDX11_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + CleanupDeviceD3D(); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} + +// Helper functions +bool CreateDeviceD3D(HWND hWnd) +{ + // Setup swap chain + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 2; + sd.BufferDesc.Width = 0; + sd.BufferDesc.Height = 0; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + UINT createDeviceFlags = 0; + //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; + D3D_FEATURE_LEVEL featureLevel; + const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; + if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) + return false; + + CreateRenderTarget(); + return true; +} + +void CleanupDeviceD3D() +{ + CleanupRenderTarget(); + if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; } + if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } +} + +void CreateRenderTarget() +{ + ID3D11Texture2D* pBackBuffer; + g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView); + pBackBuffer->Release(); +} + +void CleanupRenderTarget() +{ + if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; } +} diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 1922068efeff3..0cf937a4e0dd6 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -190,6 +190,14 @@ bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window) return ImGui_ImplSDL2_Init(window); } +bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window) +{ +#if !defined(_WIN32) + IM_ASSERT(0 && "Unsupported"); +#endif + return ImGui_ImplSDL2_Init(window); +} + void ImGui_ImplSDL2_Shutdown() { g_Window = NULL; diff --git a/examples/imgui_impl_sdl.h b/examples/imgui_impl_sdl.h index 39cc98e52522c..376e622c7fd10 100644 --- a/examples/imgui_impl_sdl.h +++ b/examples/imgui_impl_sdl.h @@ -21,6 +21,7 @@ typedef union SDL_Event SDL_Event; IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); +IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); From 516c3dee802d67c87487572a2d44d8e2d285efd6 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 18 Jun 2019 11:28:26 +0200 Subject: [PATCH 008/200] Examples: SDL+DX11: Changelog, readme, batch files, fixed vcxproj, minor stylistic fixes + minor sync of other main.cpp files. (#2632) --- docs/CHANGELOG.txt | 6 +- examples/README.txt | 7 +++ examples/example_glfw_metal/main.mm | 1 + examples/example_glfw_opengl2/main.cpp | 1 + examples/example_glfw_opengl3/main.cpp | 1 + examples/example_glfw_vulkan/main.cpp | 1 + examples/example_glut_opengl2/main.cpp | 2 + examples/example_marmalade/main.cpp | 1 + .../example_sdl_directx11/build_win32.bat | 8 +++ .../example_sdl_directx11.vcxproj | 58 +++++++++++-------- examples/example_sdl_directx11/main.cpp | 19 +++--- examples/example_sdl_opengl2/main.cpp | 2 + examples/example_sdl_opengl3/main.cpp | 2 + examples/example_sdl_vulkan/main.cpp | 4 +- examples/example_win32_directx11/main.cpp | 1 + 15 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 examples/example_sdl_directx11/build_win32.bat diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d19dc5301941f..f575242fadd62 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -44,7 +44,11 @@ Breaking Changes: Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] -- ImDrawListSlitter, ImDrawList::ChannelsSplit(), : Fixed an issue with merging draw commands between channel 0 and 1. (#2624) +- ImDrawListSlitter, ImDrawList::ChannelsSplit(), : Fixed an issue with merging draw commands between + channel 0 and 1. (#2624) +- Backends: SDL2: Added dummy ImGui_ImplSDL2_InitForD3D() function to make D3D support more visible. + (#2482, #2632) [@josiahmanson] +- Examples: Added SDL2+DirectX11 example application. (#2632, #2612, #2482) [@vincenthamm] ----------------------------------------------------------------------- diff --git a/examples/README.txt b/examples/README.txt index 116ef6b54e785..5028583bbd57b 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -201,6 +201,7 @@ example_glfw_vulkan/ GLFW (Win32, Mac, Linux) + Vulkan example. = main.cpp + imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp This is quite long and tedious, because: Vulkan. + For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp. example_glut_opengl2/ GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2. @@ -217,6 +218,11 @@ example_null This is used to quickly test compilation of core imgui files in as many setups as possible. Because this application doesn't create a window nor a graphic context, there's no graphics output. +example_sdl_directx11/ + SDL2 + DirectX11 example, Windows only. + = main.cpp + imgui_impl_sdl.cpp + imgui_impl_dx11.cpp + This to demonstrate usage of DirectX with SDL. + example_sdl_opengl2/ SDL2 (Win32, Mac, Linux etc.) + OpenGL example (legacy, fixed pipeline). = main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl2.cpp @@ -240,6 +246,7 @@ example_sdl_vulkan/ SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. = main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp This is quite long and tedious, because: Vulkan. + For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp. example_win32_directx9/ DirectX9 example, Windows only. diff --git a/examples/example_glfw_metal/main.mm b/examples/example_glfw_metal/main.mm index 3b162afbd1740..3a25a9de0e4dc 100644 --- a/examples/example_glfw_metal/main.mm +++ b/examples/example_glfw_metal/main.mm @@ -74,6 +74,7 @@ int main(int, char**) MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new]; + // Our state bool show_demo_window = true; bool show_another_window = false; float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index 57841ffa4bcb5..0a7aa3c3fc419 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -69,6 +69,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index dffd46c933361..76174a1f8449a 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -112,6 +112,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 2d1c4e0044c1b..fc3c1efb1bb26 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -440,6 +440,7 @@ int main(int, char**) ImGui_ImplVulkan_DestroyFontUploadObjects(); } + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index 764ea092b730a..75e48ca2ab0c7 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -18,6 +18,7 @@ #pragma warning (disable: 4505) // unreferenced local function has been removed #endif +// Our state static bool show_demo_window = true; static bool show_another_window = false; static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -105,6 +106,7 @@ int main(int argc, char** argv) glutDisplayFunc(glut_display_func); // Setup Dear ImGui context + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/example_marmalade/main.cpp b/examples/example_marmalade/main.cpp index e844a4c9dad4f..27a4acd9ea47b 100644 --- a/examples/example_marmalade/main.cpp +++ b/examples/example_marmalade/main.cpp @@ -44,6 +44,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_sdl_directx11/build_win32.bat b/examples/example_sdl_directx11/build_win32.bat new file mode 100644 index 0000000000000..8fc702bb618fd --- /dev/null +++ b/examples/example_sdl_directx11/build_win32.bat @@ -0,0 +1,8 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +set OUT_DIR=Debug +set OUT_EXE=example_sdl_directx11 +set INCLUDES=/I.. /I..\.. /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" +set SOURCES=main.cpp ..\imgui_impl_sdl.cpp ..\imgui_impl_dx11.cpp ..\..\imgui*.cpp +set LIBS=/libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib +mkdir %OUT_DIR% +cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj index ce1c5749e79f1..e28a5d2519180 100644 --- a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj +++ b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj @@ -20,7 +20,7 @@ {9E1987E3-1F19-45CA-B9C9-D31E791836D8} - example_win32_directx11 + example_sdl_directx11 8.1 example_sdl_directx11 @@ -28,28 +28,28 @@ Application true - Unicode - v140 + MultiByte + v110 Application true - Unicode - v140 + MultiByte + v110 Application false true - Unicode - v140 + MultiByte + v110 Application false true - Unicode - v140 + MultiByte + v110 @@ -70,43 +70,49 @@ $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + $(IncludePath) $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + $(IncludePath) $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + $(IncludePath) $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + $(IncludePath) Level4 Disabled - ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) true + %SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) - $(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x86 Console + msvcrt.lib Level4 Disabled - ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) true + %SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) - $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x64 Console + msvcrt.lib @@ -115,16 +121,18 @@ MaxSpeed true true - ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) false true true true + %SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) - $(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x86 Console + + @@ -133,25 +141,20 @@ MaxSpeed true true - ..\..;..;%(AdditionalIncludeDirectories);$(SDL2_DIR)\include + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) false true true true + %SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) - $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories);$(SDL2_DIR)\lib\x64 Console + + - - - - - - - @@ -161,6 +164,13 @@ + + + + + + + diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl_directx11/main.cpp index bf470d78f40a6..ae523fe90b9e5 100644 --- a/examples/example_sdl_directx11/main.cpp +++ b/examples/example_sdl_directx11/main.cpp @@ -1,4 +1,4 @@ -// dear imgui: standalone example application for SDL2 + OpenGL +// dear imgui: standalone example application for SDL2 + DirectX 11 // If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp. // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) @@ -22,6 +22,7 @@ void CleanupDeviceD3D(); void CreateRenderTarget(); void CleanupRenderTarget(); +// Main code int main(int, char**) { // Setup SDL @@ -31,14 +32,12 @@ int main(int, char**) return -1; } - // Create window with graphics context + // Setup window SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); - - SDL_SysWMinfo wmInfo; - SDL_VERSION(&wmInfo.version); - SDL_GetWindowWMInfo(window, &wmInfo); - + SDL_SysWMinfo wmInfo; + SDL_VERSION(&wmInfo.version); + SDL_GetWindowWMInfo(window, &wmInfo); HWND hwnd = (HWND)wmInfo.info.win.window; // Initialize Direct3D @@ -52,10 +51,8 @@ int main(int, char**) IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - //io.ConfigViewportsNoAutoMerge = true; - //io.ConfigViewportsNoTaskBarIcon = true; // Setup Dear ImGui style ImGui::StyleColorsDark(); @@ -80,6 +77,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -168,6 +166,7 @@ int main(int, char**) } // Helper functions + bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index 7b3e853a43912..1222c250c40c5 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -13,6 +13,7 @@ #include #include +// Main code int main(int, char**) { // Setup SDL @@ -64,6 +65,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index 38b9ebd596daf..ae1ef5b32a178 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -22,6 +22,7 @@ #include IMGUI_IMPL_OPENGL_LOADER_CUSTOM #endif +// Main code int main(int, char**) { // Setup SDL @@ -104,6 +105,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 6ac67b824badd..12c262e9a32e7 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -322,7 +322,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return 1; + return -1; } // Setup window @@ -353,6 +353,7 @@ int main(int, char**) SetupVulkanWindow(wd, surface, w, h); // Setup Dear ImGui context + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls @@ -423,6 +424,7 @@ int main(int, char**) ImGui_ImplVulkan_DestroyFontUploadObjects(); } + // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 9523728d87ce8..0a8f09b2c43f8 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -146,6 +146,7 @@ int main(int, char**) //g_pSwapChain->Present(0, 0); // Present without vsync } + // Cleanup ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); From dd41df3e98e85030bd478d0c68404667072ec5f1 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 18 Jun 2019 12:50:34 +0200 Subject: [PATCH 009/200] Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). --- docs/CHANGELOG.txt | 2 ++ imgui_draw.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f575242fadd62..d1e0b820c58a5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking Changes: Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). +- Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because + of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawListSlitter, ImDrawList::ChannelsSplit(), : Fixed an issue with merging draw commands between channel 0 and 1. (#2624) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 288d95aed007e..e54a5fdc56c22 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2692,7 +2692,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c } // We ignore blank width at the end of the line (they can be skipped) - if (line_width + word_width >= wrap_width) + if (line_width + word_width > wrap_width) { // Words that cannot possibly fit within an entire line will be cut anywhere. if (word_width < wrap_width) From f563e1a50451fb1a61fd34a3d8c02b95dc983a94 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 19 Jun 2019 18:14:24 +0200 Subject: [PATCH 010/200] Internals: Renamed GetFrontMostPopupModal() to GetTopMostPopupModal() to be consistent. Renamed other locals to follow that terminology. --- imgui.cpp | 36 ++++++++++++++++++------------------ imgui.h | 6 +++--- imgui_internal.h | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 532895333c6ee..0df747f8a3730 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3298,7 +3298,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame() if (!g.HoveredRootWindow->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) g.MovingWindow = NULL; } - else if (g.NavWindow != NULL && GetFrontMostPopupModal() == NULL) + else if (g.NavWindow != NULL && GetTopMostPopupModal() == NULL) { // Clicking on void disable focus FocusWindow(NULL); @@ -3310,9 +3310,9 @@ void ImGui::UpdateMouseMovingWindowEndFrame() // (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger) if (g.IO.MouseClicked[1]) { - // Find the top-most window between HoveredWindow and the front most Modal Window. + // Find the top-most window between HoveredWindow and the top-most Modal Window. // This is where we can trim the popup stack. - ImGuiWindow* modal = GetFrontMostPopupModal(); + ImGuiWindow* modal = GetTopMostPopupModal(); bool hovered_window_above_modal = false; if (modal == NULL) hovered_window_above_modal = true; @@ -3458,7 +3458,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() FindHoveredWindow(); // Modal windows prevents cursor from hovering behind them. - ImGuiWindow* modal_window = GetFrontMostPopupModal(); + ImGuiWindow* modal_window = GetTopMostPopupModal(); if (modal_window) if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) g.HoveredRootWindow = g.HoveredWindow = NULL; @@ -3654,7 +3654,7 @@ void ImGui::NewFrame() UpdateMouseMovingWindowNewFrame(); // Background darkening/whitening - if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) + if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); else g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); @@ -4062,18 +4062,18 @@ void ImGui::Render() if (!g.BackgroundDrawList.VtxBuffer.empty()) AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.BackgroundDrawList); - ImGuiWindow* windows_to_render_front_most[2]; - windows_to_render_front_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; - windows_to_render_front_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL; + ImGuiWindow* windows_to_render_top_most[2]; + windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; + windows_to_render_top_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL; for (int n = 0; n != g.Windows.Size; n++) { ImGuiWindow* window = g.Windows[n]; - if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1]) + if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) AddRootWindowToDrawData(window); } - for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_front_most); n++) - if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window - AddRootWindowToDrawData(windows_to_render_front_most[n]); + for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++) + if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window + AddRootWindowToDrawData(windows_to_render_top_most[n]); g.DrawDataBuilder.FlattenIntoSingleLayer(); // Draw software mouse cursor if requested @@ -5648,7 +5648,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) PushClipRect(host_rect.Min, host_rect.Max, false); // Draw modal window background (darkens what is behind them, all viewports) - const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0; + const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0; const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow); if (dim_bg_for_modal || dim_bg_for_window_list) { @@ -5893,7 +5893,7 @@ void ImGui::BringWindowToFocusFront(ImGuiWindow* window) ImGuiContext& g = *GImGui; if (g.WindowsFocusOrder.back() == window) return; - for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the front most window + for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the top-most window if (g.WindowsFocusOrder[i] == window) { memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*)); @@ -5908,7 +5908,7 @@ void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) ImGuiWindow* current_front_window = g.Windows.back(); if (current_front_window == window || current_front_window->RootWindow == window) return; - for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window + for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window if (g.Windows[i] == window) { memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*)); @@ -7178,7 +7178,7 @@ bool ImGui::IsPopupOpen(const char* str_id) return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id); } -ImGuiWindow* ImGui::GetFrontMostPopupModal() +ImGuiWindow* ImGui::GetTopMostPopupModal() { ImGuiContext& g = *GImGui; for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) @@ -8435,7 +8435,7 @@ static void ImGui::NavUpdateWindowing() ImGuiWindow* apply_focus_window = NULL; bool apply_toggle_layer = false; - ImGuiWindow* modal_window = GetFrontMostPopupModal(); + ImGuiWindow* modal_window = GetTopMostPopupModal(); if (modal_window != NULL) { g.NavWindowingTarget = NULL; @@ -8477,7 +8477,7 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingHighlightAlpha = 1.0f; } - // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most) + // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered top-most) if (!IsNavInputDown(ImGuiNavInput_Menu)) { g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. diff --git a/imgui.h b/imgui.h index 8131ac369a3e4..32b267e24d728 100644 --- a/imgui.h +++ b/imgui.h @@ -275,17 +275,17 @@ namespace ImGui IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() - IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() + IMGUI_API void SetNextWindowFocus(); // set next window to be focused / top-most. call before Begin() IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). - IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). + IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state - IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. + IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus. // Content region // - Those functions are bound to be redesigned soon (they are confusing, incomplete and return values in local window coordinates which increases confusion) diff --git a/imgui_internal.h b/imgui_internal.h index 599f360f3a93d..67ee3b4d2612b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -919,7 +919,7 @@ struct ImGuiContext ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging - ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. + ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed top-most. ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f ImGuiWindow* NavWindowingList; float NavWindowingTimer; @@ -1520,7 +1520,7 @@ namespace ImGui IMGUI_API bool IsPopupOpen(ImGuiID id); // Test for id within current popup stack level (currently begin-ed into); this doesn't scan the whole popup stack! IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); - IMGUI_API ImGuiWindow* GetFrontMostPopupModal(); + IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy = ImGuiPopupPositionPolicy_Default); From 41e2d4b5ae156462fc1c74c3c0d7fd1525da3b62 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 20 Jun 2019 16:09:31 +0200 Subject: [PATCH 011/200] ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, also this type was added in 1.71 and not advertised as a public-facing feature). --- docs/CHANGELOG.txt | 4 +++- imgui.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d1e0b820c58a5..6d74730432a6a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,8 +46,10 @@ Other Changes: - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] -- ImDrawListSlitter, ImDrawList::ChannelsSplit(), : Fixed an issue with merging draw commands between +- ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between channel 0 and 1. (#2624) +- ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, + also this type was added in 1.71 and not advertised as a public-facing feature). - Backends: SDL2: Added dummy ImGui_ImplSDL2_InitForD3D() function to make D3D support more visible. (#2482, #2632) [@josiahmanson] - Examples: Added SDL2+DirectX11 example application. (#2632, #2612, #2482) [@vincenthamm] diff --git a/imgui.h b/imgui.h index 32b267e24d728..101f424950865 100644 --- a/imgui.h +++ b/imgui.h @@ -1822,7 +1822,8 @@ struct ImDrawListSplitter int _Count; // Number of active channels (1+) ImVector _Channels; // Draw channels (not resized down so _Count might be < Channels.Size) - inline ImDrawListSplitter() { Clear(); } + inline ImDrawListSplitter() { Clear(); } + inline ~ImDrawListSplitter() { ClearFreeMemory(); } inline void Clear() { _Current = 0; _Count = 1; } // Do not clear Channels[] so our allocations are reused next frame IMGUI_API void ClearFreeMemory(); IMGUI_API void Split(ImDrawList* draw_list, int count); From eb3e271c24c25f668be02bbf25aeb46a46b9fc08 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 21 Jun 2019 19:38:33 +0200 Subject: [PATCH 012/200] Demo: Using ImVec2(-FLT_MIN,0.0f) instead of ImVec2(-1.0f,0.0f) where it makes sense. (#2449) --- imgui_demo.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e4b89499f8a51..80c577719c09c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -968,7 +968,7 @@ static void ShowDemoWindowWidgets() ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", (unsigned int*)&flags, ImGuiInputTextFlags_ReadOnly); ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", (unsigned int*)&flags, ImGuiInputTextFlags_AllowTabInput); ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", (unsigned int*)&flags, ImGuiInputTextFlags_CtrlEnterForNewLine); - ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), flags); + ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); ImGui::TreePop(); } @@ -1024,7 +1024,7 @@ static void ShowDemoWindowWidgets() static ImVector my_str; if (my_str.empty()) my_str.push_back(0); - Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16)); + Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16)); ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity()); ImGui::TreePop(); } @@ -1085,7 +1085,8 @@ static void ShowDemoWindowWidgets() if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } } - // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. + // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, + // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::Text("Progress Bar"); @@ -1727,7 +1728,7 @@ static void ShowDemoWindowLayout() { char buf[32]; sprintf(buf, "%03d", i); - ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); + ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); ImGui::NextColumn(); } ImGui::EndChild(); @@ -2519,7 +2520,7 @@ static void ShowDemoWindowColumns() char label[32]; sprintf(label, "Item %d", n); if (ImGui::Selectable(label)) {} - //if (ImGui::Button(label, ImVec2(-1,0))) {} + //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {} ImGui::NextColumn(); } ImGui::Columns(1); @@ -2570,7 +2571,7 @@ static void ShowDemoWindowColumns() ImGui::Text("Width %.2f", ImGui::GetColumnWidth()); ImGui::Text("Offset %.2f", ImGui::GetColumnOffset()); ImGui::Text("Long text that is likely to clip"); - ImGui::Button("Button", ImVec2(-1.0f, 0.0f)); + ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f)); ImGui::NextColumn(); } ImGui::Columns(1); From 4b95e7c2f3d5793bf73c7e8b4c130696010d2f19 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 26 Jun 2019 12:15:32 +0200 Subject: [PATCH 013/200] Doc: Tweak and extra mention of AddCustomRectFontGlyph + made the example register two rectangles. --- imgui.cpp | 2 ++ misc/fonts/README.txt | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0df747f8a3730..79c2de90f2788 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -844,6 +844,8 @@ CODE main font. Then you can refer to icons within your strings. You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment. (Read the 'misc/fonts/README.txt' file for more details about icons font loading.) + With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas, + and copying your own graphics data into it. See misc/fonts/README.txt about using the AddCustomRectFontGlyph API. Q: How can I load multiple fonts? A: Use the font atlas to pack them into a single texture: diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 010a72070d1cc..cf953cf6f5bcd 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -212,9 +212,11 @@ texture, and blit/copy any graphics data of your choice into those rectangles. Pseudo-code: - // Add font, then register one custom 13x13 rectangle mapped to glyph 'a' of this font + // Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font ImFont* font = io.Fonts->AddFontDefault(); - int rect_id = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1); + int rect_ids[2]; + rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1); + rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1); // Build atlas io.Fonts->Build(); @@ -224,14 +226,18 @@ Pseudo-code: int tex_width, tex_height; io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height); - // Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here) - if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) + for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++) { - for (int y = 0; y < rect->Height; y++) + int rect_id = rects_ids[rect_n]; + if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) { - ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X); - for (int x = rect->Width; x > 0; x--) - *p++ = IM_COL32(255, 0, 0, 255); + // Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!) + for (int y = 0; y < rect->Height; y++) + { + ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X); + for (int x = rect->Width; x > 0; x--) + *p++ = IM_COL32(255, 0, 0, 255); + } } } From 1dd322c6fb700242b156f898862ec098fa88b633 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 27 Jun 2019 12:20:18 +0200 Subject: [PATCH 014/200] Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. --- docs/CHANGELOG.txt | 1 + imgui_draw.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6d74730432a6a..bff027d359ace 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,7 @@ Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). +- Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between channel 0 and 1. (#2624) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e54a5fdc56c22..7b20f2b16af21 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -260,7 +260,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); - colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f); @@ -316,7 +316,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f); From 82711251b66a30b63a815ec6f9519c2cb6914cce Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 27 Jun 2019 18:03:19 +0200 Subject: [PATCH 015/200] Internals: ImGuiListClipper using absolute coordinate (instead of relative one). Minor no-op tweaks + ImDrawListSplitter assert --- imgui.cpp | 31 ++++++++++++++++++++----------- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 79c2de90f2788..6096f5104b440 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2239,7 +2239,8 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) //----------------------------------------------------------------------------- // [SECTION] ImGuiListClipper -// This is currently not as flexible/powerful as it should be, needs some rework (see TODO) +// This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed +// the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO) //----------------------------------------------------------------------------- static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) @@ -2247,12 +2248,14 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor. // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. // The clipper should probably have a 4th step to display the last item in a regular manner. - ImGui::SetCursorPosY(pos_y); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. - window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->DC.CursorPos.y = pos_y; + window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y); + window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. + window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. if (ImGuiColumns* columns = window->DC.CurrentColumns) - columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -2260,7 +2263,10 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) // FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. void ImGuiListClipper::Begin(int count, float items_height) { - StartPosY = ImGui::GetCursorPosY(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + StartPosY = window->DC.CursorPos.y; ItemsHeight = items_height; ItemsCount = count; StepNo = 0; @@ -2287,7 +2293,10 @@ void ImGuiListClipper::End() bool ImGuiListClipper::Step() { - if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems) + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (ItemsCount == 0 || window->SkipItems) { ItemsCount = -1; return false; @@ -2296,16 +2305,16 @@ bool ImGuiListClipper::Step() { DisplayStart = 0; DisplayEnd = 1; - StartPosY = ImGui::GetCursorPosY(); + StartPosY = window->DC.CursorPos.y; StepNo = 1; return true; } if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. { if (ItemsCount == 1) { ItemsCount = -1; return false; } - float items_height = ImGui::GetCursorPosY() - StartPosY; + float items_height = window->DC.CursorPos.y - StartPosY; IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically - Begin(ItemsCount-1, items_height); + Begin(ItemsCount - 1, items_height); DisplayStart++; DisplayEnd++; StepNo = 3; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 80c577719c09c..afd2b894b80e1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4022,7 +4022,7 @@ static void ShowExampleAppLongText(bool* p_open) static ImGuiTextBuffer log; static int lines = 0; ImGui::Text("Printing unusually long amount of text."); - ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0"); + ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped\0Multiple calls to Text(), not clipped (slow)\0"); ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); if (ImGui::Button("Clear")) { log.clear(); lines = 0; } ImGui::SameLine(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 7b20f2b16af21..51ff2cd9da859 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1304,7 +1304,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list) void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) { - IM_ASSERT(idx < _Count); + IM_ASSERT(idx >= 0 && idx < _Count); if (_Current == idx) return; // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() From 401e05147cedbe50dd150b46f1a323e622929a9a Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 29 Jun 2019 18:55:06 +0200 Subject: [PATCH 016/200] Internals: Moved CalcListClipping close to ImGuiListClipper code (no-op) --- imgui.cpp | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6096f5104b440..1053860285376 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2243,6 +2243,47 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) // the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO) //----------------------------------------------------------------------------- +// Helper to calculate coarse clipping of large list of evenly sized items. +// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. +// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX +void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.LogEnabled) + { + // If logging is active, do not perform any clipping + *out_items_display_start = 0; + *out_items_display_end = items_count; + return; + } + if (window->SkipItems) + { + *out_items_display_start = *out_items_display_end = 0; + return; + } + + // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect + ImRect unclipped_rect = window->ClipRect; + if (g.NavMoveRequest) + unclipped_rect.Add(g.NavScoringRectScreen); + + const ImVec2 pos = window->DC.CursorPos; + int start = (int)((unclipped_rect.Min.y - pos.y) / items_height); + int end = (int)((unclipped_rect.Max.y - pos.y) / items_height); + + // When performing a navigation request, ensure we have one item extra in the direction we are moving to + if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) + start--; + if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) + end++; + + start = ImClamp(start, 0, items_count); + end = ImClamp(end + 1, start, items_count); + *out_items_display_start = start; + *out_items_display_end = end; +} + static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) { // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor. @@ -4130,47 +4171,6 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex return text_size; } -// Helper to calculate coarse clipping of large list of evenly sized items. -// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. -// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX -void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (g.LogEnabled) - { - // If logging is active, do not perform any clipping - *out_items_display_start = 0; - *out_items_display_end = items_count; - return; - } - if (window->SkipItems) - { - *out_items_display_start = *out_items_display_end = 0; - return; - } - - // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect - ImRect unclipped_rect = window->ClipRect; - if (g.NavMoveRequest) - unclipped_rect.Add(g.NavScoringRectScreen); - - const ImVec2 pos = window->DC.CursorPos; - int start = (int)((unclipped_rect.Min.y - pos.y) / items_height); - int end = (int)((unclipped_rect.Max.y - pos.y) / items_height); - - // When performing a navigation request, ensure we have one item extra in the direction we are moving to - if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) - start--; - if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) - end++; - - start = ImClamp(start, 0, items_count); - end = ImClamp(end + 1, start, items_count); - *out_items_display_start = start; - *out_items_display_end = end; -} - // Find window given position, search front-to-back // FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programatically // with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is From a89f05a10e80fc25f64dc32f0feff164bb1ede27 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 27 Jun 2019 16:35:56 +0200 Subject: [PATCH 017/200] Child windows inherit Hidden frames setting from parent more accurately, so HiddenFramesCannotSkipItems is honored by child windows. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1053860285376..5f402f74336f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5832,9 +5832,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) window->HiddenFramesCanSkipItems = 1; - // Completely hide along with parent or if parent is collapsed - if (parent_window && (parent_window->Collapsed || parent_window->Hidden)) + // Hide along with parent or if parent is collapsed + if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0)) window->HiddenFramesCanSkipItems = 1; + if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0)) + window->HiddenFramesCannotSkipItems = 1; } // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point) From 2a3517a39983c4b7a2d4c1596b803e20d2137fc2 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 30 Jun 2019 12:03:09 +0200 Subject: [PATCH 018/200] Internals: Checkbox: Added undocumented mixed/indeterminate/tristate support via ImGuiItemFlags_MixedValue. (#2644) --- docs/TODO.txt | 2 +- imgui_internal.h | 1 + imgui_widgets.cpp | 11 +++++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index a918b9e16865f..cdd92383ce911 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -65,7 +65,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - widgets: start exposing PushItemFlag() and ImGuiItemFlags - widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260 - widgets: activate by identifier (trigger button, focus given id) - - widgets: a way to represent "mixed" values, so e.g. all values replaced with **, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) + - widgets: a way to represent "mixed" values, so e.g. all values replaced with *, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) (#2644) - widgets: selectable: generic BeginSelectable()/EndSelectable() mechanism. - widgets: selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection) - widgets: checkbox: checkbox with custom glyph inside frame. diff --git a/imgui_internal.h b/imgui_internal.h index 67ee3b4d2612b..3b96116e8113a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -384,6 +384,7 @@ enum ImGuiItemFlags_ ImGuiItemFlags_NoNav = 1 << 3, // false ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window + ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_Default_ = 0 }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3490586bc5afc..a5959c230c616 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1001,10 +1001,17 @@ bool ImGui::Checkbox(const char* label, bool* v) const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); RenderNavHighlight(total_bb, id); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); - if (*v) + ImU32 check_col = GetColorU32(ImGuiCol_CheckMark); + if (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) + { + // Undocumented tristate/mixed/indeterminate checkbox (#2644) + ImVec2 pad(ImMax(1.0f, (float)(int)(square_sz / 3.6f)), ImMax(1.0f, (float)(int)(square_sz / 3.6f))); + window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); + } + else if (*v) { const float pad = ImMax(1.0f, (float)(int)(square_sz / 6.0f)); - RenderCheckMark(check_bb.Min + ImVec2(pad, pad), GetColorU32(ImGuiCol_CheckMark), square_sz - pad*2.0f); + RenderCheckMark(check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f); } if (g.LogEnabled) From caf119a982dab93ab45a312be4f2d243f034b097 Mon Sep 17 00:00:00 2001 From: kevreco Date: Tue, 30 Jan 2018 21:51:28 +0100 Subject: [PATCH 019/200] Added 'SetScrollHereX' and 'SetScrollFromPosX' (#1580) --- imgui.cpp | 26 +++++++++++++++++++++++++- imgui.h | 2 ++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5f402f74336f8..1f8779614638e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4841,7 +4841,12 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s if (window->ScrollTarget.x < FLT_MAX) { float cr_x = window->ScrollTargetCenterRatio.x; - scroll.x = window->ScrollTarget.x - cr_x * window->InnerRect.GetWidth(); + float target_x = window->ScrollTarget.x; + if (snap_on_edges && cr_x <= 0.0f && target_x <= window->WindowPadding.x) + target_x = 0.0f; + else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + GImGui->Style.ItemSpacing.x) + target_x = window->ContentSize.x + window->WindowPadding.x * 2.0f; + scroll.x = target_x - cr_x * window->InnerRect.GetWidth(); } if (window->ScrollTarget.y < FLT_MAX) { @@ -6861,6 +6866,25 @@ void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) window->ScrollTargetCenterRatio.y = center_y_ratio; } +void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) +{ + // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); + window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); + window->ScrollTargetCenterRatio.x = center_x_ratio; +} + +// center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. +void ImGui::SetScrollHereX(float center_x_ratio) +{ + ImGuiWindow* window = GetCurrentWindow(); + float target_x = window->DC.LastItemRect.Min.x - window->Pos.x; // Left of last item, in window space + float last_item_width = window->DC.LastItemRect.GetWidth(); + target_x += (last_item_width * center_x_ratio) + (GImGui->Style.ItemSpacing.x * (center_x_ratio - 0.5f) * 2.0f); // Precisely aim before, in the middle or after the last item. + SetScrollFromPosX(target_x, center_x_ratio); +} + // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. void ImGui::SetScrollHereY(float center_y_ratio) { diff --git a/imgui.h b/imgui.h index 101f424950865..7b34c7c531823 100644 --- a/imgui.h +++ b/imgui.h @@ -302,7 +302,9 @@ namespace ImGui IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] + IMGUI_API void SetScrollHereX(float center_x_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_x_ratio=0.0: left, 0.5: center, 1.0: right. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. + IMGUI_API void SetScrollFromPosX(float local_x, float center_x_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position. IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position. // Parameters stacks (shared) From da29d77253072ad16128e9c9104bf8ad71299822 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 1 Jul 2019 12:15:36 +0200 Subject: [PATCH 020/200] Added SetScrollXHere, SetScrollFromPosX: Changelog, demo, comments (#1580). --- docs/CHANGELOG.txt | 1 + docs/TODO.txt | 1 + imgui.cpp | 16 +++++----- imgui_demo.cpp | 73 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 65 insertions(+), 26 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bff027d359ace..f1861aac585d9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,7 @@ Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). +- Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between diff --git a/docs/TODO.txt b/docs/TODO.txt index cdd92383ce911..d5291373c4417 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -30,6 +30,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false. - window/child: the first draw command of a child window could be moved into the current draw command of the parent window (unless child+tooltip?). - window/child: border could be emitted in parent as well. + - window/child: allow SetNextWindowContentSize() to work on child windows. - window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero. - window/tab: add a way to signify that a window or docked window requires attention (e.g. blinking title bar). - scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse) diff --git a/imgui.cpp b/imgui.cpp index 1f8779614638e..5d37d08c4075e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6857,22 +6857,22 @@ void ImGui::SetScrollY(float scroll_y) window->ScrollTargetCenterRatio.y = 0.0f; } -void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) +void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); - window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); - window->ScrollTargetCenterRatio.y = center_y_ratio; + IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); + window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); + window->ScrollTargetCenterRatio.x = center_x_ratio; } -void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) +void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); - window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); - window->ScrollTargetCenterRatio.x = center_x_ratio; + IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); + window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); + window->ScrollTargetCenterRatio.y = center_y_ratio; } // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index afd2b894b80e1..8d9337a59abe4 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1744,7 +1744,7 @@ static void ShowDemoWindowLayout() // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from the POV of the parent window) // See "Widgets" -> "Querying Status (Active/Focused/Hovered etc.)" section for more details about this. { - ImGui::SetCursorPosX(50); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 10); ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100)); ImGui::BeginChild("blah", ImVec2(200, 100), true, ImGuiWindowFlags_None); for (int n = 0; n < 50; n++) @@ -1957,7 +1957,7 @@ static void ShowDemoWindowLayout() if (ImGui::TreeNode("Groups")) { - HelpMarker("Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it."); + HelpMarker("BeginGroup() basically locks the horizontal position for new line. EndGroup() bundles the whole group so that you can use \"item\" functions such as IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group."); ImGui::BeginGroup(); { ImGui::BeginGroup(); @@ -2056,21 +2056,22 @@ static void ShowDemoWindowLayout() if (ImGui::TreeNode("Scrolling")) { - HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position."); + // Vertical scroll functions + HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position."); static bool track = true; - static int track_line = 50; + static int track_item = 50; static float scroll_to_off_px = 0.0f; static float scroll_to_pos_px = 200.0f; ImGui::Checkbox("Track", &track); ImGui::PushItemWidth(100); - ImGui::SameLine(140); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d"); + ImGui::SameLine(140); track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); bool scroll_to_off = ImGui::Button("Scroll Offset"); - ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off_y", &scroll_to_off_px, 1.00f, 0, 9999, "+%.0f px"); + ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, 9999, "+%.0f px"); bool scroll_to_pos = ImGui::Button("Scroll To Pos"); - ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos_y", &scroll_to_pos_px, 1.00f, 0, 9999, "Y = %.0f px"); + ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, 0, 9999, "X/Y = %.0f px"); ImGui::PopItemWidth(); if (scroll_to_off || scroll_to_pos) @@ -2078,28 +2079,31 @@ static void ShowDemoWindowLayout() ImGuiStyle& style = ImGui::GetStyle(); float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5; + if (child_w < 20.0f) + child_w = 20.0f; + ImGui::PushID("##VerticalScrolling"); for (int i = 0; i < 5; i++) { if (i > 0) ImGui::SameLine(); ImGui::BeginGroup(); - ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom"); + const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" }; + ImGui::TextUnformatted(names[i]); - ImGuiWindowFlags child_flags = ImGuiWindowFlags_MenuBar; - ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true, child_flags); + ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true, ImGuiWindowFlags_None); if (scroll_to_off) ImGui::SetScrollY(scroll_to_off_px); if (scroll_to_pos) ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f); - for (int line = 0; line < 100; line++) + for (int item = 0; item < 100; item++) { - if (track && line == track_line) + if (track && item == track_item) { - ImGui::TextColored(ImVec4(1,1,0,1), "Line %d", line); + ImGui::TextColored(ImVec4(1,1,0,1), "Item %d", item); ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom } else { - ImGui::Text("Line %d", line); + ImGui::Text("Item %d", item); } } float scroll_y = ImGui::GetScrollY(); @@ -2108,11 +2112,44 @@ static void ShowDemoWindowLayout() ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y); ImGui::EndGroup(); } - ImGui::TreePop(); - } + ImGui::PopID(); - if (ImGui::TreeNode("Horizontal Scrolling")) - { + // Horizontal scroll functions + ImGui::Spacing(); + HelpMarker("Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\nUsing the \"Scroll To Pos\" button above will make the discontinuity at edges visible: scrolling to the top/bottom/left/right-most item will add an additional WindowPadding to reflect on reaching the edge of the list.\n\nBecause the clipping rectangle of most window hides half worth of WindowPadding on the left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the equivalent SetScrollFromPosY(+1) wouldn't."); + ImGui::PushID("##HorizontalScrolling"); + for (int i = 0; i < 5; i++) + { + float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f; + ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(-100, child_height), true, ImGuiWindowFlags_HorizontalScrollbar); + if (scroll_to_off) + ImGui::SetScrollX(scroll_to_off_px); + if (scroll_to_pos) + ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f); + for (int item = 0; item < 100; item++) + { + if (track && item == track_item) + { + ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item); + ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right + } + else + { + ImGui::Text("Item %d", item); + } + ImGui::SameLine(); + } + float scroll_x = ImGui::GetScrollX(); + float scroll_max_x = ImGui::GetScrollMaxX(); + ImGui::EndChild(); + ImGui::SameLine(); + const char* names[] = { "Left", "25%", "Center", "75%", "Right" }; + ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x); + ImGui::Spacing(); + } + ImGui::PopID(); + + // Miscellaneous Horizontal Scrolling Demo HelpMarker("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\nYou may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin()."); static int lines = 7; ImGui::SliderInt("Lines", &lines, 1, 15); From 58c9f8a19450650088e92858f6df25a4a4237f97 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 1 Jul 2019 18:48:21 +0200 Subject: [PATCH 021/200] Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow(). + Internals: Minor renaming. --- docs/CHANGELOG.txt | 1 + imconfig.h | 1 + imgui.cpp | 39 +++++++++++++++++++++++---------------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f1861aac585d9..3eaed6266a7e2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,7 @@ Other Changes: of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. +- Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow(). - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between channel 0 and 1. (#2624) diff --git a/imconfig.h b/imconfig.h index 4d7adf5d795ac..5d9caecd09c56 100644 --- a/imconfig.h +++ b/imconfig.h @@ -28,6 +28,7 @@ //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) // It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp. //#define IMGUI_DISABLE_DEMO_WINDOWS +//#define IMGUI_DISABLE_METRICS_WINDOW //---- Don't implement some functions to reduce linkage requirements. //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. diff --git a/imgui.cpp b/imgui.cpp index 5d37d08c4075e..f5602651cc549 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9935,6 +9935,7 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} // [SECTION] METRICS/DEBUG WINDOW //----------------------------------------------------------------------------- +#ifndef IMGUI_DISABLE_METRICS_WINDOW void ImGui::ShowMetricsWindow(bool* p_open) { if (!ImGui::Begin("Dear ImGui Metrics", p_open)) @@ -9943,10 +9944,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; } - enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerRect, RT_InnerClipRect, RT_WorkRect, RT_Contents, RT_ContentsRegionRect, RT_Count }; + enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Contents, WRT_ContentsRegionRect, WRT_Count }; // Windows Rect Type + const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" }; + static bool show_windows_begin_order = false; static bool show_windows_rects = false; - static int show_windows_rect_type = RT_WorkRect; + static int show_windows_rect_type = WRT_WorkRect; static bool show_drawcmd_clip_rects = true; ImGuiIO& io = ImGui::GetIO(); @@ -9959,15 +9962,15 @@ void ImGui::ShowMetricsWindow(bool* p_open) struct Funcs { - static ImRect GetRect(ImGuiWindow* window, int rect_type) + static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) { - if (rect_type == RT_OuterRect) { return window->Rect(); } - else if (rect_type == RT_OuterRectClipped) { return window->OuterRectClipped; } - else if (rect_type == RT_InnerRect) { return window->InnerRect; } - else if (rect_type == RT_InnerClipRect) { return window->InnerClipRect; } - else if (rect_type == RT_WorkRect) { return window->WorkRect; } - else if (rect_type == RT_Contents) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } - else if (rect_type == RT_ContentsRegionRect) { return window->ContentsRegionRect; } + if (rect_type == WRT_OuterRect) { return window->Rect(); } + else if (rect_type == WRT_OuterRectClipped) { return window->OuterRectClipped; } + else if (rect_type == WRT_InnerRect) { return window->InnerRect; } + else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; } + else if (rect_type == WRT_WorkRect) { return window->WorkRect; } + else if (rect_type == WRT_Contents) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } + else if (rect_type == WRT_ContentsRegionRect) { return window->ContentsRegionRect; } IM_ASSERT(0); return ImRect(); } @@ -10174,16 +10177,15 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Checkbox("Show windows rectangles", &show_windows_rects); ImGui::SameLine(); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12); - const char* rects_names[RT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" }; - show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, rects_names, RT_Count); + show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count); if (show_windows_rects && g.NavWindow) { ImGui::BulletText("'%s':", g.NavWindow->Name); ImGui::Indent(); - for (int n = 0; n < RT_Count; n++) + for (int rect_n = 0; rect_n < WRT_Count; rect_n++) { - ImRect r = Funcs::GetRect(g.NavWindow, n); - ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), rects_names[n]); + ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); + ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); } ImGui::Unindent(); } @@ -10201,7 +10203,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImDrawList* draw_list = GetForegroundDrawList(window); if (show_windows_rects) { - ImRect r = Funcs::GetRect(window, show_windows_rect_type); + ImRect r = Funcs::GetWindowRect(window, show_windows_rect_type); draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); } if (show_windows_begin_order && !(window->Flags & ImGuiWindowFlags_ChildWindow)) @@ -10216,6 +10218,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImGui::End(); } +#else +void ImGui::ShowMetricsWindow(bool*) +{ +} +#endif //----------------------------------------------------------------------------- From e16564e67a2e88d4cbe3afa6594650712790fba3 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 1 Jul 2019 20:57:15 +0200 Subject: [PATCH 022/200] Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 4 ++-- imgui_widgets.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3eaed6266a7e2..d8e96b4c48cbe 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,7 @@ Breaking Changes: Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). +- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8d9337a59abe4..a8d72f2ef8468 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2079,8 +2079,8 @@ static void ShowDemoWindowLayout() ImGuiStyle& style = ImGui::GetStyle(); float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5; - if (child_w < 20.0f) - child_w = 20.0f; + if (child_w < 1.0f) + child_w = 1.0f; ImGui::PushID("##VerticalScrolling"); for (int i = 0; i < 5; i++) { diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a5959c230c616..8af935c5b8bfb 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -895,13 +895,13 @@ void ImGui::Scrollbar(ImGuiAxis axis) ImRect bb; if (axis == ImGuiAxis_X) { - bb.Min = ImVec2(inner_rect.Min.x, outer_rect.Max.y - border_size - scrollbar_size); + bb.Min = ImVec2(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size)); bb.Max = ImVec2(inner_rect.Max.x, outer_rect.Max.y); rounding_corners |= ImDrawCornerFlags_BotLeft; } else { - bb.Min = ImVec2(outer_rect.Max.x - border_size - scrollbar_size, inner_rect.Min.y); + bb.Min = ImVec2(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y); bb.Max = ImVec2(outer_rect.Max.x, window->InnerRect.Max.y); rounding_corners |= ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0; } From 54c49b5fb1371626f92853a2658cfe2d51d2e41d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 2 Jul 2019 18:28:53 +0200 Subject: [PATCH 023/200] Window: Mouse wheel scrolling while hovering a child window is automatically forwarded to parent window if ScrollMax is zero on the scrolling axis. Also still case if ImGuiWindowFlags_NoScrollWithMouse is set (not new), but previously the forwarding would be disabled if ImGuiWindowFlags_NoScrollbar was set on the child window, which is not the case any more (amend #1502, #1380). --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 49 +++++++++++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d8e96b4c48cbe..331e90059fa77 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,11 @@ Breaking Changes: Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). +- Window: Mouse wheel scrolling while hovering a child window is automatically forwarded to parent window + if ScrollMax is zero on the scrolling axis. + Also still case if ImGuiWindowFlags_NoScrollWithMouse is set (not new), but previously the forwarding + would be disabled if ImGuiWindowFlags_NoScrollbar was set on the child window, which is not the case + any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). - Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). diff --git a/imgui.cpp b/imgui.cpp index f5602651cc549..4d7ff31122dad 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3449,12 +3449,12 @@ void ImGui::UpdateMouseWheel() return; if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) return; - ImGuiWindow* window = g.HoveredWindow; // Zoom / Scale window // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned. - if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling && !window->Collapsed) + if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling && !g.HoveredWindow->Collapsed) { + ImGuiWindow* window = g.HoveredWindow; const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); const float scale = new_font_scale / window->FontWindowScale; window->FontWindowScale = new_font_scale; @@ -3469,31 +3469,36 @@ void ImGui::UpdateMouseWheel() } // Mouse wheel scrolling - // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). - while ((window->Flags & ImGuiWindowFlags_ChildWindow) && (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs) && window->ParentWindow) - window = window->ParentWindow; - const bool scroll_allowed = !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs); - if (scroll_allowed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f) && !g.IO.KeyCtrl) - { - ImVec2 max_step = window->InnerRect.GetSize() * 0.67f; + // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent + // FIXME: Lock scrolling window while not moving (see #2604) - // Vertical Mouse Wheel Scrolling (hold Shift to scroll horizontally) - if (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) - { - float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step.y)); - SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * scroll_step); - } - else if (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) + // Vertical Mouse Wheel scrolling + const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; + if (wheel_y != 0.0f && !g.IO.KeyCtrl) + { + ImGuiWindow* window = g.HoveredWindow; + while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) + window = window->ParentWindow; + if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) { - float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step.x)); - SetWindowScrollX(window, window->Scroll.x - g.IO.MouseWheel * scroll_step); + float max_step = window->InnerRect.GetHeight() * 0.67f; + float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step)); + SetWindowScrollY(window, window->Scroll.y - wheel_y * scroll_step); } + } - // Horizontal Mouse Wheel Scrolling (for hardware that supports it) - if (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) + // Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held + const float wheel_x = (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheelH : (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; + if (wheel_x != 0.0f && !g.IO.KeyCtrl) + { + ImGuiWindow* window = g.HoveredWindow; + while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) + window = window->ParentWindow; + if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) { - float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step.x)); - SetWindowScrollX(window, window->Scroll.x - g.IO.MouseWheelH * scroll_step); + float max_step = window->InnerRect.GetWidth() * 0.67f; + float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step)); + SetWindowScrollX(window, window->Scroll.x - wheel_x * scroll_step); } } } From d23f1b1409fbb565b974599c2f3bb0d83b830a0b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 10 Jul 2019 11:36:43 +0200 Subject: [PATCH 024/200] fonts/binary_to_compress: display error message when failing to open file + misc comments. --- docs/CHANGELOG.txt | 1 + imgui.h | 20 ++++++++++---------- misc/fonts/binary_to_compressed_c.cpp | 7 +++++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 331e90059fa77..2d507bfeb6d26 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,7 @@ Other Changes: channel 0 and 1. (#2624) - ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, also this type was added in 1.71 and not advertised as a public-facing feature). +- Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file. - Backends: SDL2: Added dummy ImGui_ImplSDL2_InitForD3D() function to make D3D support more visible. (#2482, #2632) [@josiahmanson] - Examples: Added SDL2+DirectX11 example application. (#2632, #2612, #2482) [@vincenthamm] diff --git a/imgui.h b/imgui.h index 7b34c7c531823..ec4e1357c7bec 100644 --- a/imgui.h +++ b/imgui.h @@ -126,30 +126,30 @@ typedef void* ImTextureID; // User data to identify a texture (this is typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string) typedef unsigned short ImWchar; // A single U16 character for keyboard input/display. We encode them as multi bytes UTF-8 when used in strings. typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling -typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for Set*() +typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier (ImGui-side enum) typedef int ImGuiNavInput; // -> enum ImGuiNavInput_ // Enum: An input identifier for navigation typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor identifier typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling -typedef int ImDrawCornerFlags; // -> enum ImDrawCornerFlags_ // Flags: for ImDrawList::AddRect*() etc. +typedef int ImDrawCornerFlags; // -> enum ImDrawCornerFlags_ // Flags: for ImDrawList::AddRect(), AddRectFilled() etc. typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags -typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit*(), ColorPicker*() +typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc. typedef int ImGuiColumnsFlags; // -> enum ImGuiColumnsFlags_ // Flags: for Columns(), BeginColumns() typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo() -typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for *DragDrop*() +typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload() typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. -typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText*() +typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem() -typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode*(),CollapsingHeader() -typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin*() +typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader() +typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data); typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); @@ -870,7 +870,7 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, // Return true even if a popup window is normally blocking access to this item/window //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. - ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is overlapped by another window + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is obstructed or overlapped by another window ImGuiHoveredFlags_AllowWhenDisabled = 1 << 7, // Return true even if the item is disabled ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows @@ -901,7 +901,7 @@ enum ImGuiDragDropFlags_ // A primary data type enum ImGuiDataType_ { - ImGuiDataType_S8, // char + ImGuiDataType_S8, // signed char / char (with sensible compilers) ImGuiDataType_U8, // unsigned char ImGuiDataType_S16, // short ImGuiDataType_U16, // unsigned short @@ -1344,7 +1344,7 @@ struct ImGuiIO float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. void* UserData; // = NULL // Store your own data for retrieval by callbacks. - ImFontAtlas*Fonts; // // Load, rasterize and pack one or more fonts into a single texture. + ImFontAtlas*Fonts; // // Font atlas: load, rasterize and pack one or more fonts into a single texture. float FontGlobalScale; // = 1.0f // Global scale all fonts bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. diff --git a/misc/fonts/binary_to_compressed_c.cpp b/misc/fonts/binary_to_compressed_c.cpp index 3fde3d9591451..4d3522d476a82 100644 --- a/misc/fonts/binary_to_compressed_c.cpp +++ b/misc/fonts/binary_to_compressed_c.cpp @@ -48,12 +48,15 @@ int main(int argc, char** argv) else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; } else { - printf("Unknown argument: '%s'\n", argv[argn]); + fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]); return 1; } } - return binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression) ? 0 : 1; + bool ret = binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression); + if (!ret) + fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]); + return ret ? 0 : 1; } char Encode85Byte(unsigned int x) From 3436132d4bca81300fca49031cb6bd6dced09335 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jul 2019 17:20:39 +0200 Subject: [PATCH 025/200] Combo: Hide arrow when there's not enough space even for the square button. + Various todo items. --- docs/CHANGELOG.txt | 1 + docs/README.md | 1 + docs/TODO.txt | 10 ++++++---- imgui_widgets.cpp | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2d507bfeb6d26..844a3ddd0d199 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,7 @@ Other Changes: would be disabled if ImGuiWindowFlags_NoScrollbar was set on the child window, which is not the case any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). - Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. +- Combo: Hide arrow when there's not enough space even for the square button. - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/docs/README.md b/docs/README.md index 241eaadd457d3..c5abf581705b1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -137,6 +137,7 @@ Frameworks: - Platform: GLFW, SDL, Win32, OSX, GLUT: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Framework: Allegro 5, Emscripten, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) +- bsf: [bsfimgui](https://github.com/pgruenbacher/bsfImgui) - Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) - Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551) - Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI) diff --git a/docs/TODO.txt b/docs/TODO.txt index d5291373c4417..d0f2e84e66704 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -33,12 +33,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window/child: allow SetNextWindowContentSize() to work on child windows. - window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero. - window/tab: add a way to signify that a window or docked window requires attention (e.g. blinking title bar). + ! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose lots of issues (#2424, #1463) - scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse) - scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet. - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro) - scrolling/style: shadows on scrollable areas to denote that there is more contents - - drawdata: make it easy to clone (or swap?) a ImDrawData so user can easily save that data if they use threaded rendering. + - drawdata: make it easy to clone (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (e.g. #2646) ! drawlist: add calctextsize func to facilitate consistent code from user pov (currently need to use ImGui or ImFont alternatives!) - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack. - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). @@ -205,23 +206,24 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - shortcuts: programmatically access shortcuts "Focus("&Save")) - menus: menu-bar: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin) - menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer. + - menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot). - text: selectable text (for copy) as a generic feature (ItemFlags?) - text: proper alignment options in imgui_internal.h - - text wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #? - text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT - text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not - text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use? + - text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width + - text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - - tree node / optimization: avoid formatting when clipped. - - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling. - tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings? - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits? - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - tree node: tweak color scheme to distinguish headers from selected tree node (#581) - tree node: leaf/non-leaf highlight mismatch. - tree node: _NoIndentOnOpen flag? would require to store a per-depth bit mask to store info for pop (or whatever is cheaper) + - tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height?) - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8af935c5b8bfb..e59836c19b61f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1432,7 +1432,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right); - RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down); + if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x) + RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); } RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) From e66799f79a14a533d7b7adb937fc700f6c1168fa Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jul 2019 11:54:22 +0200 Subject: [PATCH 026/200] Prefixed internal structs exposed in imgui.h with a fully qualified name to facilitate auto-generation with cimgui. --- imgui.cpp | 62 +++++++++++++++++++++++++++---------------------------- imgui.h | 36 ++++++++++++++++---------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4d7ff31122dad..6ec5e241b52e2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1923,15 +1923,15 @@ ImU32 ImGui::GetColorU32(ImU32 col) //----------------------------------------------------------------------------- // std::lower_bound but without the bullshit -static ImGuiStorage::Pair* LowerBound(ImVector& data, ImGuiID key) +static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector& data, ImGuiID key) { - ImGuiStorage::Pair* first = data.Data; - ImGuiStorage::Pair* last = data.Data + data.Size; + ImGuiStorage::ImGuiStoragePair* first = data.Data; + ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size; size_t count = (size_t)(last - first); while (count > 0) { size_t count2 = count >> 1; - ImGuiStorage::Pair* mid = first + count2; + ImGuiStorage::ImGuiStoragePair* mid = first + count2; if (mid->key < key) { first = ++mid; @@ -1953,18 +1953,18 @@ void ImGuiStorage::BuildSortByKey() static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs) { // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. - if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1; - if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1; + if (((const ImGuiStoragePair*)lhs)->key > ((const ImGuiStoragePair*)rhs)->key) return +1; + if (((const ImGuiStoragePair*)lhs)->key < ((const ImGuiStoragePair*)rhs)->key) return -1; return 0; } }; if (Data.Size > 1) - ImQsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID); + ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), StaticFunc::PairCompareByID); } int ImGuiStorage::GetInt(ImGuiID key, int default_val) const { - ImGuiStorage::Pair* it = LowerBound(const_cast&>(Data), key); + ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); if (it == Data.end() || it->key != key) return default_val; return it->val_i; @@ -1977,7 +1977,7 @@ bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const { - ImGuiStorage::Pair* it = LowerBound(const_cast&>(Data), key); + ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); if (it == Data.end() || it->key != key) return default_val; return it->val_f; @@ -1985,7 +1985,7 @@ float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const void* ImGuiStorage::GetVoidPtr(ImGuiID key) const { - ImGuiStorage::Pair* it = LowerBound(const_cast&>(Data), key); + ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); if (it == Data.end() || it->key != key) return NULL; return it->val_p; @@ -1994,9 +1994,9 @@ void* ImGuiStorage::GetVoidPtr(ImGuiID key) const // References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) { - ImGuiStorage::Pair* it = LowerBound(Data, key); + ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); + it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_i; } @@ -2007,27 +2007,27 @@ bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { - ImGuiStorage::Pair* it = LowerBound(Data, key); + ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); + it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_f; } void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) { - ImGuiStorage::Pair* it = LowerBound(Data, key); + ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); + it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_p; } // FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) void ImGuiStorage::SetInt(ImGuiID key, int val) { - ImGuiStorage::Pair* it = LowerBound(Data, key); + ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) { - Data.insert(it, Pair(key, val)); + Data.insert(it, ImGuiStoragePair(key, val)); return; } it->val_i = val; @@ -2040,10 +2040,10 @@ void ImGuiStorage::SetBool(ImGuiID key, bool val) void ImGuiStorage::SetFloat(ImGuiID key, float val) { - ImGuiStorage::Pair* it = LowerBound(Data, key); + ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) { - Data.insert(it, Pair(key, val)); + Data.insert(it, ImGuiStoragePair(key, val)); return; } it->val_f = val; @@ -2051,10 +2051,10 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val) void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) { - ImGuiStorage::Pair* it = LowerBound(Data, key); + ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) { - Data.insert(it, Pair(key, val)); + Data.insert(it, ImGuiStoragePair(key, val)); return; } it->val_p = val; @@ -2095,7 +2095,7 @@ bool ImGuiTextFilter::Draw(const char* label, float width) return value_changed; } -void ImGuiTextFilter::TextRange::split(char separator, ImVector* out) const +void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector* out) const { out->resize(0); const char* wb = b; @@ -2104,25 +2104,25 @@ void ImGuiTextFilter::TextRange::split(char separator, ImVector* out) { if (*we == separator) { - out->push_back(TextRange(wb, we)); + out->push_back(ImGuiTextRange(wb, we)); wb = we + 1; } we++; } if (wb != we) - out->push_back(TextRange(wb, we)); + out->push_back(ImGuiTextRange(wb, we)); } void ImGuiTextFilter::Build() { Filters.resize(0); - TextRange input_range(InputBuf, InputBuf+strlen(InputBuf)); + ImGuiTextRange input_range(InputBuf, InputBuf+strlen(InputBuf)); input_range.split(',', &Filters); CountGrep = 0; for (int i = 0; i != Filters.Size; i++) { - TextRange& f = Filters[i]; + ImGuiTextRange& f = Filters[i]; while (f.b < f.e && ImCharIsBlankA(f.b[0])) f.b++; while (f.e > f.b && ImCharIsBlankA(f.e[-1])) @@ -2144,19 +2144,19 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const for (int i = 0; i != Filters.Size; i++) { - const TextRange& f = Filters[i]; + const ImGuiTextRange& f = Filters[i]; if (f.empty()) continue; if (f.b[0] == '-') { // Subtract - if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL) + if (ImStristr(text, text_end, f.b + 1, f.e) != NULL) return false; } else { // Grep - if (ImStristr(text, text_end, f.begin(), f.end()) != NULL) + if (ImStristr(text, text_end, f.b, f.e) != NULL) return true; } } @@ -10102,7 +10102,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) NodeColumns(&window->ColumnsStorage[n]); ImGui::TreePop(); } - ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); + ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.size_in_bytes()); ImGui::TreePop(); } diff --git a/imgui.h b/imgui.h index ec4e1357c7bec..a1ee79584a47d 100644 --- a/imgui.h +++ b/imgui.h @@ -1591,21 +1591,19 @@ struct ImGuiTextFilter bool IsActive() const { return !Filters.empty(); } // [Internal] - struct TextRange + struct ImGuiTextRange { - const char* b; - const char* e; - - TextRange() { b = e = NULL; } - TextRange(const char* _b, const char* _e) { b = _b; e = _e; } - const char* begin() const { return b; } - const char* end () const { return e; } - bool empty() const { return b == e; } - IMGUI_API void split(char separator, ImVector* out) const; + const char* b; + const char* e; + + ImGuiTextRange() { b = e = NULL; } + ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; } + bool empty() const { return b == e; } + IMGUI_API void split(char separator, ImVector* out) const; }; - char InputBuf[256]; - ImVector Filters; - int CountGrep; + char InputBuf[256]; + ImVectorFilters; + int CountGrep; }; // Helper: Growable text buffer for logging/accumulating text @@ -1639,15 +1637,17 @@ struct ImGuiTextBuffer // Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. struct ImGuiStorage { - struct Pair + // [Internal] + struct ImGuiStoragePair { ImGuiID key; union { int val_i; float val_f; void* val_p; }; - Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } - Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } - Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } + ImGuiStoragePair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } + ImGuiStoragePair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } + ImGuiStoragePair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } }; - ImVector Data; + + ImVector Data; // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) // - Set***() functions find pair, insertion on demand if missing. From d52c6316c8280aac4df66a1380984121fa9d46da Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jul 2019 11:58:46 +0200 Subject: [PATCH 027/200] Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Keep redirection typedef (will obsolete). --- docs/CHANGELOG.txt | 1 + imgui.cpp | 1 + imgui.h | 39 +++++++++++++++++++++------------------ imgui_draw.cpp | 14 +++++++------- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 844a3ddd0d199..9bf1fd6321f7b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -40,6 +40,7 @@ Breaking Changes: - IMGUI_ONCE_UPON_A_FRAME macro. If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out the new names and equivalent. +- Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Keep redirection typedef (will obsolete). Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). diff --git a/imgui.cpp b/imgui.cpp index 6ec5e241b52e2..f0c7caf1d4ff0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -369,6 +369,7 @@ CODE When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Keep redirection typedef (will obsolete). - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names. - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering. diff --git a/imgui.h b/imgui.h index a1ee79584a47d..3aa10abf41e83 100644 --- a/imgui.h +++ b/imgui.h @@ -2027,6 +2027,19 @@ struct ImFontGlyphRangesBuilder IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges }; +// See ImFontAtlas::AddCustomRectXXX functions. +struct ImFontAtlasCustomRect +{ + unsigned int ID; // Input // User ID. Use <0x10000 to map into a font glyph, >=0x10000 for other/internal/custom texture data. + unsigned short Width, Height; // Input // Desired rectangle dimension + unsigned short X, Y; // Output // Packed position in Atlas + float GlyphAdvanceX; // Input // For custom font glyphs only (ID<0x10000): glyph xadvance + ImVec2 GlyphOffset; // Input // For custom font glyphs only (ID<0x10000): glyph display offset + ImFont* Font; // Input // For custom font glyphs only (ID<0x10000): target font + ImFontAtlasCustomRect() { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0,0); Font = NULL; } + bool IsPacked() const { return X != 0xFFFF; } +}; + enum ImFontAtlasFlags_ { ImFontAtlasFlags_None = 0, @@ -2091,7 +2104,7 @@ struct ImFontAtlas IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters - IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietname characters + IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietnamese characters //------------------------------------------- // [BETA] Custom Rectangles/Glyphs API @@ -2102,24 +2115,13 @@ struct ImFontAtlas // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), // so you can render e.g. custom colorful icons and use them as regular glyphs. // Read misc/fonts/README.txt for more details about using colorful icons. - struct CustomRect - { - unsigned int ID; // Input // User ID. Use <0x10000 to map into a font glyph, >=0x10000 for other/internal/custom texture data. - unsigned short Width, Height; // Input // Desired rectangle dimension - unsigned short X, Y; // Output // Packed position in Atlas - float GlyphAdvanceX; // Input // For custom font glyphs only (ID<0x10000): glyph xadvance - ImVec2 GlyphOffset; // Input // For custom font glyphs only (ID<0x10000): glyph display offset - ImFont* Font; // Input // For custom font glyphs only (ID<0x10000): target font - CustomRect() { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0,0); Font = NULL; } - bool IsPacked() const { return X != 0xFFFF; } - }; - IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList - IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font. - const CustomRect* GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; } + IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList + IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font. + const ImFontAtlasCustomRect*GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; } // [Internal] - IMGUI_API void CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); - IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); + IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); + IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); //------------------------------------------- // Members @@ -2140,11 +2142,12 @@ struct ImFontAtlas ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight) ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. - ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. + ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. ImVector ConfigData; // Internal data int CustomRectIds[1]; // Identifiers of custom texture rectangle used by ImFontAtlas/ImDrawList #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+ typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ #endif }; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 51ff2cd9da859..e7c5e82eea006 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1720,7 +1720,7 @@ int ImFontAtlas::AddCustomRectRegular(unsigned int id, int width, int height) IM_ASSERT(id >= 0x10000); IM_ASSERT(width > 0 && width <= 0xFFFF); IM_ASSERT(height > 0 && height <= 0xFFFF); - CustomRect r; + ImFontAtlasCustomRect r; r.ID = id; r.Width = (unsigned short)width; r.Height = (unsigned short)height; @@ -1733,7 +1733,7 @@ int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int IM_ASSERT(font != NULL); IM_ASSERT(width > 0 && width <= 0xFFFF); IM_ASSERT(height > 0 && height <= 0xFFFF); - CustomRect r; + ImFontAtlasCustomRect r; r.ID = id; r.Width = (unsigned short)width; r.Height = (unsigned short)height; @@ -1744,7 +1744,7 @@ int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int return CustomRects.Size - 1; // Return index } -void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) +void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) { IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed @@ -1760,7 +1760,7 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou return false; IM_ASSERT(CustomRectIds[0] != -1); - ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]]; + ImFontAtlasCustomRect& r = CustomRects[CustomRectIds[0]]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y); ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; @@ -2119,7 +2119,7 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa stbrp_context* pack_context = (stbrp_context*)stbrp_context_opaque; IM_ASSERT(pack_context != NULL); - ImVector& user_rects = atlas->CustomRects; + ImVector& user_rects = atlas->CustomRects; IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong. ImVector pack_rects; @@ -2145,7 +2145,7 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) { IM_ASSERT(atlas->CustomRectIds[0] >= 0); IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); - ImFontAtlas::CustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]]; + ImFontAtlasCustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); IM_ASSERT(r.IsPacked()); @@ -2180,7 +2180,7 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) // Register custom rectangle glyphs for (int i = 0; i < atlas->CustomRects.Size; i++) { - const ImFontAtlas::CustomRect& r = atlas->CustomRects[i]; + const ImFontAtlasCustomRect& r = atlas->CustomRects[i]; if (r.Font == NULL || r.ID > 0x10000) continue; From 71d20abbc34342ef6e6fc8c2824b25fa16743858 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jul 2019 13:33:24 +0200 Subject: [PATCH 028/200] Settings: Minor optimization to reduce calls in SettingsHandlerWindow_WriteAll. --- imgui.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f0c7caf1d4ff0..22a3ec454726f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9558,6 +9558,8 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) ImGuiContext& g = *GImGui; g.SettingsWindows.push_back(ImGuiWindowSettings()); ImGuiWindowSettings* settings = &g.SettingsWindows.back(); + if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() + name = p; settings->Name = ImStrdup(name); settings->ID = ImHashStr(name); return settings; @@ -9743,10 +9745,7 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl const ImGuiWindowSettings* settings = &g.SettingsWindows[i]; if (settings->Pos.x == FLT_MAX) continue; - const char* name = settings->Name; - if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() - name = p; - buf->appendf("[%s][%s]\n", handler->TypeName, name); + buf->appendf("[%s][%s]\n", handler->TypeName, settings->Name); buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y); buf->appendf("Collapsed=%d\n", settings->Collapsed); From e461e7bc7af9cb4f7eab21949fad356b9983bae1 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 14 Jul 2019 12:28:42 -0700 Subject: [PATCH 029/200] Moved ImGuiColumnsFlags erroneously forward declared in imgui.h + demo bit. --- imgui.h | 1 - imgui_demo.cpp | 1 + imgui_internal.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 3aa10abf41e83..72c19259eb604 100644 --- a/imgui.h +++ b/imgui.h @@ -138,7 +138,6 @@ typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: f typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc. -typedef int ImGuiColumnsFlags; // -> enum ImGuiColumnsFlags_ // Flags: for Columns(), BeginColumns() typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo() typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a8d72f2ef8468..81c1ba275950e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2606,6 +2606,7 @@ static void ShowDemoWindowColumns() ImGui::Separator(); ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i); ImGui::Text("Width %.2f", ImGui::GetColumnWidth()); + ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x); ImGui::Text("Offset %.2f", ImGui::GetColumnOffset()); ImGui::Text("Long text that is likely to clip"); ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f)); diff --git a/imgui_internal.h b/imgui_internal.h index 3b96116e8113a..cb5c40864c209 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -91,6 +91,7 @@ struct ImGuiWindowSettings; // Storage for window settings stored in .in // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for ButtonEx(), ButtonBehavior() +typedef int ImGuiColumnsFlags; // -> enum ImGuiColumnsFlags_ // Flags: BeginColumns() typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior() typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag() typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags From 7a9d32acee87eb352fcd96e7a356608f6d32a764 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 14 Jul 2019 18:01:06 -0700 Subject: [PATCH 030/200] Fixed unnecessary test in UpdateMouseWheel() (thanks PVS). TreeNodeBehavior: avoid computing bg_col for non-framed non-active tree nodes. Comments, binaries update, minor typos. --- docs/CHANGELOG.txt | 10 +++++----- docs/README.md | 2 +- imgui.cpp | 10 +++++----- imgui.h | 2 +- imgui_widgets.cpp | 3 ++- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9bf1fd6321f7b..036f481e75b41 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,8 +39,8 @@ Breaking Changes: - IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow() functions. - IMGUI_ONCE_UPON_A_FRAME macro. If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out - the new names and equivalent. -- Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Keep redirection typedef (will obsolete). + the new names or equivalent features. +- Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). @@ -243,7 +243,7 @@ Breaking Changes: - Renamed ColorEdit/ColorPicker's ImGuiColorEditFlags_RGB/_HSV/_HEX flags to respectively ImGuiColorEditFlags_DisplayRGB/_DisplayHSV/_DisplayHex. This is because the addition of new flag ImGuiColorEditFlags_InputHSV makes the earlier one ambiguous. - Keep redirection enum values (will obsolete). (#2384) [@haldean] + Kept redirection enum values (will obsolete). (#2384) [@haldean] - Renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete). (#2391) Other Changes: @@ -388,7 +388,7 @@ Breaking Changes: side-effect because the window would have ID zero. In particular it is causing problems in viewport/docking branches. - Renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges and removed its [Beta] mark. The addition of new configuration options in the Docking branch is pushing for a little reorganization of those names. -- Renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Keep redirection typedef (will obsolete). +- Renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete). Other Changes: - Added BETA api for Tab Bar/Tabs widgets: (#261, #351) @@ -1129,7 +1129,7 @@ Breaking Changes: - Removed `IsItemRectHovered()`, `IsWindowRectHovered()` recently introduced in 1.51 which were merely the more consistent/correct names for the above functions which are now obsolete anyway. (#1382) - Changed `IsWindowHovered()` default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. (#1382) - Renamed imconfig.h's `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS` to `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS` for consistency. -- Renamed ImFont::Glyph to ImFontGlyph. Keep redirection typedef (will obsolete). +- Renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete). Other Changes: diff --git a/docs/README.md b/docs/README.md index c5abf581705b1..902b615ada28f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -102,7 +102,7 @@ Demo Binaries ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20190219.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190219.zip) (Windows binaries, Dear ImGui 1.68 built 2019/02/19, master branch, 5 executables) +- [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, Dear ImGui 1.72 WIP built 2019/07/15, master branch, 5 executables) The demo applications are unfortunately not yet DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. diff --git a/imgui.cpp b/imgui.cpp index 22a3ec454726f..d82e8b536a644 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6,7 +6,7 @@ // Get latest version at https://github.com/ocornut/imgui // Releases change-log at https://github.com/ocornut/imgui/releases // Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started -// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 +// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2529 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). @@ -369,7 +369,7 @@ CODE When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Keep redirection typedef (will obsolete). + - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names. - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering. @@ -384,7 +384,7 @@ CODE - 2019/02/14 (1.68) - made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). If for some reason your time step calculation gives you a zero value, replace it with a dummy small value! - 2019/02/01 (1.68) - removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already). - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead! - - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Keep redirection typedef (will obsolete). + - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete). - 2018/12/20 (1.67) - made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable side-effects. - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags. - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files. @@ -457,7 +457,7 @@ CODE IsMouseHoveringWindow() --> IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) [weird, old behavior] - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead! - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete). - - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Keep redirection typedef (will obsolete). + - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete). - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete). - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)". - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)! @@ -3453,7 +3453,7 @@ void ImGui::UpdateMouseWheel() // Zoom / Scale window // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned. - if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling && !g.HoveredWindow->Collapsed) + if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling) { ImGuiWindow* window = g.HoveredWindow; const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); diff --git a/imgui.h b/imgui.h index 72c19259eb604..03cb9d36567aa 100644 --- a/imgui.h +++ b/imgui.h @@ -1040,7 +1040,7 @@ enum ImGuiCol_ ImGuiCol_Button, ImGuiCol_ButtonHovered, ImGuiCol_ButtonActive, - ImGuiCol_Header, + ImGuiCol_Header, // Header* colors are used for CollapsingHeader, TreeNode, Selectable, MenuItem ImGuiCol_HeaderHovered, ImGuiCol_HeaderActive, ImGuiCol_Separator, diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e59836c19b61f..20ae82e537874 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5238,13 +5238,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render - const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); const ImU32 text_col = GetColorU32(ImGuiCol_Text); const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y); ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin; if (display_frame) { // Framed type + const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); RenderNavHighlight(frame_bb, id, nav_highlight_flags); RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); @@ -5269,6 +5269,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Unframed typed for tree nodes if (hovered || selected) { + const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); RenderNavHighlight(frame_bb, id, nav_highlight_flags); } From 3d07c7cbe4db652a775e2a0410c59158f164b6bf Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jul 2019 17:56:20 -0700 Subject: [PATCH 031/200] TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 036f481e75b41..9b6d6809ccc98 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,7 @@ Other Changes: any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). - Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Combo: Hide arrow when there's not enough space even for the square button. +- TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 20ae82e537874..6ef4ef26f2834 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6347,7 +6347,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG window->DC.CursorPos.x = tab_bar->BarRect.Min.x; // Draw separator - const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_Tab); + const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive); const float y = tab_bar->BarRect.Max.y - 1.0f; { const float separator_min_x = tab_bar->BarRect.Min.x - ImFloor(window->WindowPadding.x * 0.5f); From a35f42f1230d1e18885c3fc3a45c5448858bc85d Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jul 2019 18:14:14 -0700 Subject: [PATCH 032/200] Removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). (#581, #324) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 1 + imgui.h | 5 +++-- imgui_demo.cpp | 2 +- imgui_widgets.cpp | 7 ------- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9b6d6809ccc98..382b2ee1c69ab 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,8 @@ Breaking Changes: If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out the new names or equivalent features. - Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). +- Removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). + Kept redirection function (will obsolete). (#581, #324) Other Changes: - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). diff --git a/imgui.cpp b/imgui.cpp index d82e8b536a644..ac96259e6621d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -369,6 +369,7 @@ CODE When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names. - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have diff --git a/imgui.h b/imgui.h index 03cb9d36567aa..c5bcb213fe84b 100644 --- a/imgui.h +++ b/imgui.h @@ -496,7 +496,6 @@ namespace ImGui IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); // ~ Unindent()+PopId() - IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header @@ -1531,8 +1530,10 @@ struct ImGuiPayload #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.72 (from July 2019) + static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); } // OBSOLETED in 1.71 (from June 2019) - static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } + static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } // OBSOLETED in 1.70 (from May 2019) static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; } // OBSOLETED in 1.69 (from Mar 2019) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 81c1ba275950e..0db2f1dbd296c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -628,7 +628,7 @@ static void ShowDemoWindowWidgets() { // Items 3..5 are Tree Leaves // The only reason we use TreeNode at all is to allow selection of the leaf. - // Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). + // Otherwise we can use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text(). node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); if (ImGui::IsItemClicked()) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6ef4ef26f2834..e38100229ec72 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4990,7 +4990,6 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl // - TreeNodeBehavior() [Internal] // - TreePush() // - TreePop() -// - TreeAdvanceToLabelPos() // - GetTreeNodeToLabelSpacing() // - SetNextItemOpen() // - CollapsingHeader() @@ -5332,12 +5331,6 @@ void ImGui::TreePop() PopID(); } -void ImGui::TreeAdvanceToLabelPos() -{ - ImGuiContext& g = *GImGui; - g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing(); -} - // Horizontal distance preceding label when using TreeNode() or Bullet() float ImGui::GetTreeNodeToLabelSpacing() { From e6a286b3a567eb1d3b032e6c412565b0ef19677a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 16 Jul 2019 16:43:21 -0700 Subject: [PATCH 033/200] Style: Added style.ColorButtonButton (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. --- docs/CHANGELOG.txt | 4 +++- imgui.cpp | 1 + imgui.h | 1 + imgui_demo.cpp | 3 ++- imgui_widgets.cpp | 21 +++++++++++++-------- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 382b2ee1c69ab..e6cf69ebe61f5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,7 +41,7 @@ Breaking Changes: If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out the new names or equivalent features. - Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). -- Removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). +- Removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). (#581, #324) Other Changes: @@ -58,6 +58,8 @@ Other Changes: of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. +- Style: Added style.ColorButtonButton (left/right, defaults to ImGuiDir_Right) to move the color button + of ColorEdit3/ColorEdit4 functions to either side of the inputs. - Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow(). - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between diff --git a/imgui.cpp b/imgui.cpp index ac96259e6621d..47dc25df7dcda 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1164,6 +1164,7 @@ ImGuiStyle::ImGuiStyle() GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. TabBorderSize = 0.0f; // Thickness of border around tabs. + ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text when button is larger than text. DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows. diff --git a/imgui.h b/imgui.h index c5bcb213fe84b..0ffde48094a90 100644 --- a/imgui.h +++ b/imgui.h @@ -1301,6 +1301,7 @@ struct ImGuiStyle float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. float TabBorderSize; // Thickness of border around tabs. + ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). ImVec2 SelectableTextAlign; // Alignment of selectable text when selectable is larger than text. Defaults to (0.0f, 0.0f) (top-left aligned). ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0db2f1dbd296c..4d08a257e7bdc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1145,7 +1145,7 @@ static void ShowDemoWindowWidgets() static ImVec4 backup_color; bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); - ImGui::SameLine(); + ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); open_popup |= ImGui::Button("Palette"); if (open_popup) { @@ -3151,6 +3151,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::Text("Alignment"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); ImGui::Combo("WindowMenuButtonPosition", (int*)&style.WindowMenuButtonPosition, "Left\0Right\0"); + ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content."); ImGui::Text("Safe Area Padding"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e38100229ec72..03a2c5083300a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4137,8 +4137,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); - const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); - const float w_items_all = CalcItemWidth() - w_extra; + const float w_full = CalcItemWidth(); + const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); + const float w_inputs = w_full - w_button; const char* label_display_end = FindRenderedTextEnd(label); g.NextItemData.ClearFlags(); @@ -4182,11 +4183,15 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag bool value_changed = false; bool value_changed_as_float = false; + const ImVec2 pos = window->DC.CursorPos; + const float inputs_offset_x = (style.ColorButtonPosition == ImGuiDir_Left) ? w_button : 0.0f; + window->DC.CursorPos.x = pos.x + inputs_offset_x; + if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) { // RGB/HSV 0..255 Sliders - const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + const float w_item_one = ImMax(1.0f, (float)(int)((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; @@ -4230,7 +4235,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255)); else ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255)); - SetNextItemWidth(w_items_all); + SetNextItemWidth(w_inputs); if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) { value_changed = true; @@ -4250,8 +4255,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiWindow* picker_active_window = NULL; if (!(flags & ImGuiColorEditFlags_NoSmallPreview)) { - if (!(flags & ImGuiColorEditFlags_NoInputs)) - SameLine(0, style.ItemInnerSpacing.x); + const float button_offset_x = ((flags & ImGuiColorEditFlags_NoInputs) || (style.ColorButtonPosition == ImGuiDir_Left)) ? 0.0f : w_inputs + style.ItemInnerSpacing.x; + window->DC.CursorPos = ImVec2(pos.x + button_offset_x, pos.y); const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f); if (ColorButton("##ColorButton", col_v4, flags)) @@ -4285,7 +4290,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) { - SameLine(0, style.ItemInnerSpacing.x); + window->DC.CursorPos = ImVec2(pos.x + w_full + style.ItemInnerSpacing.x, pos.y + style.FramePadding.y); TextEx(label, label_display_end); } From 130b44994e31d4b0b2cc8c87597a9002e4765c74 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 16 Jul 2019 18:25:49 -0700 Subject: [PATCH 034/200] Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger within the item code. The tool calls IM_DEBUG_BREAK() which can be redefined in imconfig.h if needed. --- docs/CHANGELOG.txt | 2 ++ imconfig.h | 5 +++++ imgui.cpp | 39 ++++++++++++++++++++++++++++++++++++--- imgui_internal.h | 21 +++++++++++++++++++-- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e6cf69ebe61f5..3167c5561ffe3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,8 @@ Other Changes: - Style: Added style.ColorButtonButton (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. - Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow(). +- Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger + within the item code. The tool calls IM_DEBUG_BREAK() which can be redefined in imconfig.h if needed. - ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot] - ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between channel 0 and 1. (#2624) diff --git a/imconfig.h b/imconfig.h index 5d9caecd09c56..16f8c82798fea 100644 --- a/imconfig.h +++ b/imconfig.h @@ -76,6 +76,11 @@ //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); //#define ImDrawCallback MyImDrawCallback +//---- Debug Tools +// Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging. +//#define IM_DEBUG_BREAK IM_ASSERT(0) +//#define IM_DEBUG_BREAK __debugbreak() + //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. /* namespace ImGui diff --git a/imgui.cpp b/imgui.cpp index 47dc25df7dcda..bde77d2db52de 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2862,6 +2862,16 @@ void ImGui::SetHoveredID(ImGuiID id) g.HoveredIdAllowOverlap = false; if (id != 0 && g.HoveredIdPreviousFrame != id) g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; + + // [DEBUG] Item Picker tool! + // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making + // the cost of this tool near-zero. We would get slightly better call-stack if we made the test in ItemAdd() + // but that would incur a slightly higher cost and may require us to hide this feature behind a define. + if (id != 0 && id == g.DebugBreakItemId) + { + IM_DEBUG_BREAK(); + g.DebugBreakItemId = 0; + } } ImGuiID ImGui::GetHoveredID() @@ -10180,6 +10190,28 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode("Tools")) { + static bool picking_enabled = false; + if (ImGui::Button("Item Picker..")) + picking_enabled = true; + if (picking_enabled) + { + const ImGuiID hovered_id = g.HoveredIdPreviousFrame; + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) + picking_enabled = false; + if (ImGui::IsMouseClicked(0) && hovered_id) + { + g.DebugBreakItemId = hovered_id; + picking_enabled = false; + } + ImGui::SetNextWindowBgAlpha(0.5f); + ImGui::BeginTooltip(); + ImGui::Text("HoveredId: 0x%08X", hovered_id); + ImGui::Text("Press ESC to abort picking."); + ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); + ImGui::EndTooltip(); + } + ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); ImGui::Checkbox("Show windows rectangles", &show_windows_rects); ImGui::SameLine(); @@ -10225,10 +10257,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImGui::End(); } + #else -void ImGui::ShowMetricsWindow(bool*) -{ -} + +void ImGui::ShowMetricsWindow(bool*) { } + #endif //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index cb5c40864c209..d615a942077d8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -401,7 +401,7 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_Deactivated = 1 << 5 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. #ifdef IMGUI_ENABLE_TEST_ENGINE - , // [imgui-test only] + , // [imgui_tests only] ImGuiItemStatusFlags_Openable = 1 << 10, // ImGuiItemStatusFlags_Opened = 1 << 11, // ImGuiItemStatusFlags_Checkable = 1 << 12, // @@ -1028,6 +1028,9 @@ struct ImGuiContext int LogDepthToExpand; int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. + // Debug Tools + ImGuiID DebugBreakItemId; + // Misc float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. int FramerateSecPerFrameIdx; @@ -1153,6 +1156,8 @@ struct ImGuiContext LogDepthRef = 0; LogDepthToExpand = LogDepthToExpandDefault = 2; + DebugBreakItemId = 0; + memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; FramerateSecPerFrameAccum = 0.0f; @@ -1662,7 +1667,19 @@ IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); -// Test engine hooks (imgui-test) +// Debug Tools +// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. +#ifndef IM_DEBUG_BREAK +#if defined(__clang__) +#define IM_DEBUG_BREAK() __builtin_debugtrap() +#elif defined (_MSC_VER) +#define IM_DEBUG_BREAK() __debugbreak() +#else +#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! +#endif +#endif // #ifndef IM_DEBUG_BREAK + +// Test Engine Hooks (imgui_tests) //#define IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE extern void ImGuiTestEngineHook_PreNewFrame(ImGuiContext* ctx); From ea79992d9add90f5e6d23b7b7941aceb20734bd5 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jul 2019 09:59:10 -0700 Subject: [PATCH 035/200] Fixed old SetWindowFontScale() api value from not being inherited by child window. Added comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). + Added missing IMGUI_API marker to the EmptyString storage used by ImGuiTextBuffer. (#2672) --- docs/CHANGELOG.txt | 4 +++- imgui.h | 4 ++-- imgui_demo.cpp | 3 ++- imgui_internal.h | 14 +++++++------- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3167c5561ffe3..c7a881644eb1f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,8 @@ Other Changes: Also still case if ImGuiWindowFlags_NoScrollWithMouse is set (not new), but previously the forwarding would be disabled if ImGuiWindowFlags_NoScrollbar was set on the child window, which is not the case any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). +- Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added + comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). - Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Combo: Hide arrow when there's not enough space even for the square button. - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). @@ -58,7 +60,7 @@ Other Changes: of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. -- Style: Added style.ColorButtonButton (left/right, defaults to ImGuiDir_Right) to move the color button +- Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. - Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow(). - Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger diff --git a/imgui.h b/imgui.h index 0ffde48094a90..a81296fd6c320 100644 --- a/imgui.h +++ b/imgui.h @@ -280,7 +280,7 @@ namespace ImGui IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). - IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows + IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state @@ -1612,7 +1612,7 @@ struct ImGuiTextFilter struct ImGuiTextBuffer { ImVector Buf; - static char EmptyString[1]; + IMGUI_API static char EmptyString[1]; ImGuiTextBuffer() { } inline char operator[](int i) { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4d08a257e7bdc..e1c07dcf22b9d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3295,8 +3295,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::TreePop(); } + HelpMarker("Those are old settings provided for convenience.\nHowever, the _correct_ way of scaling your UI is currently to reload your font at the designed size, rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure."); static float window_scale = 1.0f; - if (ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.2f")) // scale only this window + if (ImGui::DragFloat("window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.2f")) // scale only this window ImGui::SetWindowFontScale(window_scale); ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.2f"); // scale everything ImGui::PopItemWidth(); diff --git a/imgui_internal.h b/imgui_internal.h index d615a942077d8..33f71139a6ba6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1317,7 +1317,7 @@ struct IMGUI_API ImGuiWindow ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; ImVector ColumnsStorage; - float FontWindowScale; // User scale multiplier per-window + float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale() int SettingsIdx; // Index into SettingsWindow[] (indices are always valid as we only grow the array from the back) ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) @@ -1344,12 +1344,12 @@ struct IMGUI_API ImGuiWindow ImGuiID GetIDFromRectangle(const ImRect& r_abs); // We don't use g.FontSize because the window may be != g.CurrentWidow. - ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } - float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } - float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; } - ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } - float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } - ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } + ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } + float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } + float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; } + ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } + float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; } + ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } }; // Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data. From 1f3feb481e936c821b07ad0b0c91dbd0417133b9 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jul 2019 14:02:45 -0700 Subject: [PATCH 036/200] Internals: Refactor: Moved all Columns code from imgui.cpp to imgui_widgets.cpp (#125) Also moved NextColumn between BeginColumn and NextColumn which makes it easier to work on that code. --- imgui.cpp | 391 +------------------------------------------- imgui_internal.h | 2 + imgui_widgets.cpp | 407 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+), 390 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bde77d2db52de..659239df5ad40 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -75,7 +75,6 @@ CODE // [SECTION] TOOLTIPS // [SECTION] POPUPS // [SECTION] KEYBOARD/GAMEPAD NAVIGATION -// [SECTION] COLUMNS // [SECTION] DRAG AND DROP // [SECTION] LOGGING/CAPTURING // [SECTION] SETTINGS @@ -8664,394 +8663,6 @@ void ImGui::NavUpdateWindowingList() PopStyleVar(); } -//----------------------------------------------------------------------------- -// [SECTION] COLUMNS -// In the current version, Columns are very weak. Needs to be replaced with a more full-featured system. -//----------------------------------------------------------------------------- - -void ImGui::NextColumn() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.CurrentColumns == NULL) - return; - - ImGuiContext& g = *GImGui; - ImGuiColumns* columns = window->DC.CurrentColumns; - - if (columns->Count == 1) - { - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - IM_ASSERT(columns->Current == 0); - return; - } - - PopItemWidth(); - PopClipRect(); - - columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); - if (++columns->Current < columns->Count) - { - // Columns 1+ cancel out IndentX - // FIXME-COLUMNS: Unnecessary, could be locked? - window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(columns->Current + 1); - } - else - { - // New row/line - window->DC.ColumnsOffset.x = 0.0f; - window->DrawList->ChannelsSetCurrent(1); - columns->Current = 0; - columns->LineMinY = columns->LineMaxY; - } - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - window->DC.CursorPos.y = columns->LineMinY; - window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); - window->DC.CurrLineTextBaseOffset = 0.0f; - - PushColumnClipRect(columns->Current); // FIXME-COLUMNS: Could it be an overwrite? - - // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup. - float offset_0 = GetColumnOffset(columns->Current); - float offset_1 = GetColumnOffset(columns->Current + 1); - float width = offset_1 - offset_0; - PushItemWidth(width * 0.65f); - window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; -} - -int ImGui::GetColumnIndex() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0; -} - -int ImGui::GetColumnsCount() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1; -} - -static float OffsetNormToPixels(const ImGuiColumns* columns, float offset_norm) -{ - return offset_norm * (columns->OffMaxX - columns->OffMinX); -} - -static float PixelsToOffsetNorm(const ImGuiColumns* columns, float offset) -{ - return offset / (columns->OffMaxX - columns->OffMinX); -} - -static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f; - -static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index) -{ - // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing - // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. - IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); - - float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x; - x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); - if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) - x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); - - return x; -} - -float ImGui::GetColumnOffset(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - IM_ASSERT(column_index < columns->Columns.Size); - - const float t = columns->Columns[column_index].OffsetNorm; - const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t); - return x_offset; -} - -static float GetColumnWidthEx(ImGuiColumns* columns, int column_index, bool before_resize = false) -{ - if (column_index < 0) - column_index = columns->Current; - - float offset_norm; - if (before_resize) - offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; - else - offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; - return OffsetNormToPixels(columns, offset_norm); -} - -float ImGui::GetColumnWidth(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); -} - -void ImGui::SetColumnOffset(int column_index, float offset) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - IM_ASSERT(column_index < columns->Columns.Size); - - const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); - const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; - - if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); - columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->OffMinX); - - if (preserve_width) - SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); -} - -void ImGui::SetColumnWidth(int column_index, float width) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); -} - -void ImGui::PushColumnClipRect(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumns* columns = window->DC.CurrentColumns; - if (column_index < 0) - column_index = columns->Current; - - ImGuiColumnData* column = &columns->Columns[column_index]; - PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false); -} - -// Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns) -void ImGui::PushColumnsBackground() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumns* columns = window->DC.CurrentColumns; - window->DrawList->ChannelsSetCurrent(0); - int cmd_size = window->DrawList->CmdBuffer.Size; - PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); - IM_UNUSED(cmd_size); - IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd -} - -void ImGui::PopColumnsBackground() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumns* columns = window->DC.CurrentColumns; - window->DrawList->ChannelsSetCurrent(columns->Current + 1); - PopClipRect(); -} - -ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) -{ - // We have few columns per window so for now we don't need bother much with turning this into a faster lookup. - for (int n = 0; n < window->ColumnsStorage.Size; n++) - if (window->ColumnsStorage[n].ID == id) - return &window->ColumnsStorage[n]; - - window->ColumnsStorage.push_back(ImGuiColumns()); - ImGuiColumns* columns = &window->ColumnsStorage.back(); - columns->ID = id; - return columns; -} - -ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) -{ - ImGuiWindow* window = GetCurrentWindow(); - - // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. - // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. - PushID(0x11223347 + (str_id ? 0 : columns_count)); - ImGuiID id = window->GetID(str_id ? str_id : "columns"); - PopID(); - - return id; -} - -void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - IM_ASSERT(columns_count >= 1); - IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported - - // Acquire storage for the columns set - ImGuiID id = GetColumnsID(str_id, columns_count); - ImGuiColumns* columns = FindOrCreateColumns(window, id); - IM_ASSERT(columns->ID == id); - columns->Current = 0; - columns->Count = columns_count; - columns->Flags = flags; - window->DC.CurrentColumns = columns; - - // Set state for first column - columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x; - columns->OffMaxX = ImMax(window->WorkRect.Max.x - window->Pos.x, columns->OffMinX + 1.0f); - columns->HostCursorPosY = window->DC.CursorPos.y; - columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; - columns->HostClipRect = window->ClipRect; - columns->HostWorkRect = window->WorkRect; - columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; - window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - - // Clear data if columns count changed - if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) - columns->Columns.resize(0); - - // Initialize default widths - columns->IsFirstFrame = (columns->Columns.Size == 0); - if (columns->Columns.Size == 0) - { - columns->Columns.reserve(columns_count + 1); - for (int n = 0; n < columns_count + 1; n++) - { - ImGuiColumnData column; - column.OffsetNorm = n / (float)columns_count; - columns->Columns.push_back(column); - } - } - - for (int n = 0; n < columns_count; n++) - { - // Compute clipping rectangle - ImGuiColumnData* column = &columns->Columns[n]; - float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n)); - float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); - column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - column->ClipRect.ClipWith(window->ClipRect); - } - - if (columns->Count > 1) - { - window->DrawList->ChannelsSplit(1 + columns->Count); - window->DrawList->ChannelsSetCurrent(1); - PushColumnClipRect(0); - } - - float offset_0 = GetColumnOffset(columns->Current); - float offset_1 = GetColumnOffset(columns->Current + 1); - float width = offset_1 - offset_0; - PushItemWidth(width * 0.65f); - window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; -} - -void ImGui::EndColumns() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - PopItemWidth(); - if (columns->Count > 1) - { - PopClipRect(); - window->DrawList->ChannelsMerge(); - } - - const ImGuiColumnsFlags flags = columns->Flags; - columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = columns->LineMaxY; - if (!(flags & ImGuiColumnsFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent - - // Draw columns borders and handle resize - // The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy - bool is_being_resized = false; - if (!(flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) - { - // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. - const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y); - const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y); - int dragging_column = -1; - for (int n = 1; n < columns->Count; n++) - { - ImGuiColumnData* column = &columns->Columns[n]; - float x = window->Pos.x + GetColumnOffset(n); - const ImGuiID column_id = columns->ID + ImGuiID(n); - const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH; - const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2)); - KeepAliveID(column_id); - if (IsClippedEx(column_hit_rect, column_id, false)) - continue; - - bool hovered = false, held = false; - if (!(flags & ImGuiColumnsFlags_NoResize)) - { - ButtonBehavior(column_hit_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - if (held && !(column->Flags & ImGuiColumnsFlags_NoResize)) - dragging_column = n; - } - - // Draw column - const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); - } - - // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. - if (dragging_column != -1) - { - if (!columns->IsBeingResized) - for (int n = 0; n < columns->Count + 1; n++) - columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; - columns->IsBeingResized = is_being_resized = true; - float x = GetDraggedColumnOffset(columns, dragging_column); - SetColumnOffset(dragging_column, x); - } - } - columns->IsBeingResized = is_being_resized; - - window->WorkRect = columns->HostWorkRect; - window->DC.CurrentColumns = NULL; - window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); -} - -// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] -void ImGui::Columns(int columns_count, const char* id, bool border) -{ - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - - ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); - //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior - ImGuiColumns* columns = window->DC.CurrentColumns; - if (columns != NULL && columns->Count == columns_count && columns->Flags == flags) - return; - - if (columns != NULL) - EndColumns(); - - if (columns_count != 1) - BeginColumns(id, columns_count, flags); -} - //----------------------------------------------------------------------------- // [SECTION] DRAG AND DROP @@ -10072,7 +9683,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX); for (int column_n = 0; column_n < columns->Columns.Size; column_n++) - ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm)); + ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, GetColumnOffsetFromNorm(columns, columns->Columns[column_n].OffsetNorm)); ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 33f71139a6ba6..2eacac948294e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1563,6 +1563,8 @@ namespace ImGui IMGUI_API void PopColumnsBackground(); IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count); IMGUI_API ImGuiColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id); + IMGUI_API float GetColumnOffsetFromNorm(const ImGuiColumns* columns, float offset_norm); + IMGUI_API float GetColumnNormFromOffset(const ImGuiColumns* columns, float offset); // Tab Bars IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 03a2c5083300a..0b2b2be78f676 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -24,6 +24,7 @@ Index of this file: // [SECTION] Widgets: MenuItem, BeginMenu, EndMenu, etc. // [SECTION] Widgets: BeginTabBar, EndTabBar, etc. // [SECTION] Widgets: BeginTabItem, EndTabItem, etc. +// [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc. */ @@ -7088,3 +7089,409 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, return close_button_pressed; } + + +//------------------------------------------------------------------------- +// [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc. +// In the current version, Columns are very weak. Needs to be replaced with a more full-featured system. +//------------------------------------------------------------------------- +// - GetColumnIndex() +// - GetColumnCount() +// - GetColumnOffset() +// - GetColumnWidth() +// - SetColumnOffset() +// - SetColumnWidth() +// - PushColumnClipRect() [Internal] +// - PushColumnsBackground() [Internal] +// - PopColumnsBackground() [Internal] +// - FindOrCreateColumns() [Internal] +// - GetColumnsID() [Internal] +// - BeginColumns() +// - NextColumn() +// - EndColumns() +// - Columns() +//------------------------------------------------------------------------- + +int ImGui::GetColumnIndex() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0; +} + +int ImGui::GetColumnsCount() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1; +} + +float ImGui::GetColumnOffsetFromNorm(const ImGuiColumns* columns, float offset_norm) +{ + return offset_norm * (columns->OffMaxX - columns->OffMinX); +} + +float ImGui::GetColumnNormFromOffset(const ImGuiColumns* columns, float offset) +{ + return offset / (columns->OffMaxX - columns->OffMinX); +} + +static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f; + +static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index) +{ + // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing + // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. + IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); + + float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x; + x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); + if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) + x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); + + return x; +} + +float ImGui::GetColumnOffset(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumns* columns = window->DC.CurrentColumns; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + IM_ASSERT(column_index < columns->Columns.Size); + + const float t = columns->Columns[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t); + return x_offset; +} + +static float GetColumnWidthEx(ImGuiColumns* columns, int column_index, bool before_resize = false) +{ + if (column_index < 0) + column_index = columns->Current; + + float offset_norm; + if (before_resize) + offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; + else + offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; + return ImGui::GetColumnOffsetFromNorm(columns, offset_norm); +} + +float ImGui::GetColumnWidth(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumns* columns = window->DC.CurrentColumns; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + return GetColumnOffsetFromNorm(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); +} + +void ImGui::SetColumnOffset(int column_index, float offset) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImGuiColumns* columns = window->DC.CurrentColumns; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + IM_ASSERT(column_index < columns->Columns.Size); + + const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); + const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; + + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); + columns->Columns[column_index].OffsetNorm = GetColumnNormFromOffset(columns, offset - columns->OffMinX); + + if (preserve_width) + SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); +} + +void ImGui::SetColumnWidth(int column_index, float width) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumns* columns = window->DC.CurrentColumns; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); +} + +void ImGui::PushColumnClipRect(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumns* columns = window->DC.CurrentColumns; + if (column_index < 0) + column_index = columns->Current; + + ImGuiColumnData* column = &columns->Columns[column_index]; + PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false); +} + +// Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns) +void ImGui::PushColumnsBackground() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumns* columns = window->DC.CurrentColumns; + window->DrawList->ChannelsSetCurrent(0); + int cmd_size = window->DrawList->CmdBuffer.Size; + PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); + IM_UNUSED(cmd_size); + IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd +} + +void ImGui::PopColumnsBackground() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumns* columns = window->DC.CurrentColumns; + window->DrawList->ChannelsSetCurrent(columns->Current + 1); + PopClipRect(); +} + +ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) +{ + // We have few columns per window so for now we don't need bother much with turning this into a faster lookup. + for (int n = 0; n < window->ColumnsStorage.Size; n++) + if (window->ColumnsStorage[n].ID == id) + return &window->ColumnsStorage[n]; + + window->ColumnsStorage.push_back(ImGuiColumns()); + ImGuiColumns* columns = &window->ColumnsStorage.back(); + columns->ID = id; + return columns; +} + +ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) +{ + ImGuiWindow* window = GetCurrentWindow(); + + // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. + // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. + PushID(0x11223347 + (str_id ? 0 : columns_count)); + ImGuiID id = window->GetID(str_id ? str_id : "columns"); + PopID(); + + return id; +} + +void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + IM_ASSERT(columns_count >= 1); + IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported + + // Acquire storage for the columns set + ImGuiID id = GetColumnsID(str_id, columns_count); + ImGuiColumns* columns = FindOrCreateColumns(window, id); + IM_ASSERT(columns->ID == id); + columns->Current = 0; + columns->Count = columns_count; + columns->Flags = flags; + window->DC.CurrentColumns = columns; + + // Set state for first column + columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x; + columns->OffMaxX = ImMax(window->WorkRect.Max.x - window->Pos.x, columns->OffMinX + 1.0f); + columns->HostCursorPosY = window->DC.CursorPos.y; + columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; + columns->HostClipRect = window->ClipRect; + columns->HostWorkRect = window->WorkRect; + columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; + window->DC.ColumnsOffset.x = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + + // Clear data if columns count changed + if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) + columns->Columns.resize(0); + + // Initialize default widths + columns->IsFirstFrame = (columns->Columns.Size == 0); + if (columns->Columns.Size == 0) + { + columns->Columns.reserve(columns_count + 1); + for (int n = 0; n < columns_count + 1; n++) + { + ImGuiColumnData column; + column.OffsetNorm = n / (float)columns_count; + columns->Columns.push_back(column); + } + } + + for (int n = 0; n < columns_count; n++) + { + // Compute clipping rectangle + ImGuiColumnData* column = &columns->Columns[n]; + float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n)); + float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); + column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + column->ClipRect.ClipWith(window->ClipRect); + } + + if (columns->Count > 1) + { + window->DrawList->ChannelsSplit(1 + columns->Count); + window->DrawList->ChannelsSetCurrent(1); + PushColumnClipRect(0); + } + + float offset_0 = GetColumnOffset(columns->Current); + float offset_1 = GetColumnOffset(columns->Current + 1); + float width = offset_1 - offset_0; + PushItemWidth(width * 0.65f); + window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; +} + +void ImGui::NextColumn() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems || window->DC.CurrentColumns == NULL) + return; + + ImGuiContext& g = *GImGui; + ImGuiColumns* columns = window->DC.CurrentColumns; + + if (columns->Count == 1) + { + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + IM_ASSERT(columns->Current == 0); + return; + } + PopItemWidth(); + PopClipRect(); + + columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); + if (++columns->Current < columns->Count) + { + // Columns 1+ cancel out IndentX + // FIXME-COLUMNS: Unnecessary, could be locked? + window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->Current + 1); + } + else + { + // New row/line + window->DC.ColumnsOffset.x = 0.0f; + window->DrawList->ChannelsSetCurrent(1); + columns->Current = 0; + columns->LineMinY = columns->LineMaxY; + } + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + window->DC.CursorPos.y = columns->LineMinY; + window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); + window->DC.CurrLineTextBaseOffset = 0.0f; + + PushColumnClipRect(columns->Current); // FIXME-COLUMNS: Could it be an overwrite? + + // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup. + float offset_0 = GetColumnOffset(columns->Current); + float offset_1 = GetColumnOffset(columns->Current + 1); + float width = offset_1 - offset_0; + PushItemWidth(width * 0.65f); + window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; +} + +void ImGui::EndColumns() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + ImGuiColumns* columns = window->DC.CurrentColumns; + IM_ASSERT(columns != NULL); + + PopItemWidth(); + if (columns->Count > 1) + { + PopClipRect(); + window->DrawList->ChannelsMerge(); + } + + const ImGuiColumnsFlags flags = columns->Flags; + columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->LineMaxY; + if (!(flags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent + + // Draw columns borders and handle resize + // The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy + bool is_being_resized = false; + if (!(flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + { + // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. + const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y); + const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y); + int dragging_column = -1; + for (int n = 1; n < columns->Count; n++) + { + ImGuiColumnData* column = &columns->Columns[n]; + float x = window->Pos.x + GetColumnOffset(n); + const ImGuiID column_id = columns->ID + ImGuiID(n); + const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH; + const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2)); + KeepAliveID(column_id); + if (IsClippedEx(column_hit_rect, column_id, false)) + continue; + + bool hovered = false, held = false; + if (!(flags & ImGuiColumnsFlags_NoResize)) + { + ButtonBehavior(column_hit_rect, column_id, &hovered, &held); + if (hovered || held) + g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (held && !(column->Flags & ImGuiColumnsFlags_NoResize)) + dragging_column = n; + } + + // Draw column + const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + } + + // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. + if (dragging_column != -1) + { + if (!columns->IsBeingResized) + for (int n = 0; n < columns->Count + 1; n++) + columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; + columns->IsBeingResized = is_being_resized = true; + float x = GetDraggedColumnOffset(columns, dragging_column); + SetColumnOffset(dragging_column, x); + } + } + columns->IsBeingResized = is_being_resized; + + window->WorkRect = columns->HostWorkRect; + window->DC.CurrentColumns = NULL; + window->DC.ColumnsOffset.x = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); +} + +// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] +void ImGui::Columns(int columns_count, const char* id, bool border) +{ + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(columns_count >= 1); + + ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); + //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior + ImGuiColumns* columns = window->DC.CurrentColumns; + if (columns != NULL && columns->Count == columns_count && columns->Flags == flags) + return; + + if (columns != NULL) + EndColumns(); + + if (columns_count != 1) + BeginColumns(id, columns_count, flags); +} + +//------------------------------------------------------------------------- From 61c7f0194e9027f86b3bc476f0a7db4129d54e5c Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jul 2019 15:11:52 -0700 Subject: [PATCH 037/200] Misc: Made Button(), ColorButton() not trigger an "edited" event leading to IsItemDeactivatedAfterEdit() returning true. This also effectively make ColorEdit4() not incorrect trigger IsItemDeactivatedAfterEdit() when clicking the color button to open the picker popup. (#1875) Demo: Added Button with repeater and InputFloat with +/- button to the status query test demo. --- docs/CHANGELOG.txt | 3 +++ imgui_demo.cpp | 32 +++++++++++++------------------- imgui_widgets.cpp | 5 ----- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c7a881644eb1f..0bcc213657525 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,9 @@ Other Changes: - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. +- Misc: Made Button(), ColorButton() not trigger an "edited" event leading to IsItemDeactivatedAfterEdit() + returning true. This also effectively make ColorEdit4() not incorrect trigger IsItemDeactivatedAfterEdit() + when clicking the color button to open the picker popup. (#1875) - Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow(). - Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger within the item code. The tool calls IM_DEBUG_BREAK() which can be redefined in imconfig.h if needed. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e1c07dcf22b9d..756f8adaafb0d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1545,28 +1545,22 @@ static void ShowDemoWindowWidgets() static bool b = false; static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; static char str[16] = {}; - ImGui::RadioButton("Text", &item_type, 0); - ImGui::RadioButton("Button", &item_type, 1); - ImGui::RadioButton("Checkbox", &item_type, 2); - ImGui::RadioButton("SliderFloat", &item_type, 3); - ImGui::RadioButton("InputText", &item_type, 4); - ImGui::RadioButton("InputFloat3", &item_type, 5); - ImGui::RadioButton("ColorEdit4", &item_type, 6); - ImGui::RadioButton("MenuItem", &item_type, 7); - ImGui::RadioButton("TreeNode (w/ double-click)", &item_type, 8); - ImGui::RadioButton("ListBox", &item_type, 9); - ImGui::Separator(); + ImGui::Combo("Item Type", &item_type, "Text\0Button\0Button (w/ repeat)\0Checkbox\0SliderFloat\0InputText\0InputFloat\0InputFloat3\0ColorEdit4\0MenuItem\0TreeNode (w/ double-click)\0ListBox\0"); + ImGui::SameLine(); + HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions."); bool ret = false; if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button - if (item_type == 2) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox - if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item - if (item_type == 4) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) - if (item_type == 5) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 6) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 7) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) - if (item_type == 8) { ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. - if (item_type == 9) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater) + if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox + if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item + if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) + if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input + if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) + if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) + if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) + if (item_type == 10){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. + if (item_type == 11){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } ImGui::BulletText( "Return value = %d\n" "IsItemFocused() = %d\n" diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0b2b2be78f676..53fab78841490 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -626,8 +626,6 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); - if (pressed) - MarkItemEdited(id); // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); @@ -4840,9 +4838,6 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); - if (pressed) - MarkItemEdited(id); - return pressed; } From e28d20c3e2d33261f2542095751561ea3022f6d0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jul 2019 17:09:47 -0700 Subject: [PATCH 038/200] Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0bcc213657525..10d36d089d1ab 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,8 @@ Other Changes: - Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Combo: Hide arrow when there's not enough space even for the square button. - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). +- Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column + would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 53fab78841490..25057426192bf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7295,8 +7295,10 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.CurrentColumns = columns; // Set state for first column - columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x; - columns->OffMaxX = ImMax(window->WorkRect.Max.x - window->Pos.x, columns->OffMinX + 1.0f); + const float column_padding = g.Style.ItemSpacing.x; + columns->OffMinX = window->DC.Indent.x - column_padding; + columns->OffMaxX = window->WorkRect.Max.x - window->Pos.x; + columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostClipRect = window->ClipRect; @@ -7343,7 +7345,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); - window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; + window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } void ImGui::NextColumn() @@ -7364,17 +7366,19 @@ void ImGui::NextColumn() PopItemWidth(); PopClipRect(); + const float column_padding = g.Style.ItemSpacing.x; columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); if (++columns->Current < columns->Count) { - // Columns 1+ cancel out IndentX + // Columns 1+ ignore IndentX (by canceling it out) // FIXME-COLUMNS: Unnecessary, could be locked? - window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x; + window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding; window->DrawList->ChannelsSetCurrent(columns->Current + 1); } else { // New row/line + // Column 0 honor IndentX window->DC.ColumnsOffset.x = 0.0f; window->DrawList->ChannelsSetCurrent(1); columns->Current = 0; @@ -7392,7 +7396,7 @@ void ImGui::NextColumn() float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); - window->WorkRect.Max.x = window->Pos.x + offset_1 - window->WindowPadding.x; + window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } void ImGui::EndColumns() From 6c16ba649092bc90e219d30990f53ee8c59abc7c Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jul 2019 18:40:48 -0700 Subject: [PATCH 039/200] Columns: Improved honoring left-most and right-most alignment with various values of ItemSpacing.x and WindowPadding.x. In particular, the right-most edge now reaches up to the clipping rectangle while ensuring that the right-most column clipping width matches others. (#125, #2666) --- docs/CHANGELOG.txt | 3 +++ imgui_widgets.cpp | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 10d36d089d1ab..d60e7cd1944b3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,9 @@ Other Changes: - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) +- Columns: Improved honoring left-most and right-most alignment with various values of ItemSpacing.x and + WindowPadding.x. In particular, the right-most edge now reaches up to the clipping rectangle while + ensuring that the right-most column clipping width matches others. (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 25057426192bf..61ed2267f4018 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7294,18 +7294,19 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->Flags = flags; window->DC.CurrentColumns = columns; - // Set state for first column - const float column_padding = g.Style.ItemSpacing.x; - columns->OffMinX = window->DC.Indent.x - column_padding; - columns->OffMaxX = window->WorkRect.Max.x - window->Pos.x; - columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostClipRect = window->ClipRect; columns->HostWorkRect = window->WorkRect; + + // Set state for first column + // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect + const float column_padding = g.Style.ItemSpacing.x; + const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); + columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f); + columns->OffMaxX = ImMin(window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f), window->WorkRect.Max.x + half_clip_extend_x) - window->Pos.x; + columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; - window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Clear data if columns count changed if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) @@ -7345,6 +7346,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); + window->DC.ColumnsOffset.x = columns->OffMinX - window->DC.Indent.x + column_padding; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } @@ -7379,7 +7382,7 @@ void ImGui::NextColumn() { // New row/line // Column 0 honor IndentX - window->DC.ColumnsOffset.x = 0.0f; + window->DC.ColumnsOffset.x = columns->OffMinX - window->DC.Indent.x + column_padding; window->DrawList->ChannelsSetCurrent(1); columns->Current = 0; columns->LineMinY = columns->LineMaxY; From 44336950e9590f40ef89b00bad1841d46d1ac391 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jul 2019 11:22:39 -0700 Subject: [PATCH 040/200] Revert "Columns: Improved honoring left-most and right-most alignment with various values of ItemSpacing.x and WindowPadding.x. In particular, the right-most edge now reaches up to the clipping rectangle while ensuring that the right-most column clipping width matches others. (#125, #2666)" This reverts commit 6c16ba649092bc90e219d30990f53ee8c59abc7c. --- docs/CHANGELOG.txt | 3 --- imgui_widgets.cpp | 19 ++++++++----------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d60e7cd1944b3..10d36d089d1ab 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,9 +58,6 @@ Other Changes: - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) -- Columns: Improved honoring left-most and right-most alignment with various values of ItemSpacing.x and - WindowPadding.x. In particular, the right-most edge now reaches up to the clipping rectangle while - ensuring that the right-most column clipping width matches others. (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 61ed2267f4018..25057426192bf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7294,19 +7294,18 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->Flags = flags; window->DC.CurrentColumns = columns; + // Set state for first column + const float column_padding = g.Style.ItemSpacing.x; + columns->OffMinX = window->DC.Indent.x - column_padding; + columns->OffMaxX = window->WorkRect.Max.x - window->Pos.x; + columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostClipRect = window->ClipRect; columns->HostWorkRect = window->WorkRect; - - // Set state for first column - // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect - const float column_padding = g.Style.ItemSpacing.x; - const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); - columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f); - columns->OffMaxX = ImMin(window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f), window->WorkRect.Max.x + half_clip_extend_x) - window->Pos.x; - columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; + window->DC.ColumnsOffset.x = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Clear data if columns count changed if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) @@ -7346,8 +7345,6 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); - window->DC.ColumnsOffset.x = columns->OffMinX - window->DC.Indent.x + column_padding; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } @@ -7382,7 +7379,7 @@ void ImGui::NextColumn() { // New row/line // Column 0 honor IndentX - window->DC.ColumnsOffset.x = columns->OffMinX - window->DC.Indent.x + column_padding; + window->DC.ColumnsOffset.x = 0.0f; window->DrawList->ChannelsSetCurrent(1); columns->Current = 0; columns->LineMinY = columns->LineMaxY; From 047dc16af5548335d4a32232b6cf5d09d88603cb Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jul 2019 10:48:22 -0700 Subject: [PATCH 041/200] Debug Tools: Added DebugStartItemPicker() in imgui_internal.h to facilitate binding this anywhere in user's tool. Adedd highlight. Added IMGUI_DEBUG_TOOL_ITEM_PICKER_EX to break in ItemAdd(). --- imconfig.h | 3 ++ imgui.cpp | 73 ++++++++++++++++++++++++++++-------------------- imgui_internal.h | 9 ++++-- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/imconfig.h b/imconfig.h index 16f8c82798fea..2b7712987f661 100644 --- a/imconfig.h +++ b/imconfig.h @@ -80,6 +80,9 @@ // Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging. //#define IM_DEBUG_BREAK IM_ASSERT(0) //#define IM_DEBUG_BREAK __debugbreak() +// Have the Item Picker break in the ItemAdd() function instead of ItemHoverable() - which is earlier in the code, will catch a few extra items, allow picking items other than Hovered one. +// This adds a small runtime cost which is why it is not enabled by default. +//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. /* diff --git a/imgui.cpp b/imgui.cpp index 659239df5ad40..3b9996a3a39c8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2861,16 +2861,6 @@ void ImGui::SetHoveredID(ImGuiID id) g.HoveredIdAllowOverlap = false; if (id != 0 && g.HoveredIdPreviousFrame != id) g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; - - // [DEBUG] Item Picker tool! - // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making - // the cost of this tool near-zero. We would get slightly better call-stack if we made the test in ItemAdd() - // but that would incur a slightly higher cost and may require us to hide this feature behind a define. - if (id != 0 && id == g.DebugBreakItemId) - { - IM_DEBUG_BREAK(); - g.DebugBreakItemId = 0; - } } ImGuiID ImGui::GetHoveredID() @@ -2979,6 +2969,15 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); + + // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() +#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX + if (id == g.DebugItemPickerBreakID) + { + IM_DEBUG_BREAK(); + g.DebugItemPickerBreakID = 0; + } +#endif } window->DC.LastItemId = id; @@ -3067,6 +3066,17 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; SetHoveredID(id); + + // [DEBUG] Item Picker tool! + // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making + // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered + // items if we perform the test in ItemAdd(), but that would incur a small runtime cost. + // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd(). + if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) + GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); + if (g.DebugItemPickerBreakID == id) + IM_DEBUG_BREAK(); + return true; } @@ -3787,6 +3797,27 @@ void ImGui::NewFrame() g.BeginPopupStack.resize(0); ClosePopupsOverWindow(g.NavWindow, false); + // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. + g.DebugItemPickerBreakID = 0; + if (g.DebugItemPickerActive) + { + const ImGuiID hovered_id = g.HoveredIdPreviousFrame; + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) + g.DebugItemPickerActive = false; + if (ImGui::IsMouseClicked(0) && hovered_id) + { + g.DebugItemPickerBreakID = hovered_id; + g.DebugItemPickerActive = false; + } + ImGui::SetNextWindowBgAlpha(0.60f); + ImGui::BeginTooltip(); + ImGui::Text("HoveredId: 0x%08X", hovered_id); + ImGui::Text("Press ESC to abort picking."); + ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); + ImGui::EndTooltip(); + } + // Create implicit/fallback window - which we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. // This fallback is particularly important as it avoid ImGui:: calls from crashing. @@ -9801,27 +9832,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode("Tools")) { - static bool picking_enabled = false; + // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. if (ImGui::Button("Item Picker..")) - picking_enabled = true; - if (picking_enabled) - { - const ImGuiID hovered_id = g.HoveredIdPreviousFrame; - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) - picking_enabled = false; - if (ImGui::IsMouseClicked(0) && hovered_id) - { - g.DebugBreakItemId = hovered_id; - picking_enabled = false; - } - ImGui::SetNextWindowBgAlpha(0.5f); - ImGui::BeginTooltip(); - ImGui::Text("HoveredId: 0x%08X", hovered_id); - ImGui::Text("Press ESC to abort picking."); - ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); - ImGui::EndTooltip(); - } + ImGui::DebugStartItemPicker(); ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); ImGui::Checkbox("Show windows rectangles", &show_windows_rects); diff --git a/imgui_internal.h b/imgui_internal.h index 2eacac948294e..366c682ced7c3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1029,7 +1029,8 @@ struct ImGuiContext int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. // Debug Tools - ImGuiID DebugBreakItemId; + bool DebugItemPickerActive; + ImGuiID DebugItemPickerBreakID; // Will call IM_DEBUG_BREAK() when encountering this id // Misc float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. @@ -1156,7 +1157,8 @@ struct ImGuiContext LogDepthRef = 0; LogDepthToExpand = LogDepthToExpandDefault = 2; - DebugBreakItemId = 0; + DebugItemPickerActive = false; + DebugItemPickerBreakID = 0; memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; @@ -1658,6 +1660,9 @@ namespace ImGui IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); + // Debug Tools + inline void DebugStartItemPicker() { GImGui->DebugItemPickerActive = true; } + } // namespace ImGui // ImFontAtlas internals From 493795cdd1890d9cf1b2648c3e7ca9993f1d8971 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jul 2019 12:11:00 -0700 Subject: [PATCH 042/200] Columns: Fix support for BeginColumns() with a count of 1 (not that this isn't available via the old Columns() api). Tweaked Demo to facilitate testing for it. --- imgui_demo.cpp | 9 +++++++-- imgui_widgets.cpp | 13 +++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 756f8adaafb0d..b59fe6020fe7d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2590,11 +2590,16 @@ static void ShowDemoWindowColumns() // NB: Future columns API should allow automatic horizontal borders. static bool h_borders = true; static bool v_borders = true; + static int columns_count = 4; + const int lines_count = 3; + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); + ImGui::DragInt("##columns_count", &columns_count, 0.1f, 1, 10, "%d columns"); + ImGui::SameLine(); ImGui::Checkbox("horizontal", &h_borders); ImGui::SameLine(); ImGui::Checkbox("vertical", &v_borders); - ImGui::Columns(4, NULL, v_borders); - for (int i = 0; i < 4 * 3; i++) + ImGui::Columns(columns_count, NULL, v_borders); + for (int i = 0; i < columns_count * lines_count; i++) { if (h_borders && ImGui::GetColumnIndex() == 0) ImGui::Separator(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 25057426192bf..0878b46c70e01 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7236,6 +7236,8 @@ void ImGui::PushColumnsBackground() { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumns* columns = window->DC.CurrentColumns; + if (columns->Count == 1) + return; window->DrawList->ChannelsSetCurrent(0); int cmd_size = window->DrawList->CmdBuffer.Size; PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); @@ -7247,6 +7249,8 @@ void ImGui::PopColumnsBackground() { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumns* columns = window->DC.CurrentColumns; + if (columns->Count == 1) + return; window->DrawList->ChannelsSetCurrent(columns->Current + 1); PopClipRect(); } @@ -7294,15 +7298,16 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->Flags = flags; window->DC.CurrentColumns = columns; + columns->HostCursorPosY = window->DC.CursorPos.y; + columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; + columns->HostClipRect = window->ClipRect; + columns->HostWorkRect = window->WorkRect; + // Set state for first column const float column_padding = g.Style.ItemSpacing.x; columns->OffMinX = window->DC.Indent.x - column_padding; columns->OffMaxX = window->WorkRect.Max.x - window->Pos.x; columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); - columns->HostCursorPosY = window->DC.CursorPos.y; - columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; - columns->HostClipRect = window->ClipRect; - columns->HostWorkRect = window->WorkRect; columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffset.x = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); From 4abc2a82e0f258288ec252d810a1ab772619a528 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jul 2019 13:28:40 -0700 Subject: [PATCH 043/200] Columns: Made the right-most edge reaches up to the clipping rectangle (removing WindowPadding.x*0.5 worth of asymmetrical/extraneous padding). (#125, #2666) + Moved a few things in BeginColumns(). --- docs/CHANGELOG.txt | 3 +++ imgui_widgets.cpp | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 10d36d089d1ab..3722438fcd61c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,9 @@ Other Changes: - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) +- Columns: Made the right-most edge reaches up to the clipping rectangle (removing half of WindowPadding.x + worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset + the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0878b46c70e01..3c2405ff7d2ef 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7304,13 +7304,13 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->HostWorkRect = window->WorkRect; // Set state for first column + // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect const float column_padding = g.Style.ItemSpacing.x; + const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); columns->OffMinX = window->DC.Indent.x - column_padding; - columns->OffMaxX = window->WorkRect.Max.x - window->Pos.x; + columns->OffMaxX = window->WorkRect.Max.x + half_clip_extend_x - window->Pos.x; columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; - window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Clear data if columns count changed if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) @@ -7346,10 +7346,13 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag PushColumnClipRect(0); } + // We don't generally store Indent.x inside ColumnsOffset because it may be manipulated by the user. float offset_0 = GetColumnOffset(columns->Current); float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); + window->DC.ColumnsOffset.x = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } From b443bc0a64d5e22d445d2c9cb52f7f39da6b98c9 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jul 2019 14:22:33 -0700 Subject: [PATCH 044/200] Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3722438fcd61c..93f7a7fcf8745 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other Changes: - Columns: Made the right-most edge reaches up to the clipping rectangle (removing half of WindowPadding.x worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666) +- Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3c2405ff7d2ef..1373ea741189e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7307,9 +7307,10 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect const float column_padding = g.Style.ItemSpacing.x; const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); - columns->OffMinX = window->DC.Indent.x - column_padding; - columns->OffMaxX = window->WorkRect.Max.x + half_clip_extend_x - window->Pos.x; - columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); + const float max_1 = window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f); + const float max_2 = window->WorkRect.Max.x + half_clip_extend_x; + columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f); + columns->OffMaxX = ImMax(ImMin(max_1, max_2) - window->Pos.x, columns->OffMinX + 1.0f); columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; // Clear data if columns count changed @@ -7351,7 +7352,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); - window->DC.ColumnsOffset.x = 0.0f; + window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } @@ -7387,7 +7388,7 @@ void ImGui::NextColumn() { // New row/line // Column 0 honor IndentX - window->DC.ColumnsOffset.x = 0.0f; + window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DrawList->ChannelsSetCurrent(1); columns->Current = 0; columns->LineMinY = columns->LineMaxY; From c37f21788fcd8824d807c575947062223490b807 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jul 2019 11:23:15 -0700 Subject: [PATCH 045/200] Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with other column functions + fixed Columns demo (#2683) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 4 +++- imgui_widgets.cpp | 9 ++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 93f7a7fcf8745..c06e2e5726f28 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other Changes: - Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). +- Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with + other column functions. (#2683) - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b59fe6020fe7d..53e2bf1c47864 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2593,7 +2593,9 @@ static void ShowDemoWindowColumns() static int columns_count = 4; const int lines_count = 3; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); - ImGui::DragInt("##columns_count", &columns_count, 0.1f, 1, 10, "%d columns"); + ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns"); + if (columns_count < 2) + columns_count = 2; ImGui::SameLine(); ImGui::Checkbox("horizontal", &h_borders); ImGui::SameLine(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1373ea741189e..c42c518f0576f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7152,7 +7152,8 @@ float ImGui::GetColumnOffset(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); + if (columns == NULL) + return 0.0f; if (column_index < 0) column_index = columns->Current; @@ -7178,9 +7179,11 @@ static float GetColumnWidthEx(ImGuiColumns* columns, int column_index, bool befo float ImGui::GetColumnWidth(int column_index) { - ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; ImGuiColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); + if (columns == NULL) + return GetContentRegionAvail().x; if (column_index < 0) column_index = columns->Current; From f1ba217a92846416475576b5983652f7f716cd71 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jul 2019 12:13:44 -0700 Subject: [PATCH 046/200] Internals: Extracted some code out of the NewFrame() function. --- imgui.cpp | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3b9996a3a39c8..1cfaeabf513b5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1089,6 +1089,7 @@ static int FindWindowFocusIndex(ImGuiWindow* window); static void UpdateMouseInputs(); static void UpdateMouseWheel(); static bool UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); +static void UpdateDebugToolItemPicker(); static void RenderWindowOuterBorders(ImGuiWindow* window); static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); @@ -3584,15 +3585,10 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; } -void ImGui::NewFrame() +static void NewFrameSanityChecks() { - IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); ImGuiContext& g = *GImGui; -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiTestEngineHook_PreNewFrame(&g); -#endif - // Check user data // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) IM_ASSERT(g.Initialized); @@ -3605,7 +3601,6 @@ void ImGui::NewFrame() IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!"); IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); - for (int n = 0; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); @@ -3616,6 +3611,19 @@ void ImGui::NewFrame() // Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly. if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors)) g.IO.ConfigWindowsResizeFromEdges = false; +} + +void ImGui::NewFrame() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); + ImGuiContext& g = *GImGui; + +#ifdef IMGUI_ENABLE_TEST_ENGINE + ImGuiTestEngineHook_PreNewFrame(&g); +#endif + + // Check and assert for various common IO and Configuration mistakes + NewFrameSanityChecks(); // Load settings on first frame (if not explicitly loaded manually before) if (!g.SettingsLoaded) @@ -3798,6 +3806,24 @@ void ImGui::NewFrame() ClosePopupsOverWindow(g.NavWindow, false); // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. + UpdateDebugToolItemPicker(); + + // Create implicit/fallback window - which we will only render it if the user has added something to it. + // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. + // This fallback is particularly important as it avoid ImGui:: calls from crashing. + SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); + Begin("Debug##Default"); + g.FrameScopePushedImplicitWindow = true; + +#ifdef IMGUI_ENABLE_TEST_ENGINE + ImGuiTestEngineHook_PostNewFrame(&g); +#endif +} + +// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. +void ImGui::UpdateDebugToolItemPicker() +{ + ImGuiContext& g = *GImGui; g.DebugItemPickerBreakID = 0; if (g.DebugItemPickerActive) { @@ -3817,17 +3843,6 @@ void ImGui::NewFrame() ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); ImGui::EndTooltip(); } - - // Create implicit/fallback window - which we will only render it if the user has added something to it. - // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. - // This fallback is particularly important as it avoid ImGui:: calls from crashing. - SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); - Begin("Debug##Default"); - g.FrameScopePushedImplicitWindow = true; - -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiTestEngineHook_PostNewFrame(&g); -#endif } void ImGui::Initialize(ImGuiContext* context) From 4b44f25c9a5044d230b58deb38196e0a90ac9c68 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jul 2019 18:19:56 -0700 Subject: [PATCH 047/200] Fixed incorrect application of io.DisplaySafeAreaPadding which would be problematic with multi-viewports when a monitor uses negative coordinates (correct clamping is done right below). (#2674) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1cfaeabf513b5..a2e2280750149 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5596,7 +5596,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0); if (window_pos_with_pivot) - SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering) + SetWindowPos(window, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering) else if ((flags & ImGuiWindowFlags_ChildMenu) != 0) window->Pos = FindBestWindowPosForPopup(window); else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) From 0f86116a69dfbd3d705484d8ba031e10e523335e Mon Sep 17 00:00:00 2001 From: Aaron Cooper <1531573+amc522@users.noreply.github.com> Date: Thu, 18 Jul 2019 17:24:56 -0700 Subject: [PATCH 048/200] Adding an ImGuiKey 'ImGuiKey_EnterSecondary' to support platforms that differentiate the enter (return key) and the numpad enter key. --- examples/imgui_impl_allegro5.cpp | 1 + examples/imgui_impl_glfw.cpp | 1 + examples/imgui_impl_marmalade.cpp | 1 + examples/imgui_impl_osx.mm | 43 ++++++++++++++++--------------- examples/imgui_impl_sdl.cpp | 1 + examples/imgui_impl_win32.cpp | 1 + imgui.h | 1 + imgui_widgets.cpp | 2 +- 8 files changed, 29 insertions(+), 22 deletions(-) diff --git a/examples/imgui_impl_allegro5.cpp b/examples/imgui_impl_allegro5.cpp index 46893390018b9..8228c4161da1b 100644 --- a/examples/imgui_impl_allegro5.cpp +++ b/examples/imgui_impl_allegro5.cpp @@ -281,6 +281,7 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Space] = ALLEGRO_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER; + io.KeyMap[ImGuiKey_EnterSecondary] = ALLEGRO_KEY_PAD_ENTER; io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A; io.KeyMap[ImGuiKey_C] = ALLEGRO_KEY_C; diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index bcfeac454c8ee..c1a274965b255 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -150,6 +150,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_EnterSecondary] = GLFW_KEY_KP_ENTER; io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; diff --git a/examples/imgui_impl_marmalade.cpp b/examples/imgui_impl_marmalade.cpp index a101c69afbf14..865810ec53e7a 100644 --- a/examples/imgui_impl_marmalade.cpp +++ b/examples/imgui_impl_marmalade.cpp @@ -234,6 +234,7 @@ bool ImGui_Marmalade_Init(bool install_callbacks) io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace; io.KeyMap[ImGuiKey_Space] = s3eKeySpace; io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter; + io.KeyMap[ImGuiKey_EnterSecondary] = s3eKeyNumPadEnter; io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc; io.KeyMap[ImGuiKey_A] = s3eKeyA; io.KeyMap[ImGuiKey_C] = s3eKeyC; diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index cfcd3a74a5d1c..60cb8e237047c 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -47,27 +47,28 @@ bool ImGui_ImplOSX_Init() // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. const int offset_for_function_keys = 256 - 0xF700; - io.KeyMap[ImGuiKey_Tab] = '\t'; - io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys; - io.KeyMap[ImGuiKey_Backspace] = 127; - io.KeyMap[ImGuiKey_Space] = 32; - io.KeyMap[ImGuiKey_Enter] = 13; - io.KeyMap[ImGuiKey_Escape] = 27; - io.KeyMap[ImGuiKey_A] = 'A'; - io.KeyMap[ImGuiKey_C] = 'C'; - io.KeyMap[ImGuiKey_V] = 'V'; - io.KeyMap[ImGuiKey_X] = 'X'; - io.KeyMap[ImGuiKey_Y] = 'Y'; - io.KeyMap[ImGuiKey_Z] = 'Z'; + io.KeyMap[ImGuiKey_Tab] = '\t'; + io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Backspace] = 127; + io.KeyMap[ImGuiKey_Space] = 32; + io.KeyMap[ImGuiKey_Enter] = 13; + io.KeyMap[ImGuiKey_EnterSecondary] = 13; + io.KeyMap[ImGuiKey_Escape] = 27; + io.KeyMap[ImGuiKey_A] = 'A'; + io.KeyMap[ImGuiKey_C] = 'C'; + io.KeyMap[ImGuiKey_V] = 'V'; + io.KeyMap[ImGuiKey_X] = 'X'; + io.KeyMap[ImGuiKey_Y] = 'Y'; + io.KeyMap[ImGuiKey_Z] = 'Z'; // Load cursors. Some of them are undocumented. g_MouseCursorHidden = false; diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 0cf937a4e0dd6..86aa70a1190e4 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -143,6 +143,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE; io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; + io.KeyMap[ImGuiKey_EnterSecondary] = SDL_SCANCODE_RETURN2; io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C; diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 85dede4eef9a4..9581e7ca69c09 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -77,6 +77,7 @@ bool ImGui_ImplWin32_Init(void* hwnd) io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; + io.KeyMap[ImGuiKey_EnterSecondary] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; io.KeyMap[ImGuiKey_A] = 'A'; io.KeyMap[ImGuiKey_C] = 'C'; diff --git a/imgui.h b/imgui.h index a81296fd6c320..5aa93677ec017 100644 --- a/imgui.h +++ b/imgui.h @@ -940,6 +940,7 @@ enum ImGuiKey_ ImGuiKey_Backspace, ImGuiKey_Space, ImGuiKey_Enter, + ImGuiKey_EnterSecondary, ImGuiKey_Escape, ImGuiKey_A, // for text edit CTRL+A: select all ImGuiKey_C, // for text edit CTRL+C: copy diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c42c518f0576f..176d2167e4b30 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3653,7 +3653,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Enter)) + else if (IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_EnterSecondary)) { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) From f0348ddffc41a9ef1e34e930796ab68fe959079e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jul 2019 18:39:50 -0700 Subject: [PATCH 049/200] Amend 0f86116, renamed to ImGuiKey_KeyPadEnter Changelog.. (#2677, #2005) --- docs/CHANGELOG.txt | 3 +++ examples/imgui_impl_allegro5.cpp | 3 ++- examples/imgui_impl_glfw.cpp | 3 ++- examples/imgui_impl_glut.cpp | 1 + examples/imgui_impl_marmalade.cpp | 3 ++- examples/imgui_impl_osx.mm | 2 +- examples/imgui_impl_sdl.cpp | 3 ++- examples/imgui_impl_win32.cpp | 2 +- imgui.h | 2 +- imgui_widgets.cpp | 2 +- 10 files changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c06e2e5726f28..98cc196044668 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,9 @@ Other Changes: - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. +- IO: Added ImGuiKey_KeyPadEnter and support in various back-ends (previously back-ends would need to + specifically redirect key-pad keys to their regular counterpart). This is a temporary attenuating measure + until we actually refactor and add whole sets of keys into the ImGuiKey enum. (#2677, #2005) [@amc522] - Misc: Made Button(), ColorButton() not trigger an "edited" event leading to IsItemDeactivatedAfterEdit() returning true. This also effectively make ColorEdit4() not incorrect trigger IsItemDeactivatedAfterEdit() when clicking the color button to open the picker popup. (#1875) diff --git a/examples/imgui_impl_allegro5.cpp b/examples/imgui_impl_allegro5.cpp index 8228c4161da1b..525ad5c976e13 100644 --- a/examples/imgui_impl_allegro5.cpp +++ b/examples/imgui_impl_allegro5.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-05-11: Inputs: Don't filter character value from ALLEGRO_EVENT_KEY_CHAR before calling AddInputCharacter(). // 2019-04-30: Renderer: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2018-11-30: Platform: Added touchscreen support. @@ -281,8 +282,8 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Space] = ALLEGRO_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER; - io.KeyMap[ImGuiKey_EnterSecondary] = ALLEGRO_KEY_PAD_ENTER; io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE; + io.KeyMap[ImGuiKey_KeyPadEnter] = ALLEGRO_KEY_PAD_ENTER; io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A; io.KeyMap[ImGuiKey_C] = ALLEGRO_KEY_C; io.KeyMap[ImGuiKey_V] = ALLEGRO_KEY_V; diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index c1a274965b255..a9e72c6cbb323 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter(). // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. @@ -150,8 +151,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; - io.KeyMap[ImGuiKey_EnterSecondary] = GLFW_KEY_KP_ENTER; io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_KeyPadEnter] = GLFW_KEY_KP_ENTER; io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; diff --git a/examples/imgui_impl_glut.cpp b/examples/imgui_impl_glut.cpp index 6b800bf174376..56d8c553681e1 100644 --- a/examples/imgui_impl_glut.cpp +++ b/examples/imgui_impl_glut.cpp @@ -59,6 +59,7 @@ bool ImGui_ImplGLUT_Init() io.KeyMap[ImGuiKey_Space] = ' '; io.KeyMap[ImGuiKey_Enter] = 13; // == CTRL+M io.KeyMap[ImGuiKey_Escape] = 27; + io.KeyMap[ImGuiKey_KeyPadEnter] = 13; // == CTRL+M io.KeyMap[ImGuiKey_A] = 'A'; io.KeyMap[ImGuiKey_C] = 'C'; io.KeyMap[ImGuiKey_V] = 'V'; diff --git a/examples/imgui_impl_marmalade.cpp b/examples/imgui_impl_marmalade.cpp index 865810ec53e7a..497a5705e2f48 100644 --- a/examples/imgui_impl_marmalade.cpp +++ b/examples/imgui_impl_marmalade.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter(). // 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself. @@ -234,8 +235,8 @@ bool ImGui_Marmalade_Init(bool install_callbacks) io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace; io.KeyMap[ImGuiKey_Space] = s3eKeySpace; io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter; - io.KeyMap[ImGuiKey_EnterSecondary] = s3eKeyNumPadEnter; io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc; + io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter; io.KeyMap[ImGuiKey_A] = s3eKeyA; io.KeyMap[ImGuiKey_C] = s3eKeyC; io.KeyMap[ImGuiKey_V] = s3eKeyV; diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index 60cb8e237047c..179306e467c34 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -61,8 +61,8 @@ bool ImGui_ImplOSX_Init() io.KeyMap[ImGuiKey_Backspace] = 127; io.KeyMap[ImGuiKey_Space] = 32; io.KeyMap[ImGuiKey_Enter] = 13; - io.KeyMap[ImGuiKey_EnterSecondary] = 13; io.KeyMap[ImGuiKey_Escape] = 27; + io.KeyMap[ImGuiKey_KeyPadEnter] = 13; io.KeyMap[ImGuiKey_A] = 'A'; io.KeyMap[ImGuiKey_C] = 'C'; io.KeyMap[ImGuiKey_V] = 'V'; diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 86aa70a1190e4..4267758101701 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application). // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. // 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls. @@ -143,8 +144,8 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE; io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; - io.KeyMap[ImGuiKey_EnterSecondary] = SDL_SCANCODE_RETURN2; io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; + io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_RETURN2; io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C; io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V; diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 9581e7ca69c09..8d46d942c96b9 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -77,8 +77,8 @@ bool ImGui_ImplWin32_Init(void* hwnd) io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; - io.KeyMap[ImGuiKey_EnterSecondary] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; + io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN; io.KeyMap[ImGuiKey_A] = 'A'; io.KeyMap[ImGuiKey_C] = 'C'; io.KeyMap[ImGuiKey_V] = 'V'; diff --git a/imgui.h b/imgui.h index 5aa93677ec017..ef2014a5d221f 100644 --- a/imgui.h +++ b/imgui.h @@ -940,8 +940,8 @@ enum ImGuiKey_ ImGuiKey_Backspace, ImGuiKey_Space, ImGuiKey_Enter, - ImGuiKey_EnterSecondary, ImGuiKey_Escape, + ImGuiKey_KeyPadEnter, ImGuiKey_A, // for text edit CTRL+A: select all ImGuiKey_C, // for text edit CTRL+C: copy ImGuiKey_V, // for text edit CTRL+V: paste diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 176d2167e4b30..13875ea2a6e14 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3653,7 +3653,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_EnterSecondary)) + else if (IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter)) { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) From 29d9394a41939e8d033814704d5e9bcca516bf37 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jul 2019 19:06:07 -0700 Subject: [PATCH 050/200] OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), because it needs application to be linked with '-framework ApplicationServices'. It can be explicitly enabled back by using '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h. Re-added equivalent using NSPasteboard api in the imgui_impl_osx.mm experimental back-end. (#2546) --- docs/CHANGELOG.txt | 4 ++++ examples/imgui_impl_osx.mm | 31 +++++++++++++++++++++++++++++-- imconfig.h | 2 +- imgui.cpp | 3 ++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 98cc196044668..8250c56d5feb0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -85,6 +85,10 @@ Other Changes: - ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, also this type was added in 1.71 and not advertised as a public-facing feature). - Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file. +- Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), + because it needs application to be linked with '-framework ApplicationServices'. It can be explicitly + enabled back by using '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h. Re-added + equivalent using NSPasteboard api in the imgui_impl_osx.mm experimental back-end. (#2546) - Backends: SDL2: Added dummy ImGui_ImplSDL2_InitForD3D() function to make D3D support more visible. (#2482, #2632) [@josiahmanson] - Examples: Added SDL2+DirectX11 example application. (#2632, #2612, #2482) [@vincenthamm] diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index 179306e467c34..9042e15f9807f 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -14,6 +14,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: Readded clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change). // 2019-05-28: Inputs: Added mouse cursor shape and visibility support. // 2019-05-18: Misc: Removed clipboard handlers as they are now supported by core imgui.cpp. // 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range. @@ -81,8 +82,34 @@ bool ImGui_ImplOSX_Init() g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor]; g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor]; - // We don't set the io.SetClipboardTextFn/io.GetClipboardTextFn handlers, - // because imgui.cpp has a default for them that works with OSX. + // Note that imgui.cpp also include default OSX clipboard handlers which can be enabled + // by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line. + // Since we are already in ObjC land here, it is easy for us to add a clipboard handler using the NSPasteboard api. + io.SetClipboardTextFn = [](void*, const char* str) -> void + { + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil]; + [pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString]; + }; + + io.GetClipboardTextFn = [](void*) -> const char* + { + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]]; + if (![available isEqualToString:NSPasteboardTypeString]) + return NULL; + + NSString* string = [pasteboard stringForType:NSPasteboardTypeString]; + if (string == nil) + return NULL; + + const char* string_c = (const char*)[string UTF8String]; + size_t string_len = strlen(string_c); + static ImVector s_clipboard; + s_clipboard.resize((int)string_len + 1); + strcpy(s_clipboard.Data, string_c); + return s_clipboard.Data; + }; return true; } diff --git a/imconfig.h b/imconfig.h index 2b7712987f661..22a21db0fc108 100644 --- a/imconfig.h +++ b/imconfig.h @@ -34,7 +34,7 @@ //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). -//#define IMGUI_DISABLE_OSX_FUNCTIONS // [OSX] Won't use and link with any OSX function (clipboard). +//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices'). //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf. //#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h. //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). diff --git a/imgui.cpp b/imgui.cpp index a2e2280750149..fdc12c78cf403 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9504,12 +9504,13 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) ::CloseClipboard(); } -#elif defined(__APPLE__) && TARGET_OS_OSX && !defined(IMGUI_DISABLE_OSX_FUNCTIONS) +#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS) #include // Use old API to avoid need for separate .mm file static PasteboardRef main_clipboard = 0; // OSX clipboard implementation +// If you enable this you will need to add '-framework ApplicationServices' to your linker command-line! static void SetClipboardTextFn_DefaultImpl(void*, const char* text) { if (!main_clipboard) From cbd5a21fb0782d489b56430fdbf32d7e08aff583 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jul 2019 19:26:13 -0700 Subject: [PATCH 051/200] Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer. Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them. --- docs/CHANGELOG.txt | 2 ++ examples/imgui_impl_dx10.cpp | 5 +++++ examples/imgui_impl_dx11.cpp | 13 +++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8250c56d5feb0..3869166ff3458 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -85,6 +85,8 @@ Other Changes: - ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, also this type was added in 1.71 and not advertised as a public-facing feature). - Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file. +- Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer. +- Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them. - Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), because it needs application to be linked with '-framework ApplicationServices'. It can be explicitly enabled back by using '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h. Re-added diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index 22c4b9d02b76a..6dec6147b4a9e 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -11,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData(). // 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). @@ -81,6 +82,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); ctx->PSSetShader(g_pPixelShader); ctx->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->GSSetShader(NULL); // Setup render state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; @@ -183,6 +185,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ID3D10SamplerState* PSSampler; ID3D10PixelShader* PS; ID3D10VertexShader* VS; + ID3D10GeometryShader* GS; D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; @@ -201,6 +204,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ctx->PSGetShader(&old.PS); ctx->VSGetShader(&old.VS); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->GSGetShader(&old.GS); ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); @@ -255,6 +259,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release(); ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 3bcb03a2b79b8..89b88dead8e14 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -11,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. // 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). @@ -81,6 +82,10 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); ctx->PSSetShader(g_pPixelShader, NULL, 0); ctx->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->GSSetShader(NULL, NULL, 0); + ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. + ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. + ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. // Setup blend state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; @@ -185,8 +190,9 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ID3D11SamplerState* PSSampler; ID3D11PixelShader* PS; ID3D11VertexShader* VS; - UINT PSInstancesCount, VSInstancesCount; - ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + ID3D11GeometryShader* GS; + UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; + ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; @@ -206,6 +212,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); @@ -262,6 +270,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); From 363d33f64ea988f11c124207b89d9f4f15f11be9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jul 2019 10:23:27 -0700 Subject: [PATCH 052/200] Increased IMGUI_VERSION_NUM to facilitate transition of OSX clipboard support for framework using/embedding any version of imgui. Amend 29d9394. (#2546) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index ef2014a5d221f..cdfa426d8c798 100644 --- a/imgui.h +++ b/imgui.h @@ -47,7 +47,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.72 WIP" -#define IMGUI_VERSION_NUM 17101 +#define IMGUI_VERSION_NUM 17102 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) From 835b50b7737f7f626a0983c6980f4397575b06b4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jul 2019 17:27:41 -0700 Subject: [PATCH 053/200] Internals: Nav: Tweak NavUpdatePageUpPageDown() to make it more readable. --- imgui.cpp | 63 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fdc12c78cf403..f381e1f39fbd8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5756,6 +5756,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (render_decorations_in_parent) window->DrawList = parent_window->DrawList; + // Handle title bar, scrollbar, resize grips and resize borders const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, resize_grip_count, resize_grip_col, resize_grip_draw_size); @@ -8451,42 +8452,44 @@ static void ImGui::NavUpdateMoveResult() static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) { ImGuiContext& g = *GImGui; - if (g.NavMoveDir == ImGuiDir_None && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0) + if (g.NavMoveDir != ImGuiDir_None || g.NavWindow == NULL) + return 0.0f; + if ((g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != 0) + return 0.0f; + + ImGuiWindow* window = g.NavWindow; + bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); + bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + if (page_up_held != page_down_held) // If either (not both) are pressed { - ImGuiWindow* window = g.NavWindow; - bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); - bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); - if (page_up_held != page_down_held) // If either (not both) are pressed + if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) + { + // Fallback manual-scroll when window has no navigable item + if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) + SetWindowScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); + else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) + SetWindowScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); + } + else { - if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) + const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; + const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); + float nav_scoring_rect_offset_y = 0.0f; + if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) { - // Fallback manual-scroll when window has no navigable item - if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) - SetWindowScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); - else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) - SetWindowScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); + nav_scoring_rect_offset_y = -page_offset_y; + g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveClipDir = ImGuiDir_Up; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; } - else + else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) { - const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; - const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); - float nav_scoring_rect_offset_y = 0.0f; - if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) - { - nav_scoring_rect_offset_y = -page_offset_y; - g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) - g.NavMoveClipDir = ImGuiDir_Up; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; - } - else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) - { - nav_scoring_rect_offset_y = +page_offset_y; - g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) - g.NavMoveClipDir = ImGuiDir_Down; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; - } - return nav_scoring_rect_offset_y; + nav_scoring_rect_offset_y = +page_offset_y; + g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveClipDir = ImGuiDir_Down; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; } + return nav_scoring_rect_offset_y; } } return 0.0f; From 34cf00566f57b48870192d650cb06e4b6cc88738 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jul 2019 18:11:06 -0700 Subject: [PATCH 054/200] InputTextMultiline: Fixed vertical scrolling tracking glitch. Fixed Travis-CI banner address. --- docs/CHANGELOG.txt | 5 +++-- docs/README.md | 2 +- imgui_widgets.cpp | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3869166ff3458..c20ae7c5966f8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,10 +62,11 @@ Other Changes: worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666) - Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) -- Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because - of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with other column functions. (#2683) +- InputTextMultiline: Fixed vertical scrolling tracking glitch. +- Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because + of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button diff --git a/docs/README.md b/docs/README.md index 902b615ada28f..d020ea076ebc7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ dear imgui ===== -[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) +[![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) _(This library is free as in freedom, but needs your support to sustain its development. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal.)_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 13875ea2a6e14..4c65ed9cb0fad 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3993,9 +3993,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); else if (cursor_offset.y - size.y >= scroll_y) scroll_y = cursor_offset.y - size.y; - draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag + draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag draw_window->Scroll.y = scroll_y; - draw_pos.y = draw_window->DC.CursorPos.y; } state->CursorFollow = false; From dcd03f62a7c1d246cd0638c8657574f1fe0486fa Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jul 2019 18:24:23 -0700 Subject: [PATCH 055/200] Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling. Demo: Log, Console: Using a simpler stateless pattern for auto-scrolling. --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 38 ++++++++++++++++++++------------------ imgui_demo.cpp | 30 ++++++++++-------------------- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 4 ++-- 5 files changed, 40 insertions(+), 42 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c20ae7c5966f8..da56984afdf9b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,11 @@ Other Changes: - InputTextMultiline: Fixed vertical scrolling tracking glitch. - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). +- Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to + SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling: + // (Submit items..) + if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) // Keep scrolling at the bottom if already + ImGui::SetScrollHereY(1.0f); - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button @@ -86,6 +91,7 @@ Other Changes: - ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, also this type was added in 1.71 and not advertised as a public-facing feature). - Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file. +- Demo: Log, Console: Using a simpler stateless pattern for auto-scrolling. - Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer. - Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them. - Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), diff --git a/imgui.cpp b/imgui.cpp index f381e1f39fbd8..b473f7fa65c9d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3506,7 +3506,7 @@ void ImGui::UpdateMouseWheel() { float max_step = window->InnerRect.GetHeight() * 0.67f; float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step)); - SetWindowScrollY(window, window->Scroll.y - wheel_y * scroll_step); + SetScrollY(window, window->Scroll.y - wheel_y * scroll_step); } } @@ -3521,7 +3521,7 @@ void ImGui::UpdateMouseWheel() { float max_step = window->InnerRect.GetWidth() * 0.67f; float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step)); - SetWindowScrollX(window, window->Scroll.x - wheel_x * scroll_step); + SetScrollX(window, window->Scroll.x - wheel_x * scroll_step); } } } @@ -6524,16 +6524,6 @@ ImVec2 ImGui::GetWindowPos() return window->Pos; } -void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x) -{ - window->Scroll.x = new_scroll_x; -} - -void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) -{ - window->Scroll.y = new_scroll_y; -} - void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time @@ -6921,6 +6911,18 @@ void ImGui::SetScrollY(float scroll_y) window->ScrollTargetCenterRatio.y = 0.0f; } +void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x) +{ + window->ScrollTarget.x = new_scroll_x; + window->ScrollTargetCenterRatio.x = 0.0f; +} + +void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) +{ + window->ScrollTarget.y = new_scroll_y; + window->ScrollTargetCenterRatio.y = 0.0f; +} + void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size @@ -8333,9 +8335,9 @@ static void ImGui::NavUpdate() if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) { if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) - SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); + SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) - SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + SetScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); } // *Normal* Manual scroll with NavScrollXXX keys @@ -8343,12 +8345,12 @@ static void ImGui::NavUpdate() ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && window->ScrollbarX) { - SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); + SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); g.NavMoveFromClampedRefRect = true; } if (scroll_dir.y != 0.0f) { - SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed)); + SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed)); g.NavMoveFromClampedRefRect = true; } } @@ -8466,9 +8468,9 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) { // Fallback manual-scroll when window has no navigable item if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) - SetWindowScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); + SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) - SetWindowScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); + SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); } else { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 53e2bf1c47864..257524d5a96a2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3449,7 +3449,7 @@ struct ExampleAppConsole Commands.push_back("CLEAR"); Commands.push_back("CLASSIFY"); // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches. AutoScroll = true; - ScrollToBottom = true; + ScrollToBottom = false; AddLog("Welcome to Dear ImGui!"); } ~ExampleAppConsole() @@ -3470,7 +3470,6 @@ struct ExampleAppConsole for (int i = 0; i < Items.Size; i++) free(Items[i]); Items.clear(); - ScrollToBottom = true; } void AddLog(const char* fmt, ...) IM_FMTARGS(2) @@ -3483,8 +3482,6 @@ struct ExampleAppConsole buf[IM_ARRAYSIZE(buf)-1] = 0; va_end(args); Items.push_back(Strdup(buf)); - if (AutoScroll) - ScrollToBottom = true; } void Draw(const char* title, bool* p_open) @@ -3513,8 +3510,7 @@ struct ExampleAppConsole if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine(); if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine(); - bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine(); - if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true; + bool copy_to_clipboard = ImGui::SmallButton("Copy"); //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } ImGui::Separator(); @@ -3522,9 +3518,7 @@ struct ExampleAppConsole // Options menu if (ImGui::BeginPopup("Options")) { - if (ImGui::Checkbox("Auto-scroll", &AutoScroll)) - if (AutoScroll) - ScrollToBottom = true; + ImGui::Checkbox("Auto-scroll", &AutoScroll); ImGui::EndPopup(); } @@ -3573,9 +3567,11 @@ struct ExampleAppConsole } if (copy_to_clipboard) ImGui::LogFinish(); - if (ScrollToBottom) + + if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) ImGui::SetScrollHereY(1.0f); ScrollToBottom = false; + ImGui::PopStyleVar(); ImGui::EndChild(); ImGui::Separator(); @@ -3767,13 +3763,11 @@ struct ExampleAppLog ImGuiTextBuffer Buf; ImGuiTextFilter Filter; ImVector LineOffsets; // Index to lines offset. We maintain this with AddLog() calls, allowing us to have a random access on lines - bool AutoScroll; - bool ScrollToBottom; + bool AutoScroll; // Keep scrolling if already at the bottom ExampleAppLog() { AutoScroll = true; - ScrollToBottom = false; Clear(); } @@ -3794,8 +3788,6 @@ struct ExampleAppLog for (int new_size = Buf.size(); old_size < new_size; old_size++) if (Buf[old_size] == '\n') LineOffsets.push_back(old_size + 1); - if (AutoScroll) - ScrollToBottom = true; } void Draw(const char* title, bool* p_open = NULL) @@ -3809,9 +3801,7 @@ struct ExampleAppLog // Options menu if (ImGui::BeginPopup("Options")) { - if (ImGui::Checkbox("Auto-scroll", &AutoScroll)) - if (AutoScroll) - ScrollToBottom = true; + ImGui::Checkbox("Auto-scroll", &AutoScroll); ImGui::EndPopup(); } @@ -3876,9 +3866,9 @@ struct ExampleAppLog } ImGui::PopStyleVar(); - if (ScrollToBottom) + if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) ImGui::SetScrollHereY(1.0f); - ScrollToBottom = false; + ImGui::EndChild(); ImGui::End(); } diff --git a/imgui_internal.h b/imgui_internal.h index 366c682ced7c3..d557f99c40760 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1460,8 +1460,8 @@ namespace ImGui IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); - IMGUI_API void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); - IMGUI_API void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); + IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x); + IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y); IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4c65ed9cb0fad..b883ea0279c41 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3637,8 +3637,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } From 26f14e056c01649af1f64f73e08c65900a932ad0 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jul 2019 18:48:39 -0700 Subject: [PATCH 056/200] Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or until a short delay expires (2 seconds). This allow uninterrupted scroll even if child windows are passing under the mouse cursor. (#2604) --- docs/CHANGELOG.txt | 5 ++++- imgui.cpp | 38 ++++++++++++++++++++++++++++++++------ imgui_internal.h | 5 +++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index da56984afdf9b..f5b3bdb0006d6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,7 +53,6 @@ Other Changes: any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). - Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). -- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Combo: Hide arrow when there's not enough space even for the square button. - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column @@ -67,12 +66,16 @@ Other Changes: - InputTextMultiline: Fixed vertical scrolling tracking glitch. - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). +- Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or + until a short delay expires (2 seconds). This allow uninterrupted scroll even if child windows are + passing under the mouse cursor. (#2604) - Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling: // (Submit items..) if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) // Keep scrolling at the bottom if already ImGui::SetScrollHereY(1.0f); - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] +- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. diff --git a/imgui.cpp b/imgui.cpp index b473f7fa65c9d..9dc43e0ce89cd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1042,6 +1042,7 @@ static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time // Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by back-end) static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f; // Extend outside and inside windows. Affect FindHoveredWindow(). static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time. +static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 2.00f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certaint time, unless mouse moved. //------------------------------------------------------------------------- // [SECTION] FORWARD DECLARATIONS @@ -3465,19 +3466,45 @@ static void ImGui::UpdateMouseInputs() } } -void ImGui::UpdateMouseWheel() +static void StartLockWheelingWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (!g.HoveredWindow || g.HoveredWindow->Collapsed) + if (g.WheelingWindow == window) return; + g.WheelingWindow = window; + g.WheelingWindowRefMousePos = g.IO.MousePos; + g.WheelingWindowTimer = WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER; +} + +void ImGui::UpdateMouseWheel() +{ + ImGuiContext& g = *GImGui; + + // Reset the locked window if we move the mouse or after the timer elapses + if (g.WheelingWindow != NULL) + { + g.WheelingWindowTimer -= g.IO.DeltaTime; + if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) > g.IO.MouseDragThreshold * g.IO.MouseDragThreshold) + g.WheelingWindowTimer = 0.0f; + if (g.WheelingWindowTimer <= 0.0f) + { + g.WheelingWindow = NULL; + g.WheelingWindowTimer = 0.0f; + } + } + if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) return; + ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow; + if (!window || window->Collapsed) + return; + // Zoom / Scale window // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned. if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling) { - ImGuiWindow* window = g.HoveredWindow; + StartLockWheelingWindow(window); const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); const float scale = new_font_scale / window->FontWindowScale; window->FontWindowScale = new_font_scale; @@ -3493,13 +3520,12 @@ void ImGui::UpdateMouseWheel() // Mouse wheel scrolling // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent - // FIXME: Lock scrolling window while not moving (see #2604) // Vertical Mouse Wheel scrolling const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; if (wheel_y != 0.0f && !g.IO.KeyCtrl) { - ImGuiWindow* window = g.HoveredWindow; + StartLockWheelingWindow(window); while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) window = window->ParentWindow; if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) @@ -3514,7 +3540,7 @@ void ImGui::UpdateMouseWheel() const float wheel_x = (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheelH : (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; if (wheel_x != 0.0f && !g.IO.KeyCtrl) { - ImGuiWindow* window = g.HoveredWindow; + StartLockWheelingWindow(window); while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) window = window->ParentWindow; if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) diff --git a/imgui_internal.h b/imgui_internal.h index d557f99c40760..088fbca9289c6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -868,6 +868,9 @@ struct ImGuiContext ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. + ImGuiWindow* WheelingWindow; + ImVec2 WheelingWindowRefMousePos; + float WheelingWindowTimer; // Item/widgets state and tracking information ImGuiID HoveredId; // Hovered widget @@ -1058,6 +1061,8 @@ struct ImGuiContext HoveredWindow = NULL; HoveredRootWindow = NULL; MovingWindow = NULL; + WheelingWindow = NULL; + WheelingWindowTimer = 0.0f; HoveredId = 0; HoveredIdAllowOverlap = false; From 1820aaf44419e7474e46aaa9657b36cf915edb23 Mon Sep 17 00:00:00 2001 From: luk1337 Date: Tue, 23 Jul 2019 18:41:27 +0200 Subject: [PATCH 057/200] imgui_freetype: Initialize FT_MemoryRec_ struct manually (#2686) This fixes gcc warning: missing field 'alloc' initializer [-Wmissing-field-initializers] --- misc/freetype/imgui_freetype.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index d0d2580d32138..d3f2bf54b2e60 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -646,7 +646,8 @@ static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) { // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html - FT_MemoryRec_ memory_rec = { 0 }; + FT_MemoryRec_ memory_rec = {}; + memory_rec.user = NULL; memory_rec.alloc = &FreeType_Alloc; memory_rec.free = &FreeType_Free; memory_rec.realloc = &FreeType_Realloc; From 51853292cc0c4d7a01b056266e5dedc066490b61 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jul 2019 09:49:17 -0700 Subject: [PATCH 058/200] ImDrawList: Using ImDrawCornerFlags instead of int in various apis. Demo: Using ImGuiColorEditrFlags instead of int. --- imgui.h | 9 +++++---- imgui_demo.cpp | 2 +- imgui_draw.cpp | 14 +++++++------- imgui_widgets.cpp | 1 + 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/imgui.h b/imgui.h index cdfa426d8c798..e14f564e1f7bd 100644 --- a/imgui.h +++ b/imgui.h @@ -1837,6 +1837,7 @@ struct ImDrawListSplitter enum ImDrawCornerFlags_ { + ImDrawCornerFlags_None = 0, ImDrawCornerFlags_TopLeft = 1 << 0, // 0x1 ImDrawCornerFlags_TopRight = 1 << 1, // 0x2 ImDrawCornerFlags_BotLeft = 1 << 2, // 0x4 @@ -1897,8 +1898,8 @@ struct ImDrawList // Primitives IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4-bits corresponding to which corner to round - IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) + IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4-bits corresponding to which corner to round + IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f); IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col); @@ -1910,7 +1911,7 @@ struct ImDrawList IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = IM_COL32_WHITE); - IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners = ImDrawCornerFlags_All); + IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); @@ -1924,7 +1925,7 @@ struct ImDrawList IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); - IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); + IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // Advanced IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 257524d5a96a2..b7b48a52ebbb1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1112,7 +1112,7 @@ static void ShowDemoWindowWidgets() ImGui::Checkbox("With Drag and Drop", &drag_and_drop); ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); - int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); + ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); ImGui::Text("Color widget:"); ImGui::SameLine(); HelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n"); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e7c5e82eea006..45cf9ecb86aeb 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -943,7 +943,7 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV } } -void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners) +void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawCornerFlags rounding_corners) { rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f); @@ -978,24 +978,24 @@ void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thic } // a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly. -void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness) +void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; if (Flags & ImDrawListFlags_AntiAliasedLines) - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners_flags); + PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners); else - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners_flags); // Better looking lower-right corner and rounded non-AA shapes. + PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes. PathStroke(col, true, thickness); } -void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags) +void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) { if ((col & IM_COL32_A_MASK) == 0) return; if (rounding > 0.0f) { - PathRect(a, b, rounding, rounding_corners_flags); + PathRect(a, b, rounding, rounding_corners); PathFillConvex(col); } else @@ -1164,7 +1164,7 @@ void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, cons PopTextureID(); } -void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners) +void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) { if ((col & IM_COL32_A_MASK) == 0) return; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b883ea0279c41..9915a24c1f80c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1088,6 +1088,7 @@ bool ImGui::RadioButton(const char* label, bool active) return pressed; } +// FIXME: This would work nicely if it was a public template, e.g. 'template RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it.. bool ImGui::RadioButton(const char* label, int* v, int v_button) { const bool pressed = RadioButton(label, *v == v_button); From baae057a035014bbc0500e10616796e420d8b766 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jul 2019 11:50:41 -0700 Subject: [PATCH 059/200] Internals: Merge in minor noise from wip Tables branch to simplify further merging. --- imgui.cpp | 40 ++++++++++++++++++++++++++++++++++------ imgui_internal.h | 19 ++++++++++--------- imgui_widgets.cpp | 14 ++++++++------ 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9dc43e0ce89cd..4ecb2897d81c1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3934,6 +3934,11 @@ void ImGui::Shutdown(ImGuiContext* context) g.DrawDataBuilder.ClearFreeMemory(); g.BackgroundDrawList.ClearFreeMemory(); g.ForegroundDrawList.ClearFreeMemory(); + + g.TabBars.Clear(); + g.CurrentTabBarStack.clear(); + g.ShrinkWidthBuffer.clear(); + g.PrivateClipboard.clear(); g.InputTextState.ClearFreeMemory(); @@ -6744,7 +6749,8 @@ void ImGui::SetNextWindowBgAlpha(float alpha) // FIXME: This is in window space (not screen space!). We should try to obsolete all those functions. ImVec2 ImGui::GetContentRegionMax() { - ImGuiWindow* window = GImGui->CurrentWindow; + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; ImVec2 mx = window->ContentsRegionRect.Max - window->Pos; if (window->DC.CurrentColumns) mx.x = window->WorkRect.Max.x - window->Pos.x; @@ -6754,7 +6760,8 @@ ImVec2 ImGui::GetContentRegionMax() // [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. ImVec2 ImGui::GetContentRegionMaxAbs() { - ImGuiWindow* window = GImGui->CurrentWindow; + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; ImVec2 mx = window->ContentsRegionRect.Max; if (window->DC.CurrentColumns) mx.x = window->WorkRect.Max.x; @@ -9650,14 +9657,16 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; } + // State enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Contents, WRT_ContentsRegionRect, WRT_Count }; // Windows Rect Type const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" }; - - static bool show_windows_begin_order = false; static bool show_windows_rects = false; static int show_windows_rect_type = WRT_WorkRect; + static bool show_windows_begin_order = false; static bool show_drawcmd_clip_rects = true; + // Basic info + ImGuiContext& g = *GImGui; ImGuiIO& io = ImGui::GetIO(); ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); @@ -9666,6 +9675,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("%d active allocations", io.MetricsActiveAllocations); ImGui::Separator(); + // Helper functions to display common structures: + // - NodeDrawList + // - NodeColumns + // - NodeWindow + // - NodeWindows + // - NodeTabBar struct Funcs { static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) @@ -9830,8 +9845,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; - // Access private state, we are going to display the draw lists from last frame - ImGuiContext& g = *GImGui; Funcs::NodeWindows(g.Windows, "Windows"); if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { @@ -9857,6 +9870,20 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } +#if 0 + if (ImGui::TreeNode("Docking")) + { + ImGui::TreePop(); + } +#endif + +#if 0 + if (ImGui::TreeNode("Tables", "Tables (%d)", g.Tables.Data.Size)) + { + ImGui::TreePop(); + } +#endif + if (ImGui::TreeNode("Internal state")) { const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); @@ -9903,6 +9930,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } + // Tool: Display windows Rectangles and Begin Order if (show_windows_rects || show_windows_begin_order) { for (int n = 0; n < g.Windows.Size; n++) diff --git a/imgui_internal.h b/imgui_internal.h index 088fbca9289c6..d7c37c5f9f337 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -358,7 +358,8 @@ enum ImGuiSelectableFlagsPrivate_ ImGuiSelectableFlags_PressedOnClick = 1 << 21, ImGuiSelectableFlags_PressedOnRelease = 1 << 22, ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 23, // FIXME: We may be able to remove this (added in 6251d379 for menus) - ImGuiSelectableFlags_AllowItemOverlap = 1 << 24 + ImGuiSelectableFlags_AllowItemOverlap = 1 << 24, + ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 25 // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. }; // Extend ImGuiTreeNodeFlags_ @@ -827,13 +828,13 @@ struct ImGuiShrinkWidthItem float Width; }; -struct ImGuiTabBarRef +struct ImGuiPtrOrIndex { - ImGuiTabBar* Ptr; // Either field can be set, not both. Dock node tab bars are loose while BeginTabBar() ones are in a pool. - int IndexInMainPool; + void* Ptr; // Either field can be set, not both. e.g. Dock node tab bars are loose while BeginTabBar() ones are in a pool. + int Index; // Usually index in a main pool. - ImGuiTabBarRef(ImGuiTabBar* ptr) { Ptr = ptr; IndexInMainPool = -1; } - ImGuiTabBarRef(int index_in_main_pool) { Ptr = NULL; IndexInMainPool = index_in_main_pool; } + ImGuiPtrOrIndex(void* ptr) { Ptr = ptr; Index = -1; } + ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } }; //----------------------------------------------------------------------------- @@ -986,9 +987,9 @@ struct ImGuiContext unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads // Tab bars - ImPool TabBars; ImGuiTabBar* CurrentTabBar; - ImVector CurrentTabBarStack; + ImPool TabBars; + ImVector CurrentTabBarStack; ImVector ShrinkWidthBuffer; // Widget state @@ -1425,7 +1426,7 @@ struct ImGuiTabBar float ScrollingSpeed; ImGuiTabBarFlags Flags; ImGuiID ReorderRequestTabId; - int ReorderRequestDir; + ImS8 ReorderRequestDir; bool WantLayout; bool VisibleTabWasSubmitted; short LastTabItemIdx; // For BeginTabItem()/EndTabItem() diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9915a24c1f80c..3c48d247514df 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5490,6 +5490,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render + if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld)) + hovered = true; if (hovered || selected) { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); @@ -6271,18 +6273,18 @@ static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const voi return (int)(a->Offset - b->Offset); } -static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiTabBarRef& ref) +static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref) { ImGuiContext& g = *GImGui; - return ref.Ptr ? ref.Ptr : g.TabBars.GetByIndex(ref.IndexInMainPool); + return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index); } -static ImGuiTabBarRef GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar) +static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar) { ImGuiContext& g = *GImGui; if (g.TabBars.Contains(tab_bar)) - return ImGuiTabBarRef(g.TabBars.GetIndex(tab_bar)); - return ImGuiTabBarRef(tab_bar); + return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar)); + return ImGuiPtrOrIndex(tab_bar); } bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags) @@ -6637,7 +6639,7 @@ void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* IM_ASSERT(dir == -1 || dir == +1); IM_ASSERT(tab_bar->ReorderRequestTabId == 0); tab_bar->ReorderRequestTabId = tab->ID; - tab_bar->ReorderRequestDir = dir; + tab_bar->ReorderRequestDir = (ImS8)dir; } static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar) From 824e8c53b43aa1bd0ed799ad563f7fa01cde4484 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jul 2019 21:26:15 -0700 Subject: [PATCH 060/200] Internals: Added IMGUI_DEBUG_INI_SETTINGS. Made IMGUI_DEBUG_LOG redefinable in imconfig.h. Comments. Fix to allow Metrics's NodeWindow() being called with a NULL window. --- imgui.cpp | 15 +++++++++++++-- imgui_internal.h | 7 +++++-- imgui_widgets.cpp | 6 +++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4ecb2897d81c1..c1b78907adbea 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -998,6 +998,7 @@ CODE // Debug options #define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL #define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window +#define IMGUI_DEBUG_INI_SETTINGS 0 // Save additional comments in .ini file // Visual Studio warnings #ifdef _MSC_VER @@ -4795,6 +4796,7 @@ ImGuiWindow* ImGui::FindWindowByName(const char* name) static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; + //IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags); // Create window the first time ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name); @@ -9265,8 +9267,12 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) ImGuiContext& g = *GImGui; g.SettingsWindows.push_back(ImGuiWindowSettings()); ImGuiWindowSettings* settings = &g.SettingsWindows.back(); - if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() +#if !IMGUI_DEBUG_INI_SETTINGS + // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() + // Preserve the full string when IMGUI_DEBUG_INI_SETTINGS is set to make .ini inspection easier. + if (const char* p = strstr(name, "###")) name = p; +#endif settings->Name = ImStrdup(name); settings->ID = ImHashStr(name); return settings; @@ -9791,7 +9797,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) static void NodeWindow(ImGuiWindow* window, const char* label) { - if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) + if (window == NULL) + { + ImGui::BulletText("%s: NULL", label); + return; + } + if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, (window->Active || window->WasActive), window)) return; ImGuiWindowFlags flags = window->Flags; NodeDrawList(window, window->DrawList, "DrawList"); diff --git a/imgui_internal.h b/imgui_internal.h index d7c37c5f9f337..dd2b8927a4829 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -141,12 +141,15 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #define IM_NEWLINE "\n" #endif #define IM_TABSIZE (4) - -#define IMGUI_DEBUG_LOG(_FMT,...) printf("[%05d] " _FMT, GImGui->FrameCount, __VA_ARGS__) #define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 +// Debug Logging +#ifndef IMGUI_DEBUG_LOG +#define IMGUI_DEBUG_LOG(_FMT,...) printf("[%05d] " _FMT, GImGui->FrameCount, __VA_ARGS__) +#endif + // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall #ifdef _MSC_VER #define IMGUI_CDECL __cdecl diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3c48d247514df..5717f8e2e4f3f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5935,6 +5935,10 @@ void ImGui::EndMainMenuBar() End(); } +// FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere.. +// Currently the main responsibility of this function being to setup clip-rect + horizontal layout + menu navigation layer. +// Ideally we also want this to be responsible for claiming space out of the main window scrolling rectangle, in which case ImGuiWindowFlags_MenuBar will become unnecessary. +// Then later the same system could be used for multiple menu-bars, scrollbars, side-bars. bool ImGui::BeginMenuBar() { ImGuiWindow* window = GetCurrentWindow(); @@ -5944,7 +5948,7 @@ bool ImGui::BeginMenuBar() return false; IM_ASSERT(!window->DC.MenuBarAppending); - BeginGroup(); // Backup position on layer 0 + BeginGroup(); // Backup position on layer 0 // FIXME: Misleading to use a group for that backup/restore PushID("##menubar"); // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. From d057550209d794461744a91c812bf8e9e264f32f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jul 2019 09:48:34 -0700 Subject: [PATCH 061/200] Fixed Clang 8.0 warning "empty expression statement has no effect; remove unnecessary ';' to silence this" warning [-Wextra-semi-stmt] + Comment --- imgui.cpp | 2 +- imgui.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c1b78907adbea..0a2a53ee00c5c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8171,7 +8171,7 @@ static void ImGui::NavUpdate() // Update Keyboard->Nav inputs mapping if (nav_keyboard_active) { - #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } + #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } } while (0) NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); diff --git a/imgui.h b/imgui.h index e14f564e1f7bd..0b5ad55855354 100644 --- a/imgui.h +++ b/imgui.h @@ -327,7 +327,7 @@ namespace ImGui IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, IMGUI_API void PopItemWidth(); IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) - IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position + IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space IMGUI_API void PopTextWrapPos(); IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets From 7a26a49f080426bd09c2034a01a57eeb81f46a21 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 26 Jul 2019 12:08:29 -0700 Subject: [PATCH 062/200] Internal: Added IsMouseDragPastThreshold(). Tweaks. Todo. Demo: Showing how to use the format parameter of Slider/Drag functions to display the name of an enum value instead of the underlying integer value --- docs/CHANGELOG.txt | 2 ++ docs/TODO.txt | 2 ++ imgui.cpp | 17 ++++++++++++++--- imgui_demo.cpp | 17 ++++++++++++++--- imgui_internal.h | 1 + 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f5b3bdb0006d6..540e1e58128c0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -95,6 +95,8 @@ Other Changes: also this type was added in 1.71 and not advertised as a public-facing feature). - Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file. - Demo: Log, Console: Using a simpler stateless pattern for auto-scrolling. +- Demo: Widgets: Showing how to use the format parameter of Slider/Drag functions to display the name + of an enum value instead of the underlying integer value. - Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer. - Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them. - Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), diff --git a/docs/TODO.txt b/docs/TODO.txt index d0f2e84e66704..f289ebab77b3b 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -89,6 +89,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - input text: decorrelate layout from inputs - e.g. what's the easiest way to implement a nice IP/Mac address input editor? - input text: global callback system so user can plug in an expression evaluator easily. (#1691) - input text: force scroll to end or scroll to a given line/contents (so user can implement a log or a search feature) + - input text: a way to preview completion (e.g. disabled text completing from the cursor) - input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there. - input text: a way for the user to provide syntax coloring. - input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count. @@ -122,6 +123,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - columns: option to alternate background colors on odd/even scanlines. - columns: allow columns to recurse. - columns: allow a same columns set to be interrupted by e.g. CollapsingHeader and resume with columns in sync when moving them. + - columns: sizing is lossy when columns width is very small (default width may turn negative etc.) - columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125) - columns: flag to add horizontal separator above/below? - columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets) diff --git a/imgui.cpp b/imgui.cpp index 0a2a53ee00c5c..27c90033a51be 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4433,17 +4433,25 @@ bool ImGui::IsMouseDoubleClicked(int button) return g.IO.MouseDoubleClicked[button]; } -bool ImGui::IsMouseDragging(int button, float lock_threshold) +// [Internal] This doesn't test if the button is presed +bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (!g.IO.MouseDown[button]) - return false; if (lock_threshold < 0.0f) lock_threshold = g.IO.MouseDragThreshold; return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; } +bool ImGui::IsMouseDragging(int button, float lock_threshold) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + if (!g.IO.MouseDown[button]) + return false; + return IsMouseDragPastThreshold(button, lock_threshold); +} + ImVec2 ImGui::GetMousePos() { return GImGui->IO.MousePos; @@ -9719,6 +9727,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (!node_open) return; + if (window && !window->WasActive) + ImGui::Text("(Note: owning Window is inactive: DrawList is not being rendered!)"); + int elem_offset = 0; for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b7b48a52ebbb1..570d18dbaddaf 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -539,8 +539,19 @@ static void ShowDemoWindowWidgets() static float f1=0.123f, f2=0.0f; ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f); + static float angle = 0.0f; ImGui::SliderAngle("slider angle", &angle); + + // Using the format string to display a name instead of an integer. + // Here we completely omit '%d' from the format string, so it'll only display a name. + // This technique can also be used with DragInt(). + enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT }; + const char* element_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" }; + static int current_element = Element_Fire; + const char* current_element_name = (current_element >= 0 && current_element < Element_COUNT) ? element_names[current_element] : "Unknown"; + ImGui::SliderInt("slider enum", ¤t_element, 0, Element_COUNT - 1, current_element_name); + ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer."); } { @@ -1782,9 +1793,9 @@ static void ShowDemoWindowLayout() ImGui::Text("SetNextItemWidth/PushItemWidth(-1)"); ImGui::SameLine(); HelpMarker("Align to right edge"); ImGui::PushItemWidth(-1); - ImGui::DragFloat("float##5a", &f); - ImGui::DragFloat("float##5b", &f); - ImGui::DragFloat("float##5c", &f); + ImGui::DragFloat("##float5a", &f); + ImGui::DragFloat("##float5b", &f); + ImGui::DragFloat("##float5c", &f); ImGui::PopItemWidth(); ImGui::TreePop(); diff --git a/imgui_internal.h b/imgui_internal.h index dd2b8927a4829..522914d32103b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1556,6 +1556,7 @@ namespace ImGui IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel); // Inputs + inline bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { const int key_index = GImGui->IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } inline bool IsNavInputDown(ImGuiNavInput n) { return GImGui->IO.NavInputs[n] > 0.0f; } inline bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) { return GetNavInputAmount(n, mode) > 0.0f; } From ecb9b1e2eba5becc38019b5c9f75fba711cd881b Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 27 Jul 2019 17:06:17 -0700 Subject: [PATCH 063/200] Version 1.72 --- docs/CHANGELOG.txt | 33 +++++++++++++++++---------------- docs/README.md | 23 ++++++++++++----------- examples/README.txt | 2 +- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- misc/fonts/README.txt | 2 +- 10 files changed, 39 insertions(+), 37 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 540e1e58128c0..a9fcc258f120b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -30,7 +30,7 @@ HOW TO UPDATE? ----------------------------------------------------------------------- - VERSION 1.72 (In Progress) + VERSION 1.72 (Released 2019-07-27) ----------------------------------------------------------------------- Breaking Changes: @@ -45,37 +45,38 @@ Breaking Changes: Kept redirection function (will obsolete). (#581, #324) Other Changes: -- Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). -- Window: Mouse wheel scrolling while hovering a child window is automatically forwarded to parent window + comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). +- Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or + until a short delay expires (~2 seconds). This allow uninterrupted scroll even if child windows are + passing under the mouse cursor. (#2604) +- Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to + SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling: + // (Submit items..) + if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) // If scrolling at the already at the bottom.. + ImGui::SetScrollHereY(1.0f); // ..make last item fully visible +- Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] +- Scrolling: Mouse wheel scrolling while hovering a child window is automatically forwarded to parent window if ScrollMax is zero on the scrolling axis. - Also still case if ImGuiWindowFlags_NoScrollWithMouse is set (not new), but previously the forwarding + Also still the case if ImGuiWindowFlags_NoScrollWithMouse is set (not new), but previously the forwarding would be disabled if ImGuiWindowFlags_NoScrollbar was set on the child window, which is not the case any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). +- Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). - Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added - comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). +- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Combo: Hide arrow when there's not enough space even for the square button. +- InputText: Testing for newly added ImGuiKey_KeyPadEnter key. (#2677, #2005) [@amc522] - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) - Columns: Made the right-most edge reaches up to the clipping rectangle (removing half of WindowPadding.x worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset - the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666) + the right-most column, otherwise it's clipping width won't match the other columns). (#125, #2666) - Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) - Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with other column functions. (#2683) - InputTextMultiline: Fixed vertical scrolling tracking glitch. - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). -- Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or - until a short delay expires (2 seconds). This allow uninterrupted scroll even if child windows are - passing under the mouse cursor. (#2604) -- Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to - SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling: - // (Submit items..) - if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) // Keep scrolling at the bottom if already - ImGui::SetScrollHereY(1.0f); -- Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] -- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button of ColorEdit3/ColorEdit4 functions to either side of the inputs. diff --git a/docs/README.md b/docs/README.md index d020ea076ebc7..5a706354fc01c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,10 @@ dear imgui [![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) -_(This library is free as in freedom, but needs your support to sustain its development. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal.)_ +_(This library is available under a free and permissive licence, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.)_ + +Businesses: support continued development via invoiced technical support & maintenance contracts: +
  _E-mail: omarcornut at gmail dot com_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_01.png)](http://www.patreon.com/imgui) @@ -11,9 +14,6 @@ Individuals/hobbyists: support continued maintenance and development via the mon Individuals/hobbyists: support continued maintenance and development via PayPal:
  [![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=WGHNC6MBFLZ2S) -Businesses: support continued maintenance and development via support contracts or sponsoring: -
  _E-mail: omarcornut at gmail dot com_ - Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. @@ -290,7 +290,10 @@ Support dear imgui **How can I help financing further development of Dear ImGui?** -Your contributions are keeping this project alive. The library is free as in freedom, but continued maintenance and development are a full-time endeavor. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. Thank you! +Your contributions are keeping this project alive. The library is available under a free and permissive licence, but continued maintenance and development are a full-time endeavor and I would like to grow the team. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced technical support and maintenance contracts. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal. Thank you! + +Businesses: support continued development via invoiced technical support & maintenance contracts: +
  _E-mail: omarcornut at gmail dot com_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_01.png)](http://www.patreon.com/imgui) @@ -298,22 +301,20 @@ Individuals/hobbyists: support continued maintenance and development via the mon Individuals/hobbyists: support continued maintenance and development via PayPal:
  [![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=WGHNC6MBFLZ2S) -Businesses: support continued maintenance and development via support contracts or sponsoring: -
  _E-mail: omarcornut at gmail dot com_ - Ongoing dear imgui development is financially supported by users and private sponsors, recently: **Platinum-chocolate sponsors** -- **Blizzard Entertainment**. +- Blizzard Entertainment +- Google **Double-chocolate sponsors** - Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn. **Salty caramel supporters** -- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford. +- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, Morten Skaaning, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford. **Caramel supporters** -- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra. +- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis. And all other past and present supporters; THANK YOU! (Please contact me if you would like to be added or removed from this list) diff --git a/examples/README.txt b/examples/README.txt index 5028583bbd57b..ded7d12a0a1ad 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- - dear imgui, v1.72 WIP + dear imgui, v1.72 ----------------------------------------------------------------------- examples/README.txt (This is the README file for the examples/ folder. See docs/ for more documentation) diff --git a/imgui.cpp b/imgui.cpp index 27c90033a51be..ce9e1c1e61793 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 WIP +// dear imgui, v1.72 // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index 0b5ad55855354..23efa5d6d0777 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.72 WIP +// dear imgui, v1.72 // (headers) // See imgui.cpp file for documentation. @@ -46,8 +46,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.72 WIP" -#define IMGUI_VERSION_NUM 17102 +#define IMGUI_VERSION "1.72" +#define IMGUI_VERSION_NUM 17200 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 570d18dbaddaf..af8b422b93c8f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 WIP +// dear imgui, v1.72 // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 45cf9ecb86aeb..a03f58554720e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 WIP +// dear imgui, v1.72 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 522914d32103b..eef74b0f070e6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.72 WIP +// dear imgui, v1.72 // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5717f8e2e4f3f..f06dec60b6a58 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 WIP +// dear imgui, v1.72 // (widgets code) /* diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index cf953cf6f5bcd..a17e9f15ca69c 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -1,4 +1,4 @@ -dear imgui, v1.72 WIP +dear imgui, v1.72 (Font Readme) --------------------------------------- From 9183e7c4267aadfb3d7a28e96092b40a590cf9fc Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jul 2019 15:54:32 -0700 Subject: [PATCH 064/200] Version 1.73 WIP --- docs/CHANGELOG.txt | 5 +++++ examples/README.txt | 2 +- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- misc/fonts/README.txt | 2 +- 9 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a9fcc258f120b..58d2ff63ae76d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -29,6 +29,11 @@ HOW TO UPDATE? - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.73 (In Progress) +----------------------------------------------------------------------- + + ----------------------------------------------------------------------- VERSION 1.72 (Released 2019-07-27) ----------------------------------------------------------------------- diff --git a/examples/README.txt b/examples/README.txt index ded7d12a0a1ad..7e46c8432ab65 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- - dear imgui, v1.72 + dear imgui, v1.73 WIP ----------------------------------------------------------------------- examples/README.txt (This is the README file for the examples/ folder. See docs/ for more documentation) diff --git a/imgui.cpp b/imgui.cpp index ce9e1c1e61793..8cbfa12907cab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 +// dear imgui, v1.73 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index 23efa5d6d0777..ed7712f1b3adb 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.72 +// dear imgui, v1.73 WIP // (headers) // See imgui.cpp file for documentation. @@ -46,8 +46,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.72" -#define IMGUI_VERSION_NUM 17200 +#define IMGUI_VERSION "1.73 WIP" +#define IMGUI_VERSION_NUM 17201 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index af8b422b93c8f..65c0355d279d4 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 +// dear imgui, v1.73 WIP // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a03f58554720e..3e5ca0617ac63 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 +// dear imgui, v1.73 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index eef74b0f070e6..fdade58b61100 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.72 +// dear imgui, v1.73 WIP // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f06dec60b6a58..add9d7cd52359 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72 +// dear imgui, v1.73 WIP // (widgets code) /* diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index a17e9f15ca69c..b8790af627b3a 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -1,4 +1,4 @@ -dear imgui, v1.72 +dear imgui, v1.73 WIP (Font Readme) --------------------------------------- From 85ad8e0e2e4c928d69883dfa7f42bd368adf4ec0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jul 2019 14:26:02 -0700 Subject: [PATCH 065/200] Nav: Fixed an issue with NavFlattened window flag where widgets not entirely fitting in child window (often selectable because of their extruded bits) would be not considered to navigate toward the child window. (#787) This creates a little bit of tension because g.NavDisableHighlight tends to makes the reference point not always visible. Amend c665c15a7d5942037852027cec88de9ccc2494ac --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8cbfa12907cab..ef50ee5b07989 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7761,7 +7761,7 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) if (window->ParentWindow == g.NavWindow) { IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); - if (!window->ClipRect.Contains(cand)) + if (!window->ClipRect.Overlaps(cand)) return false; cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window } From 494d804735a47e1a0f453590b4337948f462558f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jul 2019 15:02:40 -0700 Subject: [PATCH 066/200] Internal: Added ImGuiInputTextState::ClearText() helper. --- imgui_internal.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index fdade58b61100..43a450f8ed28f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -630,22 +630,23 @@ struct IMGUI_API ImGuiInputTextState float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection - - // Temporarily set when active - ImGuiInputTextFlags UserFlags; - ImGuiInputTextCallback UserCallback; - void* UserCallbackData; + ImGuiInputTextFlags UserFlags; // Temporarily set while we call user's callback + ImGuiInputTextCallback UserCallback; // " + void* UserCallbackData; // " ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } + void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } + int GetUndoAvailCount() const { return Stb.undostate.undo_point; } + int GetRedoAvailCount() const { return STB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } + void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation + + // Cursor & Selection void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } bool HasSelection() const { return Stb.select_start != Stb.select_end; } void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } - int GetUndoAvailCount() const { return Stb.undostate.undo_point; } - int GetRedoAvailCount() const { return STB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } - void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation }; // Windows data saved in imgui.ini file From 5ef7445d922fd9fb5c59bedf2dada2926a4100e0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jul 2019 16:48:15 -0700 Subject: [PATCH 067/200] Internal: Avoid using GImGui multiple times in same function. --- imgui.cpp | 42 ++++++++++++++++++++++++++---------------- imgui_widgets.cpp | 2 +- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ef50ee5b07989..0c24e497bfdef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3171,13 +3171,15 @@ void ImGui::MemFree(void* ptr) const char* ImGui::GetClipboardText() { - return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : ""; + ImGuiContext& g = *GImGui; + return g.IO.GetClipboardTextFn ? g.IO.GetClipboardTextFn(g.IO.ClipboardUserData) : ""; } void ImGui::SetClipboardText(const char* text) { - if (GImGui->IO.SetClipboardTextFn) - GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text); + ImGuiContext& g = *GImGui; + if (g.IO.SetClipboardTextFn) + g.IO.SetClipboardTextFn(g.IO.ClipboardUserData, text); } const char* ImGui::GetVersion() @@ -4331,15 +4333,18 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c int ImGui::GetKeyIndex(ImGuiKey imgui_key) { IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT); - return GImGui->IO.KeyMap[imgui_key]; + ImGuiContext& g = *GImGui; + return g.IO.KeyMap[imgui_key]; } // Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]! bool ImGui::IsKeyDown(int user_key_index) { - if (user_key_index < 0) return false; - IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown)); - return GImGui->IO.KeysDown[user_key_index]; + if (user_key_index < 0) + return false; + ImGuiContext& g = *GImGui; + IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); + return g.IO.KeysDown[user_key_index]; } int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate) @@ -4948,7 +4953,7 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s float target_x = window->ScrollTarget.x; if (snap_on_edges && cr_x <= 0.0f && target_x <= window->WindowPadding.x) target_x = 0.0f; - else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + GImGui->Style.ItemSpacing.x) + else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + g.Style.ItemSpacing.x) target_x = window->ContentSize.x + window->WindowPadding.x * 2.0f; scroll.x = target_x - cr_x * window->InnerRect.GetWidth(); } @@ -6139,7 +6144,7 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - const ImGuiStyle& style = GImGui->Style; + const ImGuiStyle& style = g.Style; const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); window->DC.ItemWidthStack.push_back(w_item_last); @@ -6969,7 +6974,8 @@ void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); window->ScrollTargetCenterRatio.x = center_x_ratio; @@ -6978,7 +6984,8 @@ void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); window->ScrollTargetCenterRatio.y = center_y_ratio; @@ -6987,19 +6994,21 @@ void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. void ImGui::SetScrollHereX(float center_x_ratio) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; float target_x = window->DC.LastItemRect.Min.x - window->Pos.x; // Left of last item, in window space float last_item_width = window->DC.LastItemRect.GetWidth(); - target_x += (last_item_width * center_x_ratio) + (GImGui->Style.ItemSpacing.x * (center_x_ratio - 0.5f) * 2.0f); // Precisely aim before, in the middle or after the last item. + target_x += (last_item_width * center_x_ratio) + (g.Style.ItemSpacing.x * (center_x_ratio - 0.5f) * 2.0f); // Precisely aim before, in the middle or after the last item. SetScrollFromPosX(target_x, center_x_ratio); } // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. void ImGui::SetScrollHereY(float center_y_ratio) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space - target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. + target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (g.Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. SetScrollFromPosY(target_y, center_y_ratio); } @@ -9640,7 +9649,8 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) { // Notify OS Input Method Editor of text input position - if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle) + ImGuiIO& io = ImGui::GetIO(); + if (HWND hwnd = (HWND)io.ImeWindowHandle) if (HIMC himc = ::ImmGetContext(hwnd)) { COMPOSITIONFORM cf; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index add9d7cd52359..07e8d2e34b492 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3123,7 +3123,7 @@ namespace ImStb static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; } static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; } -static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx+char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); } +static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); } static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; } static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx) From 1b1e53928843e4c2fe645dba39bcd0f7a333318f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jul 2019 18:21:44 -0700 Subject: [PATCH 068/200] Internal: Moved NavScrollToBringItemIntoView() declaration to imgui_internal.h. Fixed spacing missing in 494d804. Fixed changelog wreck from 1.72. --- docs/CHANGELOG.txt | 2 +- imgui.cpp | 3 +-- imgui_demo.cpp | 14 +++++++------- imgui_internal.h | 15 ++++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 58d2ff63ae76d..c5652c968114d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,7 +50,6 @@ Breaking Changes: Kept redirection function (will obsolete). (#581, #324) Other Changes: - comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). - Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or until a short delay expires (~2 seconds). This allow uninterrupted scroll even if child windows are passing under the mouse cursor. (#2604) @@ -67,6 +66,7 @@ Other Changes: any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). - Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71). - Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added + comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). - Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small. - Combo: Hide arrow when there's not enough space even for the square button. - InputText: Testing for newly added ImGuiKey_KeyPadEnter key. (#2677, #2005) [@amc522] diff --git a/imgui.cpp b/imgui.cpp index 0c24e497bfdef..085aa0a083936 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8139,8 +8139,7 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput } // Scroll to keep newly navigated item fully into view -// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. -static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) +void ImGui::NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) { ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 65c0355d279d4..7fb29ec7fa780 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2064,23 +2064,23 @@ static void ShowDemoWindowLayout() // Vertical scroll functions HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position."); - static bool track = true; static int track_item = 50; + static bool enable_track = true; static float scroll_to_off_px = 0.0f; static float scroll_to_pos_px = 200.0f; - ImGui::Checkbox("Track", &track); + ImGui::Checkbox("Track", &enable_track); ImGui::PushItemWidth(100); - ImGui::SameLine(140); track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); + ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); bool scroll_to_off = ImGui::Button("Scroll Offset"); ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, 9999, "+%.0f px"); bool scroll_to_pos = ImGui::Button("Scroll To Pos"); ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, 0, 9999, "X/Y = %.0f px"); - ImGui::PopItemWidth(); + if (scroll_to_off || scroll_to_pos) - track = false; + enable_track = false; ImGuiStyle& style = ImGui::GetStyle(); float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5; @@ -2101,7 +2101,7 @@ static void ShowDemoWindowLayout() ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f); for (int item = 0; item < 100; item++) { - if (track && item == track_item) + if (enable_track && item == track_item) { ImGui::TextColored(ImVec4(1,1,0,1), "Item %d", item); ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom @@ -2133,7 +2133,7 @@ static void ShowDemoWindowLayout() ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f); for (int item = 0; item < 100; item++) { - if (track && item == track_item) + if (enable_track && item == track_item) { ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item); ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right diff --git a/imgui_internal.h b/imgui_internal.h index 43a450f8ed28f..1cc8e99020d9f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -634,19 +634,19 @@ struct IMGUI_API ImGuiInputTextState ImGuiInputTextCallback UserCallback; // " void* UserCallbackData; // " - ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } + ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } - void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } + void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } int GetUndoAvailCount() const { return Stb.undostate.undo_point; } int GetRedoAvailCount() const { return STB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation // Cursor & Selection - void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } - bool HasSelection() const { return Stb.select_start != Stb.select_end; } - void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } - void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } + void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking + void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } + bool HasSelection() const { return Stb.select_start != Stb.select_end; } + void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } + void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } }; // Windows data saved in imgui.ini file @@ -1549,6 +1549,7 @@ namespace ImGui IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); + IMGUI_API void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect); IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); From 3548fb80134cdf90565241d0930db38ba1d7fcf7 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jul 2019 20:04:02 -0700 Subject: [PATCH 069/200] Internal refactor: moved all Scroll related functions in a same spot. --- imgui.cpp | 322 ++++++++++++++++++++++++----------------------- imgui_internal.h | 8 +- 2 files changed, 169 insertions(+), 161 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 085aa0a083936..316a71ee921ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -72,6 +72,7 @@ CODE // [SECTION] ImGuiListClipper // [SECTION] RENDER HELPERS // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) +// [SECTION] SCROLLING // [SECTION] TOOLTIPS // [SECTION] POPUPS // [SECTION] KEYBOARD/GAMEPAD NAVIGATION @@ -4943,40 +4944,6 @@ ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window) return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents)); } -static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges) -{ - ImGuiContext& g = *GImGui; - ImVec2 scroll = window->Scroll; - if (window->ScrollTarget.x < FLT_MAX) - { - float cr_x = window->ScrollTargetCenterRatio.x; - float target_x = window->ScrollTarget.x; - if (snap_on_edges && cr_x <= 0.0f && target_x <= window->WindowPadding.x) - target_x = 0.0f; - else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + g.Style.ItemSpacing.x) - target_x = window->ContentSize.x + window->WindowPadding.x * 2.0f; - scroll.x = target_x - cr_x * window->InnerRect.GetWidth(); - } - if (window->ScrollTarget.y < FLT_MAX) - { - // 'snap_on_edges' allows for a discontinuity at the edge of scrolling limits to take account of WindowPadding so that scrolling to make the last item visible scroll far enough to see the padding. - float cr_y = window->ScrollTargetCenterRatio.y; - float target_y = window->ScrollTarget.y; - if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y) - target_y = 0.0f; - if (snap_on_edges && cr_y >= 1.0f && target_y >= window->ContentSize.y + window->WindowPadding.y + g.Style.ItemSpacing.y) - target_y = window->ContentSize.y + window->WindowPadding.y * 2.0f; - scroll.y = target_y - cr_y * window->InnerRect.GetHeight(); - } - scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); - if (!window->Collapsed && !window->SkipItems) - { - scroll.x = ImMin(scroll.x, window->ScrollMax.x); - scroll.y = ImMin(scroll.y, window->ScrollMax.y); - } - return scroll; -} - static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags) { if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) @@ -6921,97 +6888,6 @@ void ImGui::SetCursorScreenPos(const ImVec2& pos) window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); } -float ImGui::GetScrollX() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Scroll.x; -} - -float ImGui::GetScrollY() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Scroll.y; -} - -float ImGui::GetScrollMaxX() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ScrollMax.x; -} - -float ImGui::GetScrollMaxY() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ScrollMax.y; -} - -void ImGui::SetScrollX(float scroll_x) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTarget.x = scroll_x; - window->ScrollTargetCenterRatio.x = 0.0f; -} - -void ImGui::SetScrollY(float scroll_y) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTarget.y = scroll_y; - window->ScrollTargetCenterRatio.y = 0.0f; -} - -void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x) -{ - window->ScrollTarget.x = new_scroll_x; - window->ScrollTargetCenterRatio.x = 0.0f; -} - -void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) -{ - window->ScrollTarget.y = new_scroll_y; - window->ScrollTargetCenterRatio.y = 0.0f; -} - -void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) -{ - // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); - window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); - window->ScrollTargetCenterRatio.x = center_x_ratio; -} - -void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) -{ - // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); - window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); - window->ScrollTargetCenterRatio.y = center_y_ratio; -} - -// center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. -void ImGui::SetScrollHereX(float center_x_ratio) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float target_x = window->DC.LastItemRect.Min.x - window->Pos.x; // Left of last item, in window space - float last_item_width = window->DC.LastItemRect.GetWidth(); - target_x += (last_item_width * center_x_ratio) + (g.Style.ItemSpacing.x * (center_x_ratio - 0.5f) * 2.0f); // Precisely aim before, in the middle or after the last item. - SetScrollFromPosX(target_x, center_x_ratio); -} - -// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. -void ImGui::SetScrollHereY(float center_y_ratio) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space - target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (g.Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. - SetScrollFromPosY(target_y, center_y_ratio); -} - void ImGui::ActivateItem(ImGuiID id) { ImGuiContext& g = *GImGui; @@ -7248,6 +7124,167 @@ void ImGui::Unindent(float indent_w) window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; } + +//----------------------------------------------------------------------------- +// [SECTION] SCROLLING +//----------------------------------------------------------------------------- + +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges) +{ + ImGuiContext& g = *GImGui; + ImVec2 scroll = window->Scroll; + if (window->ScrollTarget.x < FLT_MAX) + { + float cr_x = window->ScrollTargetCenterRatio.x; + float target_x = window->ScrollTarget.x; + if (snap_on_edges && cr_x <= 0.0f && target_x <= window->WindowPadding.x) + target_x = 0.0f; + else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + g.Style.ItemSpacing.x) + target_x = window->ContentSize.x + window->WindowPadding.x * 2.0f; + scroll.x = target_x - cr_x * window->InnerRect.GetWidth(); + } + if (window->ScrollTarget.y < FLT_MAX) + { + // 'snap_on_edges' allows for a discontinuity at the edge of scrolling limits to take account of WindowPadding so that scrolling to make the last item visible scroll far enough to see the padding. + float cr_y = window->ScrollTargetCenterRatio.y; + float target_y = window->ScrollTarget.y; + if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y) + target_y = 0.0f; + if (snap_on_edges && cr_y >= 1.0f && target_y >= window->ContentSize.y + window->WindowPadding.y + g.Style.ItemSpacing.y) + target_y = window->ContentSize.y + window->WindowPadding.y * 2.0f; + scroll.y = target_y - cr_y * window->InnerRect.GetHeight(); + } + scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); + if (!window->Collapsed && !window->SkipItems) + { + scroll.x = ImMin(scroll.x, window->ScrollMax.x); + scroll.y = ImMin(scroll.y, window->ScrollMax.y); + } + return scroll; +} + +// Scroll to keep newly navigated item fully into view +void ImGui::ScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) +{ + ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); + //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] + if (window_rect.Contains(item_rect)) + return; + + ImGuiContext& g = *GImGui; + if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) + { + window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 0.0f; + } + else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) + { + window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 1.0f; + } + if (item_rect.Min.y < window_rect.Min.y) + { + window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 0.0f; + } + else if (item_rect.Max.y >= window_rect.Max.y) + { + window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 1.0f; + } +} + +float ImGui::GetScrollX() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Scroll.x; +} + +float ImGui::GetScrollY() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Scroll.y; +} + +float ImGui::GetScrollMaxX() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->ScrollMax.x; +} + +float ImGui::GetScrollMaxY() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->ScrollMax.y; +} + +void ImGui::SetScrollX(float scroll_x) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->ScrollTarget.x = scroll_x; + window->ScrollTargetCenterRatio.x = 0.0f; +} + +void ImGui::SetScrollY(float scroll_y) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->ScrollTarget.y = scroll_y; + window->ScrollTargetCenterRatio.y = 0.0f; +} + +void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x) +{ + window->ScrollTarget.x = new_scroll_x; + window->ScrollTargetCenterRatio.x = 0.0f; +} + +void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) +{ + window->ScrollTarget.y = new_scroll_y; + window->ScrollTargetCenterRatio.y = 0.0f; +} + +void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) +{ + // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); + window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); + window->ScrollTargetCenterRatio.x = center_x_ratio; +} + +void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) +{ + // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); + window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); + window->ScrollTargetCenterRatio.y = center_y_ratio; +} + +// center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. +void ImGui::SetScrollHereX(float center_x_ratio) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + float target_x = window->DC.LastItemRect.Min.x - window->Pos.x; // Left of last item, in window space + float last_item_width = window->DC.LastItemRect.GetWidth(); + target_x += (last_item_width * center_x_ratio) + (g.Style.ItemSpacing.x * (center_x_ratio - 0.5f) * 2.0f); // Precisely aim before, in the middle or after the last item. + SetScrollFromPosX(target_x, center_x_ratio); +} + +// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. +void ImGui::SetScrollHereY(float center_y_ratio) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space + target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (g.Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. + SetScrollFromPosY(target_y, center_y_ratio); +} + //----------------------------------------------------------------------------- // [SECTION] TOOLTIPS //----------------------------------------------------------------------------- @@ -8138,37 +8175,6 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput return delta; } -// Scroll to keep newly navigated item fully into view -void ImGui::NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) -{ - ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); - //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] - if (window_rect.Contains(item_rect)) - return; - - ImGuiContext& g = *GImGui; - if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) - { - window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 0.0f; - } - else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) - { - window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 1.0f; - } - if (item_rect.Min.y < window_rect.Min.y) - { - window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 0.0f; - } - else if (item_rect.Max.y >= window_rect.Max.y) - { - window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 1.0f; - } -} - static void ImGui::NavUpdate() { ImGuiContext& g = *GImGui; @@ -8478,7 +8484,7 @@ static void ImGui::NavUpdateMoveResult() if (g.NavLayer == 0) { ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); - NavScrollToBringItemIntoView(result->Window, rect_abs); + ScrollToBringItemIntoView(result->Window, rect_abs); // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate() ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false); @@ -8487,7 +8493,7 @@ static void ImGui::NavUpdateMoveResult() // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy). if (result->Window->Flags & ImGuiWindowFlags_ChildWindow) - NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll)); + ScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll)); } ClearActiveID(); diff --git a/imgui_internal.h b/imgui_internal.h index 1cc8e99020d9f..8c0d741078aff 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1470,8 +1470,6 @@ namespace ImGui IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); - IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x); - IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y); IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); @@ -1498,6 +1496,11 @@ namespace ImGui IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); + // Scrolling + IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x); + IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y); + IMGUI_API void ScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect); + // Basic Accessors inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } @@ -1549,7 +1552,6 @@ namespace ImGui IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); - IMGUI_API void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect); IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); From 4cfaf7d89c16c8c2fd58110633a0315efb1a17f1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jul 2019 10:26:10 -0700 Subject: [PATCH 070/200] Scrolling, Nav: Fixed programmatic scroll leading to a slightly incorrect scroll offset when the window has decorations or a menu-bar (broken in 1.71). This was mostly noticeable when a keyboard/gamepad movement led to scrolling the view, or using e.g. SetScrollHereY() function. Fix/amend a0994d74. --- docs/CHANGELOG.txt | 6 +++++ imgui.cpp | 56 +++++++++++++++++++++++----------------------- imgui_demo.cpp | 19 +++++++++++++--- imgui_internal.h | 4 +++- 4 files changed, 53 insertions(+), 32 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c5652c968114d..78d67db35e47b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -33,6 +33,12 @@ HOW TO UPDATE? VERSION 1.73 (In Progress) ----------------------------------------------------------------------- +Other Changes: + +- Scrolling, Nav: Fixed programmatic scroll leading to a slightly incorrect scroll offset when + the window has decorations or a menu-bar (broken in 1.71). This was mostly noticeable when + a keyboard/gamepad movement led to scrolling the view, or using e.g. SetScrollHereY() function. + ----------------------------------------------------------------------- VERSION 1.72 (Released 2019-07-27) diff --git a/imgui.cpp b/imgui.cpp index 316a71ee921ab..71c76095372d8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5692,7 +5692,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Inner rectangle // Not affected by window border size. Used by: // - InnerClipRect - // - NavScrollToBringItemIntoView() + // - ScrollToBringRectIntoView() // - NavUpdatePageUpPageDown() // - Scrollbar() window->InnerRect.Min.x = window->Pos.x; @@ -7141,18 +7141,19 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s target_x = 0.0f; else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + g.Style.ItemSpacing.x) target_x = window->ContentSize.x + window->WindowPadding.x * 2.0f; - scroll.x = target_x - cr_x * window->InnerRect.GetWidth(); + scroll.x = target_x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x); } if (window->ScrollTarget.y < FLT_MAX) { // 'snap_on_edges' allows for a discontinuity at the edge of scrolling limits to take account of WindowPadding so that scrolling to make the last item visible scroll far enough to see the padding. + float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); float cr_y = window->ScrollTargetCenterRatio.y; float target_y = window->ScrollTarget.y; if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y) target_y = 0.0f; if (snap_on_edges && cr_y >= 1.0f && target_y >= window->ContentSize.y + window->WindowPadding.y + g.Style.ItemSpacing.y) target_y = window->ContentSize.y + window->WindowPadding.y * 2.0f; - scroll.y = target_y - cr_y * window->InnerRect.GetHeight(); + scroll.y = target_y - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); } scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); if (!window->Collapsed && !window->SkipItems) @@ -7164,7 +7165,7 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s } // Scroll to keep newly navigated item fully into view -void ImGui::ScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) +void ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect) { ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] @@ -7173,25 +7174,13 @@ void ImGui::ScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_re ImGuiContext& g = *GImGui; if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) - { - window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 0.0f; - } + SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x + g.Style.ItemSpacing.x, 0.0f); else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) - { - window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 1.0f; - } + SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f); if (item_rect.Min.y < window_rect.Min.y) - { - window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 0.0f; - } + SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y - g.Style.ItemSpacing.y, 0.0f); else if (item_rect.Max.y >= window_rect.Max.y) - { - window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 1.0f; - } + SetScrollFromPosY(window, item_rect.Max.y - window->Pos.y + g.Style.ItemSpacing.y, 1.0f); } float ImGui::GetScrollX() @@ -7244,26 +7233,37 @@ void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) window->ScrollTargetCenterRatio.y = 0.0f; } -void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) + +void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); window->ScrollTargetCenterRatio.x = center_x_ratio; } -void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) +void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio) { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); + const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); + local_y -= decoration_up_height; window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); window->ScrollTargetCenterRatio.y = center_y_ratio; } +void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) +{ + ImGuiContext& g = *GImGui; + SetScrollFromPosX(g.CurrentWindow, local_x, center_x_ratio); +} + +void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) +{ + ImGuiContext& g = *GImGui; + SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio); +} + // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. void ImGui::SetScrollHereX(float center_x_ratio) { @@ -8484,7 +8484,7 @@ static void ImGui::NavUpdateMoveResult() if (g.NavLayer == 0) { ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); - ScrollToBringItemIntoView(result->Window, rect_abs); + ScrollToBringRectIntoView(result->Window, rect_abs); // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate() ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false); @@ -8493,7 +8493,7 @@ static void ImGui::NavUpdateMoveResult() // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy). if (result->Window->Flags & ImGuiWindowFlags_ChildWindow) - ScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll)); + ScrollToBringRectIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll)); } ClearActiveID(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7fb29ec7fa780..5a4259fdde8fe 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2066,8 +2066,14 @@ static void ShowDemoWindowLayout() static int track_item = 50; static bool enable_track = true; + static bool enable_extra_decorations = false; static float scroll_to_off_px = 0.0f; static float scroll_to_pos_px = 200.0f; + + ImGui::Checkbox("Decoration", &enable_extra_decorations); + ImGui::SameLine(); + HelpMarker("We expose this for testing because scrolling sometimes had issues with window decoration such as menu-bars."); + ImGui::Checkbox("Track", &enable_track); ImGui::PushItemWidth(100); ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); @@ -2076,7 +2082,7 @@ static void ShowDemoWindowLayout() ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, 9999, "+%.0f px"); bool scroll_to_pos = ImGui::Button("Scroll To Pos"); - ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, 0, 9999, "X/Y = %.0f px"); + ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, 9999, "X/Y = %.0f px"); ImGui::PopItemWidth(); if (scroll_to_off || scroll_to_pos) @@ -2094,7 +2100,13 @@ static void ShowDemoWindowLayout() const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" }; ImGui::TextUnformatted(names[i]); - ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true, ImGuiWindowFlags_None); + ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0; + ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true, child_flags); + if (ImGui::BeginMenuBar()) + { + ImGui::TextUnformatted("abc"); + ImGui::EndMenuBar(); + } if (scroll_to_off) ImGui::SetScrollY(scroll_to_off_px); if (scroll_to_pos) @@ -2126,7 +2138,8 @@ static void ShowDemoWindowLayout() for (int i = 0; i < 5; i++) { float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f; - ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(-100, child_height), true, ImGuiWindowFlags_HorizontalScrollbar); + ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0); + ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(-100, child_height), true, child_flags); if (scroll_to_off) ImGui::SetScrollX(scroll_to_off_px); if (scroll_to_pos) diff --git a/imgui_internal.h b/imgui_internal.h index 8c0d741078aff..6a672edca5da8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1499,7 +1499,9 @@ namespace ImGui // Scrolling IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x); IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y); - IMGUI_API void ScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect); + IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio = 0.5f); + IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio = 0.5f); + IMGUI_API void ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); // Basic Accessors inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } From 27079e68c2c045a53991c6546b4693f275229d17 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jul 2019 10:36:40 -0700 Subject: [PATCH 071/200] Nav: Made hovering non-MenuItem Selectable not re-assign the source item for keyboard navigation. --- docs/CHANGELOG.txt | 6 +++++- imgui_internal.h | 3 ++- imgui_widgets.cpp | 11 ++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 78d67db35e47b..3c5904b56e183 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,9 +35,13 @@ HOW TO UPDATE? Other Changes: -- Scrolling, Nav: Fixed programmatic scroll leading to a slightly incorrect scroll offset when +- Nav, Scrolling: Fixed programmatic scroll leading to a slightly incorrect scroll offset when the window has decorations or a menu-bar (broken in 1.71). This was mostly noticeable when a keyboard/gamepad movement led to scrolling the view, or using e.g. SetScrollHereY() function. +- Nav: Made hovering non-MenuItem Selectable not re-assign the source item for keyboard navigation. +- Nav: Fixed an issue with NavFlattened window flag (beta) where widgets not entirely fitting + in child window (often selectables because of their protruding sides) would be not considered + as entry points to to navigate toward the child window. (#787) ----------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 6a672edca5da8..23bf45f35234e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -362,7 +362,8 @@ enum ImGuiSelectableFlagsPrivate_ ImGuiSelectableFlags_PressedOnRelease = 1 << 22, ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 23, // FIXME: We may be able to remove this (added in 6251d379 for menus) ImGuiSelectableFlags_AllowItemOverlap = 1 << 24, - ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 25 // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. + ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 25, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. + ImGuiSelectableFlags_SetNavIdOnHover = 1 << 26 }; // Extend ImGuiTreeNodeFlags_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 07e8d2e34b492..84f2ea4755a15 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5472,13 +5472,16 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const bool was_selected = selected; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); - // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) - if (pressed || hovered) + + // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard + if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) + { if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { g.NavDisableHighlight = true; SetNavID(id, window->DC.NavLayerCurrent); } + } if (pressed) MarkItemEdited(id); @@ -6178,7 +6181,9 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo ImVec2 pos = window->DC.CursorPos; ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGuiSelectableFlags flags = ImGuiSelectableFlags_PressedOnRelease | (enabled ? 0 : ImGuiSelectableFlags_Disabled); + // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), + // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. + ImGuiSelectableFlags flags = ImGuiSelectableFlags_PressedOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); bool pressed; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { From 6a0d0dab5a9f0b9518a2bc9bb456a69895ae0962 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jul 2019 10:42:32 -0700 Subject: [PATCH 072/200] Version 1.72b (patch for nav) --- docs/CHANGELOG.txt | 2 +- examples/README.txt | 2 +- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- misc/fonts/README.txt | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3c5904b56e183..52fbafb612928 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -30,7 +30,7 @@ HOW TO UPDATE? ----------------------------------------------------------------------- - VERSION 1.73 (In Progress) + VERSION 1.72b (Released 2019-07-31) ----------------------------------------------------------------------- Other Changes: diff --git a/examples/README.txt b/examples/README.txt index 7e46c8432ab65..d7245f18c5b61 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- - dear imgui, v1.73 WIP + dear imgui, v1.72b ----------------------------------------------------------------------- examples/README.txt (This is the README file for the examples/ folder. See docs/ for more documentation) diff --git a/imgui.cpp b/imgui.cpp index 71c76095372d8..6e6da3b1b8587 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.72b // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index ed7712f1b3adb..b7d25947031de 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.72b // (headers) // See imgui.cpp file for documentation. @@ -46,8 +46,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.73 WIP" -#define IMGUI_VERSION_NUM 17201 +#define IMGUI_VERSION "1.72b" +#define IMGUI_VERSION_NUM 17202 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5a4259fdde8fe..89e0f302c93d6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.72b // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3e5ca0617ac63..45f997b121edf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.72b // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 23bf45f35234e..77328281194fc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.72b // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 84f2ea4755a15..ba58bce0fb37d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.72b // (widgets code) /* diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index b8790af627b3a..92be3238cbdf5 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -1,4 +1,4 @@ -dear imgui, v1.73 WIP +dear imgui, v1.72b (Font Readme) --------------------------------------- From 9bd7846f0782deaeee6c0817d1f9cea102558061 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jul 2019 18:37:55 -0700 Subject: [PATCH 073/200] Internal: Made ScrollToBringRectIntoView() handle recursing back to scroll parent window, so the function can be called elsewhere (instead of 1 deep recursion done in NavUpdateMoveResult(). --- imgui.cpp | 48 +++++++++++++++++++++++++++--------------------- imgui_internal.h | 2 +- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6e6da3b1b8587..4f55e4a97073b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7165,22 +7165,33 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s } // Scroll to keep newly navigated item fully into view -void ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect) +ImVec2 ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect) { + ImGuiContext& g = *GImGui; ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] - if (window_rect.Contains(item_rect)) - return; - ImGuiContext& g = *GImGui; - if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) - SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x + g.Style.ItemSpacing.x, 0.0f); - else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) - SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f); - if (item_rect.Min.y < window_rect.Min.y) - SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y - g.Style.ItemSpacing.y, 0.0f); - else if (item_rect.Max.y >= window_rect.Max.y) - SetScrollFromPosY(window, item_rect.Max.y - window->Pos.y + g.Style.ItemSpacing.y, 1.0f); + ImVec2 delta_scroll; + if (!window_rect.Contains(item_rect)) + { + if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) + SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x + g.Style.ItemSpacing.x, 0.0f); + else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) + SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f); + if (item_rect.Min.y < window_rect.Min.y) + SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y - g.Style.ItemSpacing.y, 0.0f); + else if (item_rect.Max.y >= window_rect.Max.y) + SetScrollFromPosY(window, item_rect.Max.y - window->Pos.y + g.Style.ItemSpacing.y, 1.0f); + + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window, false); + delta_scroll = next_scroll - window->Scroll; + } + + // Also scroll parent window to keep us into view if necessary + if (window->Flags & ImGuiWindowFlags_ChildWindow) + delta_scroll += ScrollToBringRectIntoView(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll)); + + return delta_scroll; } float ImGui::GetScrollX() @@ -8484,16 +8495,11 @@ static void ImGui::NavUpdateMoveResult() if (g.NavLayer == 0) { ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); - ScrollToBringRectIntoView(result->Window, rect_abs); - - // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate() - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false); - ImVec2 delta_scroll = result->Window->Scroll - next_scroll; - result->RectRel.Translate(delta_scroll); + ImVec2 delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); - // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy). - if (result->Window->Flags & ImGuiWindowFlags_ChildWindow) - ScrollToBringRectIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll)); + // Offset our result position so mouse position can be applied immediately after in NavUpdate() + result->RectRel.TranslateX(-delta_scroll.x); + result->RectRel.TranslateY(-delta_scroll.y); } ClearActiveID(); diff --git a/imgui_internal.h b/imgui_internal.h index 77328281194fc..4a038d12708d3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1502,7 +1502,7 @@ namespace ImGui IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y); IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio = 0.5f); IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio = 0.5f); - IMGUI_API void ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); + IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); // Basic Accessors inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } From f624455d7bb59ff5d2056c822e645073c323c6d8 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Aug 2019 10:57:13 -0700 Subject: [PATCH 074/200] Version 1.73 WIP --- docs/CHANGELOG.txt | 6 ++++++ examples/README.txt | 2 +- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- misc/fonts/README.txt | 2 +- 9 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 52fbafb612928..43ec4234a7d69 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -29,6 +29,12 @@ HOW TO UPDATE? - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.73 WIP (In Progress) +----------------------------------------------------------------------- + +Other Changes: + ----------------------------------------------------------------------- VERSION 1.72b (Released 2019-07-31) ----------------------------------------------------------------------- diff --git a/examples/README.txt b/examples/README.txt index d7245f18c5b61..7e46c8432ab65 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- - dear imgui, v1.72b + dear imgui, v1.73 WIP ----------------------------------------------------------------------- examples/README.txt (This is the README file for the examples/ folder. See docs/ for more documentation) diff --git a/imgui.cpp b/imgui.cpp index 4f55e4a97073b..fc1a46bd04df5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72b +// dear imgui, v1.73 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index b7d25947031de..f58105197a8b0 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.72b +// dear imgui, v1.73 WIP // (headers) // See imgui.cpp file for documentation. @@ -46,8 +46,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.72b" -#define IMGUI_VERSION_NUM 17202 +#define IMGUI_VERSION "1.73 WIP" +#define IMGUI_VERSION_NUM 17203 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 89e0f302c93d6..5a4259fdde8fe 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72b +// dear imgui, v1.73 WIP // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 45f997b121edf..3e5ca0617ac63 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72b +// dear imgui, v1.73 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 4a038d12708d3..cac70f049533e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.72b +// dear imgui, v1.73 WIP // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba58bce0fb37d..84f2ea4755a15 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.72b +// dear imgui, v1.73 WIP // (widgets code) /* diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 92be3238cbdf5..b8790af627b3a 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -1,4 +1,4 @@ -dear imgui, v1.72b +dear imgui, v1.73 WIP (Font Readme) --------------------------------------- From 6cf4743f1755408fd094a75cf1d7a6e5a2ae803e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Aug 2019 10:58:41 -0700 Subject: [PATCH 075/200] Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). --- docs/CHANGELOG.txt | 3 +++ examples/imgui_impl_dx11.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 43ec4234a7d69..7c251b31bec72 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,6 +34,9 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Other Changes: +- Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, + would generally make the debug layer complain (Added in 1.72). + ----------------------------------------------------------------------- VERSION 1.72b (Released 2019-07-31) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 89b88dead8e14..197bbe02345e2 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -11,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). // 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. // 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. @@ -208,7 +209,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); - old.PSInstancesCount = old.VSInstancesCount = 256; + old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); From 62143dff64c8cfb960248b84cf6c4566ffc5a743 Mon Sep 17 00:00:00 2001 From: Vilya Harvey Date: Wed, 31 Jul 2019 19:50:50 +0100 Subject: [PATCH 076/200] Backends: Vulkan: Added support for specifying multisample count. (#2705, #2706) --- docs/CHANGELOG.txt | 3 +++ examples/imgui_impl_vulkan.cpp | 6 +++++- examples/imgui_impl_vulkan.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7c251b31bec72..acc7bef637364 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,6 +36,9 @@ HOW TO UPDATE? Other Changes: - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). +- Backends: Vulkan: Added support for specifying multisample count. + Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values + to use, default is non-multisampled as before. (#2705, #2706) [@vilya] ----------------------------------------------------------------------- diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index b55cb190bd7f7..9d977f0056597 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -22,6 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. // 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount(). @@ -721,7 +722,10 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() VkPipelineMultisampleStateCreateInfo ms_info = {}; ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + if (v->MSAASamples != 0) + ms_info.rasterizationSamples = v->MSAASamples; + else + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_attachment[1] = {}; color_attachment[0].blendEnable = VK_TRUE; diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 80356b96f5758..f2bf92938b07d 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -37,6 +37,7 @@ struct ImGui_ImplVulkan_InitInfo VkDescriptorPool DescriptorPool; uint32_t MinImageCount; // >= 2 uint32_t ImageCount; // >= MinImageCount + VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); }; From 2e756d5b477486ff93c08d302d5bd39f5d0d6d87 Mon Sep 17 00:00:00 2001 From: Matthias Moulin Date: Mon, 12 Aug 2019 22:31:49 +0200 Subject: [PATCH 077/200] Explicit narrowing cast from size_t to UINT (#2726) Clang: `non-constant-expression cannot be narrowed from type 'size_t' (aka 'unsigned long long') to 'UINT' (aka 'unsigned int') in initializer list [-Wc++11-narrowing]` --- examples/imgui_impl_dx12.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index b40e9282991f8..3161d1837370a 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -502,9 +502,9 @@ bool ImGui_ImplDX12_CreateDeviceObjects() // Create the input layout static D3D12_INPUT_ELEMENT_DESC local_layout[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, IM_OFFSETOF(ImDrawVert, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, }; psoDesc.InputLayout = { local_layout, 3 }; } From 7d2cfa6ff11a40a44fd1dc504ae7403937f16535 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Aug 2019 14:49:18 +0200 Subject: [PATCH 078/200] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000000..96b413db72155 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms +#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: imgui From 88bf056a9ffb0f92452174acf709345fcec35c54 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Aug 2019 14:51:38 +0200 Subject: [PATCH 079/200] Removing Funding file (unnecessary as we'll switch services) --- .github/FUNDING.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 96b413db72155..0000000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -# These are supported funding model platforms -#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: imgui From 9fce2789183d223440592b2ab8c66d495d5e9b80 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Aug 2019 19:03:07 +0200 Subject: [PATCH 080/200] ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). --- docs/CHANGELOG.txt | 7 +++-- imgui.cpp | 2 +- imgui_widgets.cpp | 65 +++++++++++++++++++++++++--------------------- 3 files changed, 42 insertions(+), 32 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index acc7bef637364..2daadc5e648d3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,10 +34,13 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Other Changes: +- ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) + Note that some elements won't accurately fade down with the same intensity, and the color wheel + when enabled will have small overlap glitches with (style.Alpha < 1.0). - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). -- Backends: Vulkan: Added support for specifying multisample count. - Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values +- Backends: Vulkan: Added support for specifying multisample count. + Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. (#2705, #2706) [@vilya] diff --git a/imgui.cpp b/imgui.cpp index fc1a46bd04df5..809df9bba6c82 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4439,7 +4439,7 @@ bool ImGui::IsMouseDoubleClicked(int button) return g.IO.MouseDoubleClicked[button]; } -// [Internal] This doesn't test if the button is presed +// [Internal] This doesn't test if the button is pressed bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold) { ImGuiContext& g = *GImGui; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 84f2ea4755a15..212d6a3e3e605 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4402,17 +4402,19 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU } // Helper for ColorPicker4() -static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w) +static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha) { - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32_WHITE); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32_BLACK); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE); + ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8)); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8)); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8)); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8)); } // Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.) // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) +// FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0) bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) { ImGuiContext& g = *GImGui; @@ -4662,17 +4664,22 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl } } - ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); + const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha); + const ImU32 col_black = IM_COL32(0,0,0,style_alpha8); + const ImU32 col_white = IM_COL32(255,255,255,style_alpha8); + const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8); + const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) }; + + ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f); - ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, 1.0f)); + ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!! - const ImU32 hue_colors[6+1] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) }; ImVec2 sv_cursor_pos; if (flags & ImGuiColorEditFlags_PickerHueWheel) { // Render Hue Wheel - const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). + const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12); for (int n = 0; n < 6; n++) { @@ -4680,13 +4687,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps; const int vert_start_idx = draw_list->VtxBuffer.Size; draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc); - draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness); + draw_list->PathStroke(col_white, false, wheel_thickness); const int vert_end_idx = draw_list->VtxBuffer.Size; // Paint colors over existing vertices ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); - ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); + ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n+1]); } // Render Cursor + preview on Hue Wheel @@ -4696,8 +4703,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); - draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments); - draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments); + draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments); + draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); // Render SV triangle (rotated according to hue) ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); @@ -4707,46 +4714,46 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl draw_list->PrimReserve(6, 6); draw_list->PrimVtx(tra, uv_white, hue_color32); draw_list->PrimVtx(trb, uv_white, hue_color32); - draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE); - draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS); - draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK); - draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS); - draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f); + draw_list->PrimVtx(trc, uv_white, col_white); + draw_list->PrimVtx(tra, uv_white, 0); + draw_list->PrimVtx(trb, uv_white, col_white); + draw_list->PrimVtx(trc, uv_white, 0); + draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); } else if (flags & ImGuiColorEditFlags_PickerHueBar) { // Render SV Square - draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE); - draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK); - RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f); + draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); + draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); + RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); // Render Hue Bar for (int i = 0; i < 6; ++i) - draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]); + draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]); float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f); RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); - RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f); + RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; - draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12); - draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12); - draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12); + draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12); + draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12); + draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12); // Render alpha bar if (alpha_bar) { float alpha = ImSaturate(col[3]); ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); - RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); - draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK); + RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); + draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); - RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f); + RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } EndGroup(); From 7abd41bd5fa75df0c013a71c6d8bb91c855e05cc Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Aug 2019 20:38:17 +0200 Subject: [PATCH 081/200] TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2daadc5e648d3..8b4659e27a76e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -37,6 +37,7 @@ Other Changes: - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). +- TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 212d6a3e3e605..3e4f08a9e2f1e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6638,7 +6638,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) float tab_x1 = tab->Offset + (order > 0 ? -margin : 0.0f); float tab_x2 = tab->Offset + tab->Width + (order + 1 < tab_bar->Tabs.Size ? margin : 1.0f); tab_bar->ScrollingTargetDistToVisibility = 0.0f; - if (tab_bar->ScrollingTarget > tab_x1) + if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= tab_bar->BarRect.GetWidth())) { tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f); tab_bar->ScrollingTarget = tab_x1; From a33cedda142f6e96a9bd2d665290830362671566 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Aug 2019 21:48:03 +0200 Subject: [PATCH 082/200] Internals: Renaming window size calc functions. --- imgui.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 809df9bba6c82..3612139862d94 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4857,7 +4857,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl return window; } -static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) +static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) { ImGuiContext& g = *GImGui; if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) @@ -4889,7 +4889,7 @@ static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) return new_size; } -static ImVec2 CalcContentSize(ImGuiWindow* window) +static ImVec2 CalcWindowContentSize(ImGuiWindow* window) { if (window->Collapsed) if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) @@ -4903,7 +4903,7 @@ static ImVec2 CalcContentSize(ImGuiWindow* window) return sz; } -static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents) +static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents) { ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; @@ -4927,7 +4927,7 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents) // When the window cannot fit all contents (either because of constraints, either because screen is too small), // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding. - ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit); + ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit); bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - size_decorations.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar); bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - size_decorations.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar); if (will_have_scrollbar_x) @@ -4940,8 +4940,10 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents) ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window) { - ImVec2 size_contents = CalcContentSize(window); - return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents)); + ImVec2 size_contents = CalcWindowContentSize(window); + ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents); + ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit); + return size_final; } static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags) @@ -4958,7 +4960,7 @@ static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& co ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right ImVec2 size_expected = pos_max - pos_min; - ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected); + ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected); *out_pos = pos_min; if (corner_norm.x == 0.0f) out_pos->x -= (size_constrained.x - size_expected.x); @@ -5039,7 +5041,7 @@ static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) { // Manual auto-fit when double-clicking - size_target = CalcSizeAfterConstraint(window, size_auto_fit); + size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit); ret_auto_fit = true; ClearActiveID(); } @@ -5094,7 +5096,7 @@ static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au g.NavDisableMouseHover = true; resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. - size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); + size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); } } @@ -5481,7 +5483,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS // Update contents size from last frame for auto-fitting (or use explicit size) - window->ContentSize = CalcContentSize(window); + window->ContentSize = CalcWindowContentSize(window); if (window->HiddenFramesCanSkipItems > 0) window->HiddenFramesCanSkipItems--; if (window->HiddenFramesCannotSkipItems > 0) @@ -5545,7 +5547,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // SIZE // Calculate auto-fit size, handle automatic resize - const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->ContentSize); + const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSize); bool use_current_size_for_scrollbar_x = window_just_created; bool use_current_size_for_scrollbar_y = window_just_created; if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) @@ -5581,7 +5583,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Apply minimum/maximum window size constraints and final size - window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull); + window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull); window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull; // Decoration size From a856c670c17fe70d61e519bf74ccb2559915a2ff Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 21 Aug 2019 23:05:46 +0200 Subject: [PATCH 083/200] TabBar: fixed single-tab not shrinking their width down. + minor typo fixes (#2738) --- docs/CHANGELOG.txt | 1 + examples/imgui_impl_opengl2.cpp | 2 +- imgui.cpp | 2 +- imgui_widgets.cpp | 8 ++++++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8b4659e27a76e..63033042799cb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -38,6 +38,7 @@ Other Changes: Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. +- TabBar: fixed single-tab not shrinking their width down. - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/examples/imgui_impl_opengl2.cpp b/examples/imgui_impl_opengl2.cpp index 95720ff3cc64e..fbe278c7f0697 100644 --- a/examples/imgui_impl_opengl2.cpp +++ b/examples/imgui_impl_opengl2.cpp @@ -24,7 +24,7 @@ // 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications. // 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples. // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. -// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself. // 2017-09-01: OpenGL: Save and restore current polygon mode. // 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal). // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. diff --git a/imgui.cpp b/imgui.cpp index 3612139862d94..374efe2a6c157 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -638,7 +638,7 @@ CODE - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using: - OpenGL: ImTextureID = GLuint (see ImGui_ImplGlfwGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp) + OpenGL: ImTextureID = GLuint (see ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp) DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp) DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp) DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3e4f08a9e2f1e..89e6ca0b3e92c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1361,8 +1361,12 @@ static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs) // Shrink excess width from a set of item, by removing width from the larger items first. void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess) { - if (count > 1) - ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer); + if (count == 1) + { + items[0].Width -= width_excess; + return; + } + ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer); int count_same_width = 1; while (width_excess > 0.0f && count_same_width < count) { From c4b0bf718ad69a1c24da6ad5f95e58458d1ff28d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Aug 2019 11:40:37 +0200 Subject: [PATCH 084/200] More typos in comments (#2738) --- imgui.cpp | 2 +- imgui_demo.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 374efe2a6c157..6be7fdc9c482b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -638,7 +638,7 @@ CODE - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using: - OpenGL: ImTextureID = GLuint (see ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp) + OpenGL: ImTextureID = GLuint (see ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp) DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp) DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp) DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5a4259fdde8fe..0264debc281ea 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -759,7 +759,7 @@ static void ShowDemoWindowWidgets() // Here we are grabbing the font texture because that's the only one we have access to inside the demo code. // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure. // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID. - // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.) + // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier etc.) // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc. // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this. // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). From 3fb5cf3541c745b1a655f78ae593e665d4c4b6eb Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Aug 2019 16:55:42 +0200 Subject: [PATCH 085/200] Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 2 +- imgui.h | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 63033042799cb..e5dfa6579c21e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,7 @@ Other Changes: when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. +- Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/imgui.cpp b/imgui.cpp index 6be7fdc9c482b..b4b4bc34df0db 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -176,7 +176,7 @@ CODE - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide. Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" - phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render(). + phases of your own application. All rendering information are stored into command-lists that you will retrieve after calling ImGui::Render(). - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code. - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder. diff --git a/imgui.h b/imgui.h index f58105197a8b0..abb42a789ab4b 100644 --- a/imgui.h +++ b/imgui.h @@ -73,8 +73,12 @@ Index of this file: #define IM_FMTLIST(FMT) #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers! -#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in modern C++. #define IM_UNUSED(_VAR) ((void)_VAR) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. +#if (__cplusplus >= 201100) +#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11 +#else +#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro. +#endif // Warnings #if defined(__clang__) From c4ff1b3578ea0bcac93a25b16d5e3e4cb32f0a9a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Aug 2019 17:43:57 +0200 Subject: [PATCH 086/200] ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) --- docs/CHANGELOG.txt | 1 + imgui.h | 36 ++++++++------- imgui_demo.cpp | 4 +- imgui_draw.cpp | 108 +++++++++++++++++++++++---------------------- 4 files changed, 79 insertions(+), 70 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e5dfa6579c21e..ede7464d24686 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,7 @@ Other Changes: when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. +- ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). diff --git a/imgui.h b/imgui.h index abb42a789ab4b..63a8eec8c2965 100644 --- a/imgui.h +++ b/imgui.h @@ -1901,33 +1901,39 @@ struct ImDrawList inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } // Primitives - IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4-bits corresponding to which corner to round - IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) - IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); - IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col); - IMGUI_API void AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col); - IMGUI_API void AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); - IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12); + // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners. + IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4-bits corresponding to which corner to round + IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) + IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); + IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col); + IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col); + IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); + IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 12); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); - IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = IM_COL32_WHITE); - IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = IM_COL32_WHITE); - IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); + // Image primitives + // - Read FAQ to understand what ImTextureID is. + // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. + // - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture. + IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE); + IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE); + IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); + // Stateful path API, add points then finish with PathFillConvex() or PathStroke() inline void PathClear() { _Path.Size = 0; } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } // Note: Anti-aliased filling requires points to be in clockwise order. inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness); _Path.Size = 0; } - IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); - IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle + IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 10); + IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0264debc281ea..790cb63c7a454 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4391,9 +4391,9 @@ static void ShowExampleAppCustomRendering(bool* p_open) ImVec2 window_size = ImGui::GetWindowSize(); ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f); if (draw_bg) - ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 32, 10+4); + ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 48, 10+4); if (draw_fg) - ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 32, 10); + ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 48, 10); ImGui::EndTabItem(); } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3e5ca0617ac63..3eb1067efcd5d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -860,26 +860,26 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun } } -void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12) +void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12) { if (radius == 0.0f || a_min_of_12 > a_max_of_12) { - _Path.push_back(centre); + _Path.push_back(center); return; } _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); for (int a = a_min_of_12; a <= a_max_of_12; a++) { const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)]; - _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); + _Path.push_back(ImVec2(center.x + c.x * radius, center.y + c.y * radius)); } } -void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments) +void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) { if (radius == 0.0f) { - _Path.push_back(centre); + _Path.push_back(center); return; } @@ -889,7 +889,7 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, floa for (int i = 0; i <= num_segments; i++) { const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); - _Path.push_back(ImVec2(centre.x + ImCos(a) * radius, centre.y + ImSin(a) * radius)); + _Path.push_back(ImVec2(center.x + ImCos(a) * radius, center.y + ImSin(a) * radius)); } } @@ -968,44 +968,46 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDr } } -void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness) +void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; - PathLineTo(a + ImVec2(0.5f,0.5f)); - PathLineTo(b + ImVec2(0.5f,0.5f)); + PathLineTo(p1 + ImVec2(0.5f, 0.5f)); + PathLineTo(p2 + ImVec2(0.5f, 0.5f)); PathStroke(col, false, thickness); } -// a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly. -void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness) +// p_min = upper-left, p_max = lower-right +// Note we don't render 1 pixels sized rectangles properly. +void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; if (Flags & ImDrawListFlags_AntiAliasedLines) - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners); + PathRect(p_min + ImVec2(0.50f,0.50f), p_max - ImVec2(0.50f,0.50f), rounding, rounding_corners); else - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes. + PathRect(p_min + ImVec2(0.50f,0.50f), p_max - ImVec2(0.49f,0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes. PathStroke(col, true, thickness); } -void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) +void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) { if ((col & IM_COL32_A_MASK) == 0) return; if (rounding > 0.0f) { - PathRect(a, b, rounding, rounding_corners); + PathRect(p_min, p_max, rounding, rounding_corners); PathFillConvex(col); } else { PrimReserve(6, 4); - PrimRect(a, b, col); + PrimRect(p_min, p_max, col); } } -void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left) +// p_min = upper-left, p_max = lower-right +void ImDrawList::AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left) { if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) return; @@ -1014,77 +1016,77 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 PrimReserve(6, 4); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3)); - PrimWriteVtx(a, uv, col_upr_left); - PrimWriteVtx(ImVec2(c.x, a.y), uv, col_upr_right); - PrimWriteVtx(c, uv, col_bot_right); - PrimWriteVtx(ImVec2(a.x, c.y), uv, col_bot_left); + PrimWriteVtx(p_min, uv, col_upr_left); + PrimWriteVtx(ImVec2(p_max.x, p_min.y), uv, col_upr_right); + PrimWriteVtx(p_max, uv, col_bot_right); + PrimWriteVtx(ImVec2(p_min.x, p_max.y), uv, col_bot_left); } -void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness) +void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; - PathLineTo(a); - PathLineTo(b); - PathLineTo(c); - PathLineTo(d); + PathLineTo(p1); + PathLineTo(p2); + PathLineTo(p3); + PathLineTo(p4); PathStroke(col, true, thickness); } -void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col) +void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; - PathLineTo(a); - PathLineTo(b); - PathLineTo(c); - PathLineTo(d); + PathLineTo(p1); + PathLineTo(p2); + PathLineTo(p3); + PathLineTo(p4); PathFillConvex(col); } -void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness) +void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; - PathLineTo(a); - PathLineTo(b); - PathLineTo(c); + PathLineTo(p1); + PathLineTo(p2); + PathLineTo(p3); PathStroke(col, true, thickness); } -void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col) +void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; - PathLineTo(a); - PathLineTo(b); - PathLineTo(c); + PathLineTo(p1); + PathLineTo(p2); + PathLineTo(p3); PathFillConvex(col); } -void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness) +void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; // Because we are filling a closed shape we remove 1 from the count of segments/points - const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments - 1); + const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; + PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); PathStroke(col, true, thickness); } -void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments) +void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; // Because we are filling a closed shape we remove 1 from the count of segments/points - const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(centre, radius, 0.0f, a_max, num_segments - 1); + const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; + PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } @@ -1132,7 +1134,7 @@ void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, c AddText(NULL, 0.0f, pos, col, text_begin, text_end); } -void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col) +void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; @@ -1142,13 +1144,13 @@ void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const Im PushTextureID(user_texture_id); PrimReserve(6, 4); - PrimRectUV(a, b, uv_a, uv_b, col); + PrimRectUV(p_min, p_max, uv_min, uv_max, col); if (push_texture_id) PopTextureID(); } -void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col) +void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, const ImVec2& uv4, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; @@ -1158,20 +1160,20 @@ void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, cons PushTextureID(user_texture_id); PrimReserve(6, 4); - PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col); + PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col); if (push_texture_id) PopTextureID(); } -void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) +void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) { if ((col & IM_COL32_A_MASK) == 0) return; if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0) { - AddImage(user_texture_id, a, b, uv_a, uv_b, col); + AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col); return; } @@ -1180,10 +1182,10 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, c PushTextureID(user_texture_id); int vert_start_idx = VtxBuffer.Size; - PathRect(a, b, rounding, rounding_corners); + PathRect(p_min, p_max, rounding, rounding_corners); PathFillConvex(col); int vert_end_idx = VtxBuffer.Size; - ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, a, b, uv_a, uv_b, true); + ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true); if (push_texture_id) PopTextureID(); From cb538fadfe3d24ec2b8c30a97103e44055db811c Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Aug 2019 11:08:30 +0200 Subject: [PATCH 087/200] Internals: Storing settings using ImVec2ih to match what we are doing with dock node. + removed ImMax from reading Size value (done in Begin) + removed seemingly unnecessary FLT_MAX compare in SettingsHandlerWindow_WriteAll. About: Added backquote to text copied into clipboard so it doesn't mess up with github formatting when pasted. --- imgui.cpp | 25 +++++++++++-------------- imgui_demo.cpp | 6 ++++++ imgui_internal.h | 14 +++++++++++--- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b4b4bc34df0db..fbe7a29e88faf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4827,10 +4827,10 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl // Retrieve settings from .ini file window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings); SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); - window->Pos = ImFloor(settings->Pos); + window->Pos = ImVec2(settings->Pos.x, settings->Pos.y); window->Collapsed = settings->Collapsed; - if (ImLengthSqr(settings->Size) > 0.00001f) - size = ImFloor(settings->Size); + if (settings->Size.x > 0 && settings->Size.y > 0) + size = ImVec2(settings->Size.x, settings->Size.y); } window->Size = window->SizeFull = ImFloor(size); window->DC.CursorStartPos = window->DC.CursorMaxPos = window->Pos; // So first call to CalcContentSize() doesn't return crazy values @@ -9447,14 +9447,13 @@ static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler* return (void*)settings; } -static void SettingsHandlerWindow_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler*, void* entry, const char* line) +static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) { - ImGuiContext& g = *ctx; ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; - float x, y; + int x, y; int i; - if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y); - else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize); + if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) settings->Pos = ImVec2ih((short)x, (short)y); + else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) settings->Size = ImVec2ih((short)x, (short)y); else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0); } @@ -9476,8 +9475,8 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings); } IM_ASSERT(settings->ID == window->ID); - settings->Pos = window->Pos; - settings->Size = window->SizeFull; + settings->Pos = ImVec2ih((short)window->Pos.x, (short)window->Pos.y); + settings->Size = ImVec2ih((short)window->SizeFull.x, (short)window->SizeFull.y); settings->Collapsed = window->Collapsed; } @@ -9486,11 +9485,9 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl for (int i = 0; i != g.SettingsWindows.Size; i++) { const ImGuiWindowSettings* settings = &g.SettingsWindows[i]; - if (settings->Pos.x == FLT_MAX) - continue; buf->appendf("[%s][%s]\n", handler->TypeName, settings->Name); - buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); - buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y); + buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y); + buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y); buf->appendf("Collapsed=%d\n", settings->Collapsed); buf->appendf("\n"); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 790cb63c7a454..b2b7a7e450aea 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2961,7 +2961,10 @@ void ImGui::ShowAboutWindow(bool* p_open) bool copy_to_clipboard = ImGui::Button("Copy to clipboard"); ImGui::BeginChildFrame(ImGui::GetID("cfginfos"), ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18), ImGuiWindowFlags_NoMove); if (copy_to_clipboard) + { ImGui::LogToClipboard(); + ImGui::LogText("```\n"); // Back quotes will make the text appears without formatting when pasting to GitHub + } ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); ImGui::Separator(); @@ -3052,7 +3055,10 @@ void ImGui::ShowAboutWindow(bool* p_open) ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y); if (copy_to_clipboard) + { + ImGui::LogText("\n```\n"); ImGui::LogFinish(); + } ImGui::EndChildFrame(); } ImGui::End(); diff --git a/imgui_internal.h b/imgui_internal.h index cac70f049533e..a936f69e56250 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -528,6 +528,14 @@ struct ImVec1 ImVec1(float _x) { x = _x; } }; +// 2D vector (half-size integer) +struct ImVec2ih +{ + short x, y; + ImVec2ih() { x = y = 0; } + ImVec2ih(short _x, short _y) { x = _x; y = _y; } +}; + // 2D axis aligned bounding-box // NB: we can't rely on ImVec2 math operators being available here struct IMGUI_API ImRect @@ -655,11 +663,11 @@ struct ImGuiWindowSettings { char* Name; ImGuiID ID; - ImVec2 Pos; - ImVec2 Size; + ImVec2ih Pos; + ImVec2ih Size; bool Collapsed; - ImGuiWindowSettings() { Name = NULL; ID = 0; Pos = Size = ImVec2(0,0); Collapsed = false; } + ImGuiWindowSettings() { Name = NULL; ID = 0; Pos = Size = ImVec2ih(0, 0); Collapsed = false; } }; struct ImGuiSettingsHandler From bcdb89ab078780ac256ec6ee155af0a0c55460a7 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen Date: Tue, 27 Aug 2019 22:40:34 +0200 Subject: [PATCH 088/200] Rebased imstb_rectpack on stb_rect_pack v1.00. --- docs/CHANGELOG.txt | 2 ++ imstb_rectpack.h | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ede7464d24686..046e59d450e0d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,8 @@ Other Changes: - Backends: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. (#2705, #2706) [@vilya] +- Misc: Updated stb_rect_pack from 0.99 to 1.00 (fixes by @rygorous: off-by-1 bug in best-fit heuristic, + fix handling of rectangles too large to fit inside texture). (#2762) [@tido64] ----------------------------------------------------------------------- diff --git a/imstb_rectpack.h b/imstb_rectpack.h index 23f922a579748..ff2a85df42bc6 100644 --- a/imstb_rectpack.h +++ b/imstb_rectpack.h @@ -1,10 +1,10 @@ -// [DEAR IMGUI] -// This is a slightly modified version of stb_rect_pack.h 0.99. +// [DEAR IMGUI] +// This is a slightly modified version of stb_rect_pack.h 1.00. // Those changes would need to be pushed into nothings/stb: // - Added STBRP__CDECL // Grep for [DEAR IMGUI] to find the changes. -// stb_rect_pack.h - v0.99 - public domain - rectangle packing +// stb_rect_pack.h - v1.00 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -37,9 +37,11 @@ // // Bugfixes / warning fixes // Jeremy Jaussaud +// Fabian Giesen // // Version history: // +// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles // 0.99 (2019-02-07) warning fixes // 0.11 (2017-03-03) return packing success/fail result // 0.10 (2016-10-25) remove cast-away-const to avoid warnings @@ -357,6 +359,13 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt width -= width % c->align; STBRP_ASSERT(width % c->align == 0); + // if it can't possibly fit, bail immediately + if (width > c->width || height > c->height) { + fr.prev_link = NULL; + fr.x = fr.y = 0; + return fr; + } + node = c->active_head; prev = &c->active_head; while (node->x + width <= c->width) { @@ -420,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt } STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); - if (y + height < c->height) { + if (y + height <= c->height) { if (y <= best_y) { if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { best_x = xpos; From c8418015c22fad3479ebd5cd91f7658d56e47ad8 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Aug 2019 12:31:43 +0200 Subject: [PATCH 089/200] SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) + misc minor stuff. --- docs/CHANGELOG.txt | 1 + imgui.h | 2 +- imgui_widgets.cpp | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 046e59d450e0d..d9a60769ffa72 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,7 @@ Other Changes: when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. +- SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, diff --git a/imgui.h b/imgui.h index 63a8eec8c2965..6b0de93a918e8 100644 --- a/imgui.h +++ b/imgui.h @@ -1789,7 +1789,7 @@ struct ImDrawCmd ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. void* UserCallbackData; // The draw callback code can access this. - ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = ClipRect.z = ClipRect.w = 0.0f; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; } + ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; } }; // Vertex index diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 89e6ca0b3e92c..79f5b2d490a3d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2464,13 +2464,13 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2); return SliderBehaviorT(bb, id, data_type, (ImS32*)v, *(const ImS32*)v_min, *(const ImS32*)v_max, format, power, flags, out_grab_bb); case ImGuiDataType_U32: - IM_ASSERT(*(const ImU32*)v_min <= IM_U32_MAX/2); + IM_ASSERT(*(const ImU32*)v_max <= IM_U32_MAX/2); return SliderBehaviorT(bb, id, data_type, (ImU32*)v, *(const ImU32*)v_min, *(const ImU32*)v_max, format, power, flags, out_grab_bb); case ImGuiDataType_S64: IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2); return SliderBehaviorT(bb, id, data_type, (ImS64*)v, *(const ImS64*)v_min, *(const ImS64*)v_max, format, power, flags, out_grab_bb); case ImGuiDataType_U64: - IM_ASSERT(*(const ImU64*)v_min <= IM_U64_MAX/2); + IM_ASSERT(*(const ImU64*)v_max <= IM_U64_MAX/2); return SliderBehaviorT(bb, id, data_type, (ImU64*)v, *(const ImU64*)v_min, *(const ImU64*)v_max, format, power, flags, out_grab_bb); case ImGuiDataType_Float: IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f); @@ -3384,7 +3384,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ BeginGroup(); const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); From 45a0db597925777ffaa08f58089eca36382edddc Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Mon, 26 Aug 2019 19:52:08 -0400 Subject: [PATCH 090/200] Demo: PlotLine example displays the average value. (#2759) + extra comments --- imgui_demo.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b2b7a7e450aea..04214437ec593 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1043,6 +1043,8 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } + // Plot/Graph widgets are currently fairly limited. + // Consider writing your own plotting widget, or using a third-party one (see "Wiki->Useful Widgets", or github.com/ocornut/imgui/issues/2747) if (ImGui::TreeNode("Plots Widgets")) { static bool animate = true; @@ -1066,7 +1068,18 @@ static void ShowDemoWindowWidgets() phase += 0.10f*values_offset; refresh_time += 1.0f/60.0f; } - ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); + + // Plots can display overlay texts + // (in this example, we will display an average value) + { + float average = 0.0f; + for (int n = 0; n < IM_ARRAYSIZE(values); n++) + average += values[n]; + average /= (float)IM_ARRAYSIZE(values); + char overlay[32]; + sprintf(overlay, "avg %f", average); + ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0,80)); + } ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80)); // Use functions to generate output From 62f75c7fb163a2fcd0455ae4e68ea4acf0b15d17 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 30 Jun 2019 12:48:19 +0200 Subject: [PATCH 091/200] Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++- imgui.h | 1 + imgui_demo.cpp | 1 + imgui_internal.h | 9 +++++++- 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d9a60769ffa72..9dee4195b74e0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,9 @@ Other Changes: - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) +- Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when + a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory + usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/imgui.cpp b/imgui.cpp index fbe7a29e88faf..6a8cc176a0602 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1244,6 +1244,7 @@ ImGuiIO::ImGuiIO() ConfigInputTextCursorBlink = true; ConfigWindowsResizeFromEdges = true; ConfigWindowsMoveFromTitleBarOnly = false; + ConfigWindowsMemoryCompactTimer = 60.0f; // Platform Functions BackendPlatformName = BackendRendererName = NULL; @@ -2699,6 +2700,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); LastFrameActive = -1; + LastTimeActive = -1.0f; ItemWidthDefault = 0.0f; FontWindowScale = 1.0f; SettingsIdx = -1; @@ -2713,6 +2715,9 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) NavLastIds[0] = NavLastIds[1] = 0; NavRectRel[0] = NavRectRel[1] = ImRect(); NavLastChildNavWindow = NULL; + + MemoryCompacted = false; + MemoryDrawListIdxCapacity = MemoryDrawListVtxCapacity = 0; } ImGuiWindow::~ImGuiWindow() @@ -2783,6 +2788,36 @@ static void SetCurrentWindow(ImGuiWindow* window) g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); } +// Free up/compact internal window buffers, we can use this when a window becomes unused. +// This is currently unused by the library, but you may call this yourself for easy GC. +// Not freed: +// - ImGuiWindow, ImGuiWindowSettings, Name +// - StateStorage, ColumnsStorage (may hold useful data) +// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost. +void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window) +{ + window->MemoryCompacted = true; + window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity; + window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity; + window->IDStack.clear(); + window->DrawList->ClearFreeMemory(); + window->DC.ChildWindows.clear(); + window->DC.ItemFlagsStack.clear(); + window->DC.ItemWidthStack.clear(); + window->DC.TextWrapPosStack.clear(); + window->DC.GroupStack.clear(); +} + +void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) +{ + // We stored capacity of the ImDrawList buffer to reduce growth-caused allocation/copy when awakening. + // The other buffers tends to amortize much faster. + window->MemoryCompacted = false; + window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity); + window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity); + window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0; +} + void ImGui::SetNavID(ImGuiID id, int nav_layer) { ImGuiContext& g = *GImGui; @@ -3814,8 +3849,9 @@ void ImGui::NewFrame() g.NavIdTabCounter = INT_MAX; - // Mark all windows as not visible + // Mark all windows as not visible and compact unused memory. IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); + const float memory_compact_start_time = (g.IO.ConfigWindowsMemoryCompactTimer > 0.0f) ? (float)g.Time - g.IO.ConfigWindowsMemoryCompactTimer : FLT_MAX; for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; @@ -3823,6 +3859,10 @@ void ImGui::NewFrame() window->BeginCount = 0; window->Active = false; window->WriteAccessed = false; + + // Garbage collect (this is totally functional but we may need decide if the side-effects are desirable) + if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time) + GcCompactTransientWindowBuffers(window); } // Closing the focused window restore focus to the first active root window in descending z-order @@ -5391,6 +5431,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { window->Flags = (ImGuiWindowFlags)flags; window->LastFrameActive = current_frame; + window->LastTimeActive = (float)g.Time; window->BeginOrderWithinParent = 0; window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++); } @@ -5404,6 +5445,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); + // We allow window memory to be compacted so recreate the base stack when needed. + if (window->IDStack.Size == 0) + window->IDStack.push_back(window->ID); + // Add to stack // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() g.CurrentWindowStack.push_back(window); @@ -5468,6 +5513,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); window->IDStack.resize(1); + // Restore buffer capacity when woken from a compacted state, to avoid + if (window->MemoryCompacted) + GcAwakeTransientWindowBuffers(window); + // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged). // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere. bool window_title_visible_elsewhere = false; diff --git a/imgui.h b/imgui.h index 6b0de93a918e8..28c7d20d5c499 100644 --- a/imgui.h +++ b/imgui.h @@ -1360,6 +1360,7 @@ struct ImGuiIO bool ConfigInputTextCursorBlink; // = true // Set to false to disable blinking cursor, for users who consider it distracting. (was called: io.OptCursorBlink prior to 1.63) bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsMoveFromTitleBarOnly; // = false // [BETA] Set to true to only allow moving windows when clicked+dragged from the title bar. Windows without a title bar are not affected. + float ConfigWindowsMemoryCompactTimer;// = 60.0f // [BETA] Compact window memory usage when unused. Set to 0.0f to disable. //------------------------------------------------------------------ // Platform Functions diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 04214437ec593..568da3b928c4e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3049,6 +3049,7 @@ void ImGui::ShowAboutWindow(bool* p_open) if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink"); if (io.ConfigWindowsResizeFromEdges) ImGui::Text("io.ConfigWindowsResizeFromEdges"); if (io.ConfigWindowsMoveFromTitleBarOnly) ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly"); + if (io.ConfigWindowsMemoryCompactTimer > 0.0f) ImGui::Text("io.ConfigWindowsMemoryCompactTimer = %.1ff", io.ConfigWindowsMemoryCompactTimer); ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags); if (io.BackendFlags & ImGuiBackendFlags_HasGamepad) ImGui::Text(" HasGamepad"); if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) ImGui::Text(" HasMouseCursors"); diff --git a/imgui_internal.h b/imgui_internal.h index a936f69e56250..1018b1e9ddbd8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1321,8 +1321,8 @@ struct IMGUI_API ImGuiWindow ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. + ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure) ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name. - ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack // The best way to understand what those rectangles are is to use the 'Metrics -> Tools -> Show windows rectangles' viewer. // The main 'OuterRect', omitted as a field, is window->Rect(). @@ -1334,6 +1334,7 @@ struct IMGUI_API ImGuiWindow ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. int LastFrameActive; // Last frame number the window was Active. + float LastTimeActive; float ItemWidthDefault; ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; @@ -1352,6 +1353,10 @@ struct IMGUI_API ImGuiWindow ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space + bool MemoryCompacted; + int MemoryDrawListIdxCapacity; + int MemoryDrawListVtxCapacity; + public: ImGuiWindow(ImGuiContext* context, const char* name); ~ImGuiWindow(); @@ -1483,6 +1488,8 @@ namespace ImGui IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); + IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); + IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void SetCurrentFont(ImFont* font); inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } From bfcdaeb6108e5473a967532c712ed36d56d2fee9 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Aug 2019 20:30:36 +0200 Subject: [PATCH 092/200] Disable with ConfigWindowsMemoryCompactTimer < 0.0f (#2636) --- imgui.cpp | 2 +- imgui.h | 2 +- imgui_demo.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6a8cc176a0602..89541b2f7db6e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3851,7 +3851,7 @@ void ImGui::NewFrame() // Mark all windows as not visible and compact unused memory. IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); - const float memory_compact_start_time = (g.IO.ConfigWindowsMemoryCompactTimer > 0.0f) ? (float)g.Time - g.IO.ConfigWindowsMemoryCompactTimer : FLT_MAX; + const float memory_compact_start_time = (g.IO.ConfigWindowsMemoryCompactTimer >= 0.0f) ? (float)g.Time - g.IO.ConfigWindowsMemoryCompactTimer : FLT_MAX; for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; diff --git a/imgui.h b/imgui.h index 28c7d20d5c499..a27017391b542 100644 --- a/imgui.h +++ b/imgui.h @@ -1360,7 +1360,7 @@ struct ImGuiIO bool ConfigInputTextCursorBlink; // = true // Set to false to disable blinking cursor, for users who consider it distracting. (was called: io.OptCursorBlink prior to 1.63) bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsMoveFromTitleBarOnly; // = false // [BETA] Set to true to only allow moving windows when clicked+dragged from the title bar. Windows without a title bar are not affected. - float ConfigWindowsMemoryCompactTimer;// = 60.0f // [BETA] Compact window memory usage when unused. Set to 0.0f to disable. + float ConfigWindowsMemoryCompactTimer;// = 60.0f // [BETA] Compact window memory usage when unused. Set to -1.0f to disable. //------------------------------------------------------------------ // Platform Functions diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 568da3b928c4e..8485f7c9a0f81 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3049,7 +3049,7 @@ void ImGui::ShowAboutWindow(bool* p_open) if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink"); if (io.ConfigWindowsResizeFromEdges) ImGui::Text("io.ConfigWindowsResizeFromEdges"); if (io.ConfigWindowsMoveFromTitleBarOnly) ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly"); - if (io.ConfigWindowsMemoryCompactTimer > 0.0f) ImGui::Text("io.ConfigWindowsMemoryCompactTimer = %.1ff", io.ConfigWindowsMemoryCompactTimer); + if (io.ConfigWindowsMemoryCompactTimer >= 0.0f) ImGui::Text("io.ConfigWindowsMemoryCompactTimer = %.1ff", io.ConfigWindowsMemoryCompactTimer); ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags); if (io.BackendFlags & ImGuiBackendFlags_HasGamepad) ImGui::Text(" HasGamepad"); if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) ImGui::Text(" HasMouseCursors"); From f8d3d8d7f5415e889315c6b7de430ead61ae7aeb Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 29 Aug 2019 12:13:29 +0200 Subject: [PATCH 093/200] TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9dee4195b74e0..649e75ed1282e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,8 @@ Other Changes: when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. +- TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. + Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 79f5b2d490a3d..42e132436e271 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1370,14 +1370,28 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc int count_same_width = 1; while (width_excess > 0.0f && count_same_width < count) { - while (count_same_width < count && items[0].Width == items[count_same_width].Width) + while (count_same_width < count && items[0].Width <= items[count_same_width].Width) count_same_width++; - float width_to_remove_per_item_max = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f); - float width_to_remove_per_item = ImMin(width_excess / count_same_width, width_to_remove_per_item_max); + float max_width_to_remove_per_item = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f); + float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item); for (int item_n = 0; item_n < count_same_width; item_n++) items[item_n].Width -= width_to_remove_per_item; width_excess -= width_to_remove_per_item * count_same_width; } + + // Round width and redistribute remainder left-to-right (could make it an option of the function?) + // Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator. + width_excess = 0.0f; + for (int n = 0; n < count; n++) + { + float width_rounded = ImFloor(items[n].Width); + width_excess += items[n].Width - width_rounded; + items[n].Width = width_rounded; + } + if (width_excess > 0.0f) + for (int n = 0; n < count; n++) + if (items[n].Index < (int)(width_excess + 0.01f)) + items[n].Width += 1.0f; } //------------------------------------------------------------------------- From 3f99890f40c999052e78490b26ce138f80c803b4 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 29 Aug 2019 14:46:02 +0200 Subject: [PATCH 094/200] TabBar: feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) Before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations. Amend f95c77eeeae70383b3e278a33b511e0d63ee16ac. --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 3 ++- imgui_internal.h | 3 ++- imgui_widgets.cpp | 13 ++++++++----- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 649e75ed1282e..d20df9d9f05b9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,8 @@ Other Changes: when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. +- TabBar: feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) + (before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations). - TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8485f7c9a0f81..d5bc96c56524f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4286,7 +4286,6 @@ static void ShowExampleAppWindowTitles(bool*) // Demonstrate using the low-level ImDrawList to draw custom shapes. static void ShowExampleAppCustomRendering(bool* p_open) { - ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Example: Custom rendering", p_open)) { ImGui::End(); @@ -4406,7 +4405,9 @@ static void ShowExampleAppCustomRendering(bool* p_open) static bool draw_bg = true; static bool draw_fg = true; ImGui::Checkbox("Draw in Background draw list", &draw_bg); + ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows."); ImGui::Checkbox("Draw in Foreground draw list", &draw_fg); + ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows."); ImVec2 window_pos = ImGui::GetWindowPos(); ImVec2 window_size = ImGui::GetWindowSize(); ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f); diff --git a/imgui_internal.h b/imgui_internal.h index 1018b1e9ddbd8..e9139d60f42be 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1435,8 +1435,9 @@ struct ImGuiTabBar int CurrFrameVisible; int PrevFrameVisible; ImRect BarRect; - float ContentsHeight; + float LastTabContentHeight; // Record the height of contents submitted below the tab bar float OffsetMax; // Distance from BarRect.Min.x, locked during layout + float OffsetMaxIdeal; // Ideal offset if all tabs were visible and not clipped float OffsetNextTab; // Distance from BarRect.Min.x, incremented with each BeginTabItem() call, not used if ImGuiTabBarFlags_Reorderable if set. float ScrollingAnim; float ScrollingTarget; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 42e132436e271..423a873b63d7d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6290,8 +6290,8 @@ ImGuiTabBar::ImGuiTabBar() ID = 0; SelectedTabId = NextSelectedTabId = VisibleTabId = 0; CurrFrameVisible = PrevFrameVisible = -1; - ContentsHeight = 0.0f; - OffsetMax = OffsetNextTab = 0.0f; + LastTabContentHeight = 0.0f; + OffsetMax = OffsetMaxIdeal = OffsetNextTab = 0.0f; ScrollingAnim = ScrollingTarget = ScrollingTargetDistToVisibility = ScrollingSpeed = 0.0f; Flags = ImGuiTabBarFlags_None; ReorderRequestTabId = 0; @@ -6373,7 +6373,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG tab_bar->FramePadding = g.Style.FramePadding; // Layout - ItemSize(ImVec2(0.0f /*tab_bar->OffsetMax*/, tab_bar->BarRect.GetHeight())); // Don't feed width back + ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight())); window->DC.CursorPos.x = tab_bar->BarRect.Min.x; // Draw separator @@ -6406,9 +6406,9 @@ void ImGui::EndTabBar() // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed(). const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing) - tab_bar->ContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f); + tab_bar->LastTabContentHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f); else - window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->ContentsHeight; + window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->LastTabContentHeight; if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) PopID(); @@ -6532,6 +6532,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) // Layout all active tabs float offset_x = initial_offset_x; + float offset_x_ideal = offset_x; tab_bar->OffsetNextTab = offset_x; // This is used by non-reorderable tab bar where the submission order is always honored. for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) { @@ -6540,8 +6541,10 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID) scroll_track_selected_tab_id = tab->ID; offset_x += tab->Width + g.Style.ItemInnerSpacing.x; + offset_x_ideal += tab->WidthContents + g.Style.ItemInnerSpacing.x; } tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f); + tab_bar->OffsetMaxIdeal = ImMax(offset_x_ideal - g.Style.ItemInnerSpacing.x, 0.0f); // Horizontal scrolling buttons const bool scrolling_buttons = (tab_bar->OffsetMax > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll); From b59ec7b9b7f85c60d26907690126f30bf4f1e11a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 30 Aug 2019 20:28:14 +0200 Subject: [PATCH 095/200] DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. --- docs/CHANGELOG.txt | 1 + imgui.h | 2 ++ imgui_widgets.cpp | 13 ++++++++----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d20df9d9f05b9..33ee2680e18d5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -44,6 +44,7 @@ Other Changes: - TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] +- DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when diff --git a/imgui.h b/imgui.h index a27017391b542..42ee53406ee43 100644 --- a/imgui.h +++ b/imgui.h @@ -426,6 +426,8 @@ namespace ImGui // - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). + // - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits. + // - Use v_min > v_max to lock edits. IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 423a873b63d7d..6cec3827b0c23 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1916,11 +1916,14 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const ImGuiContext& g = *GImGui; const ImGuiAxis axis = (flags & ImGuiDragFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); - const bool has_min_max = (v_min != v_max); - const bool is_power = (power != 1.0f && is_decimal && has_min_max && (v_max - v_min < FLT_MAX)); + const bool is_clamped = (v_min < v_max); + const bool is_power = (power != 1.0f && is_decimal && is_clamped && (v_max - v_min < FLT_MAX)); + const bool is_locked = (v_min > v_max); + if (is_locked) + return false; // Default tweak speed - if (v_speed == 0.0f && has_min_max && (v_max - v_min < FLT_MAX)) + if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX)) v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio); // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings @@ -1948,7 +1951,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const // Clear current value on activation // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. bool is_just_activated = g.ActiveIdIsJustActivated; - bool is_already_past_limits_and_pushing_outward = has_min_max && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); + bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); bool is_drag_direction_change_with_power = is_power && ((adjust_delta < 0 && g.DragCurrentAccum > 0) || (adjust_delta > 0 && g.DragCurrentAccum < 0)); if (is_just_activated || is_already_past_limits_and_pushing_outward || is_drag_direction_change_with_power) { @@ -2000,7 +2003,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const v_cur = (TYPE)0; // Clamp values (+ handle overflow/wrap-around for integer types) - if (*v != v_cur && has_min_max) + if (*v != v_cur && is_clamped) { if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal)) v_cur = v_min; From 0537ac005f7e76311556a4e24c8ddfb4fa1bdcc8 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 30 Aug 2019 20:33:35 +0200 Subject: [PATCH 096/200] ColorEdit: Disable Hue edit when Saturation==0 instead of letting Hue values jump around. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 33ee2680e18d5..a34aef9206d29 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -37,6 +37,7 @@ Other Changes: - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). +- ColorEdit: Disable Hue edit when Saturation==0 instead of letting Hue values jump around. - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. - TabBar: feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6cec3827b0c23..a91268b3206c6 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4234,14 +4234,17 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (n > 0) SameLine(0, style.ItemInnerSpacing.x); SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last); + + // Disable Hue edit when Saturation is zero + const bool disable_hue_edit = (n == 0 && (flags & ImGuiColorEditFlags_DisplayHSV) && i[1] == 0); if (flags & ImGuiColorEditFlags_Float) { - value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); + value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, disable_hue_edit ? +FLT_MAX : 0.0f, disable_hue_edit ? -FLT_MAX : hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); value_changed_as_float |= value_changed; } else { - value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); + value_changed |= DragInt(ids[n], &i[n], 1.0f, disable_hue_edit ? INT_MAX : 0, disable_hue_edit ? INT_MIN : hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context"); From c077dd4872f435dd959feb024e5a9adb2c7df20c Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 31 Aug 2019 19:59:51 +0200 Subject: [PATCH 097/200] Fixed missing IMGUI_API for IsMouseDragPastThreshold(). --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index e9139d60f42be..f13aeedc7df3c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1579,7 +1579,7 @@ namespace ImGui IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel); // Inputs - inline bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); + IMGUI_API bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { const int key_index = GImGui->IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } inline bool IsNavInputDown(ImGuiNavInput n) { return GImGui->IO.NavInputs[n] > 0.0f; } inline bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) { return GetNavInputAmount(n, mode) > 0.0f; } From cc288e073c64114058269d227d4038cf211db2e5 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Sep 2019 12:08:23 +0200 Subject: [PATCH 098/200] Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before ImGui_ImplOpenGL3_NewFrame() if for some reason they wanted. --- docs/CHANGELOG.txt | 2 ++ examples/imgui_impl_opengl3.cpp | 24 +++++++++--------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a34aef9206d29..09381fd5b7181 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,8 @@ Other Changes: - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) +- Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() + before ImGui_ImplOpenGL3_NewFrame() if for some reason they wanted. - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 9585215c41f0c..199638e85f567 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. @@ -164,7 +165,7 @@ void ImGui_ImplOpenGL3_Shutdown() void ImGui_ImplOpenGL3_NewFrame() { - if (!g_FontTexture) + if (!g_ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); } @@ -613,20 +614,13 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() void ImGui_ImplOpenGL3_DestroyDeviceObjects() { - if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); - if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); - g_VboHandle = g_ElementsHandle = 0; - - if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); - if (g_VertHandle) glDeleteShader(g_VertHandle); - g_VertHandle = 0; - - if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle); - if (g_FragHandle) glDeleteShader(g_FragHandle); - g_FragHandle = 0; - - if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle); - g_ShaderHandle = 0; + if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; } + if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; } + if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); } + if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); } + if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; } + if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; } + if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; } ImGui_ImplOpenGL3_DestroyFontsTexture(); } From 3cf519c9cbbfc2f4e91883d8f14e62e82e5d6765 Mon Sep 17 00:00:00 2001 From: Bagrat Dabaghyan Date: Mon, 16 Sep 2019 06:03:42 +0400 Subject: [PATCH 099/200] Fix DragScalar for unsigned types (#2780) decreasing the value was broken on arm64 --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 09381fd5b7181..cf03be73259a4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,7 @@ Other Changes: Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. +- DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a91268b3206c6..e3441ac0db25e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1975,12 +1975,12 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min)); - v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); + v_cur = v_min + (SIGNEDTYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); v_old_ref_for_accum_remainder = v_old_norm_curved; } else { - v_cur += (TYPE)g.DragCurrentAccum; + v_cur += (SIGNEDTYPE)g.DragCurrentAccum; } // Round to user desired precision based on format string From b05f6f6f502752586bb82afb01b942475953677e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 9 Sep 2019 18:09:41 +0900 Subject: [PATCH 100/200] Nav, Scrolling: Added support for Home/End key. (#787) --- docs/CHANGELOG.txt | 1 + docs/TODO.txt | 7 +++-- imgui.cpp | 73 ++++++++++++++++++++++++++++++++++------------ imgui_internal.h | 5 ++-- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cf03be73259a4..5bc49ac7e3468 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,6 +34,7 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Other Changes: +- Nav, Scrolling: Added support for Home/End key. (#787) - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). diff --git a/docs/TODO.txt b/docs/TODO.txt index f289ebab77b3b..70c64c40f3e89 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -300,12 +300,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font/opt: Considering storing standalone AdvanceX table as 16-bit fixed point integer? - font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16 bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8? + - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?) + - nav: configuration flag to disable global shortcuts (currently only CTRL-Tab) ? + - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view? - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window" - nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping(). - nav: patterns to make it possible for arrows key to update selection - - nav: restore/find nearest navid when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) + - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem - - nav: allow input system to be be more tolerant of io.DeltaTime=0.0f - nav: ESC within a menu of a child window seems to exit the child window. - nav: NavFlattened: ESC on a flattened child should select something. - nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child. @@ -323,7 +325,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - nav: when activating a button that changes label (without a static ID) or disappear, can we somehow automatically recover into a nearest highlight item? - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable. - - nav: configuration flag to disable global shortcuts (currently only CTRL-tab) ? - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) diff --git a/imgui.cpp b/imgui.cpp index 89541b2f7db6e..1dc4862a7131e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1078,7 +1078,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& // Navigation static void NavUpdate(); static void NavUpdateWindowing(); -static void NavUpdateWindowingList(); +static void NavUpdateWindowingOverlay(); static void NavUpdateMoveResult(); static float NavUpdatePageUpPageDown(int allowed_dir_flags); static inline void NavUpdateAnyRequestFlag(); @@ -4184,8 +4184,8 @@ void ImGui::EndFrame() End(); // Show CTRL+TAB list window - if (g.NavWindowingTarget) - NavUpdateWindowingList(); + if (g.NavWindowingTarget != NULL) + NavUpdateWindowingOverlay(); // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted) if (g.DragDropActive) @@ -8074,7 +8074,7 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None); - ImGui::NavMoveRequestCancel(); + NavMoveRequestCancel(); g.NavMoveDir = move_dir; g.NavMoveClipDir = clip_dir; g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; @@ -8410,10 +8410,10 @@ static void ImGui::NavUpdate() g.NavMoveRequestFlags = ImGuiNavMoveFlags_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); - ImVec2 delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); + ImVec2 delta_scroll; + if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge) + { + float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f; + delta_scroll.y = result->Window->Scroll.y - scroll_target; + SetScrollY(result->Window, scroll_target); + } + else + { + ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); + delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); + } // Offset our result position so mouse position can be applied immediately after in NavUpdate() result->RectRel.TranslateX(-delta_scroll.x); @@ -8565,6 +8576,7 @@ static void ImGui::NavUpdateMoveResult() g.NavMoveFromClampedRefRect = false; } +// Handle PageUp/PageDown/Home/End keys static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) { ImGuiContext& g = *GImGui; @@ -8574,9 +8586,11 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) return 0.0f; ImGuiWindow* window = g.NavWindow; - bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); - bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); - if (page_up_held != page_down_held) // If either (not both) are pressed + const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); + const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); + const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed { if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) { @@ -8585,26 +8599,49 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); + else if (home_pressed) + SetScrollY(window, 0.0f); + else if (end_pressed) + SetScrollY(window, window->ScrollMax.y); } else { - const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; + ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); float nav_scoring_rect_offset_y = 0.0f; if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) { nav_scoring_rect_offset_y = -page_offset_y; - g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item) g.NavMoveClipDir = ImGuiDir_Up; g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; } else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) { nav_scoring_rect_offset_y = +page_offset_y; - g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item) g.NavMoveClipDir = ImGuiDir_Down; g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; } + else if (home_pressed) + { + // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y + // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result. + // Preserve current horizontal position if we have any. + nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y; + if (nav_rect_rel.IsInverted()) + nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; + g.NavMoveDir = ImGuiDir_Down; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge; + } + else if (end_pressed) + { + nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y; + if (nav_rect_rel.IsInverted()) + nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; + g.NavMoveDir = ImGuiDir_Up; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge; + } return nav_scoring_rect_offset_y; } } @@ -8800,7 +8837,7 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window) } // Overlay displayed when using CTRL+TAB. Called by EndFrame(). -void ImGui::NavUpdateWindowingList() +void ImGui::NavUpdateWindowingOverlay() { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindowingTarget != NULL); diff --git a/imgui_internal.h b/imgui_internal.h index f13aeedc7df3c..9c87d2a14d012 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -497,7 +497,8 @@ enum ImGuiNavMoveFlags_ ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) - ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5 // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. + ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. + ImGuiNavMoveFlags_ScrollToEdge = 1 << 6 }; enum ImGuiNavForward @@ -960,7 +961,7 @@ struct ImGuiContext ImGuiNavMoveFlags NavMoveRequestFlags; ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request - ImGuiDir NavMoveClipDir; + ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) From 3dcf323c35a20914930f6068002e3d4c4815bb87 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Sep 2019 19:03:20 +0200 Subject: [PATCH 101/200] Columns: Separator: Fixed a bug where non-visible separators within columns would alter the next row position differently than visible ones. Fixed rounding issues also leading to change of ScrollMax depending on visible items (in particular negative coordinate would be rounded differently) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 2 +- imgui_widgets.cpp | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5bc49ac7e3468..6e487ae5ca508 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,8 @@ Other Changes: (before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations). - TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. +- Columns, Separator: Fixed a bug where non-visible separators within columns would alter the next row position + differently than visible ones. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d5bc96c56524f..fd1d85a3d55bb 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1451,7 +1451,7 @@ static void ShowDemoWindowWidgets() ImGui::PushID("set2"); static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; const int rows = 3; - const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows); + const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows)); for (int nx = 0; nx < 4; nx++) { if (nx > 0) ImGui::SameLine(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e3441ac0db25e..35ce1436eb21a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1261,7 +1261,10 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) if (!ItemAdd(bb, 0)) { if (columns) + { PopColumnsBackground(); + columns->LineMinY = window->DC.CursorPos.y; + } return; } @@ -5624,7 +5627,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). ImVec2 size; size.x = 0.0f; - size.y = GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f; + size.y = ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f); return ListBoxHeader(label, size); } From 561e7dd49098f2d6c16a21dad7701f73f78545a3 Mon Sep 17 00:00:00 2001 From: Qix Date: Tue, 17 Sep 2019 09:21:09 +0200 Subject: [PATCH 102/200] Fix signed types warning in pasteboard handler (#2786) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1dc4862a7131e..c5039d637e37b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9689,7 +9689,7 @@ static const char* GetClipboardTextFn_DefaultImpl(void*) ItemCount item_count = 0; PasteboardGetItemCount(main_clipboard, &item_count); - for (int i = 0; i < item_count; i++) + for (ItemCount i = 0; i < item_count; i++) { PasteboardItemID item_id = 0; PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id); From e7e88ed413502f1b603e35d389186d3d73a8147a Mon Sep 17 00:00:00 2001 From: NeroBurner Date: Tue, 17 Sep 2019 10:04:40 +0200 Subject: [PATCH 103/200] Examples: SDL/GLFW + OpenGL3: Fixes for Makefile (#2774) - append CXXFLAGS instead of overwriting them - add glad.c build rule --- examples/example_glfw_opengl3/Makefile | 9 +++++---- examples/example_sdl_opengl3/Makefile | 14 ++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/example_glfw_opengl3/Makefile b/examples/example_glfw_opengl3/Makefile index e8cf461462021..7e17476c78cf7 100644 --- a/examples/example_glfw_opengl3/Makefile +++ b/examples/example_glfw_opengl3/Makefile @@ -35,12 +35,11 @@ CXXFLAGS += -I../libs/gl3w ## Using OpenGL loader: glew ## (This assumes a system-wide installation) -# CXXFLAGS = -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW +# CXXFLAGS += -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW ## Using OpenGL loader: glad -## (You'll also need to change the rule at line ~77 of this Makefile to compile/link glad.c/.o) # SOURCES += ../libs/glad/src/glad.c -# CXXFLAGS = -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD +# CXXFLAGS += -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD ##--------------------------------------------------------------------- ## BUILD FLAGS PER PLATFORM @@ -87,7 +86,9 @@ endif $(CXX) $(CXXFLAGS) -c -o $@ $< %.o:../libs/gl3w/GL/%.c -# %.o:../libs/glad/src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +%.o:../libs/glad/src/%.c $(CC) $(CFLAGS) -c -o $@ $< all: $(EXE) diff --git a/examples/example_sdl_opengl3/Makefile b/examples/example_sdl_opengl3/Makefile index 76601a1b888a2..9e84df92b7335 100644 --- a/examples/example_sdl_opengl3/Makefile +++ b/examples/example_sdl_opengl3/Makefile @@ -35,12 +35,11 @@ CXXFLAGS += -I../libs/gl3w ## Using OpenGL loader: glew ## (This assumes a system-wide installation) -# CXXFLAGS = -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW +# CXXFLAGS += -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW ## Using OpenGL loader: glad -## (You'll also need to change the rule at line ~77 of this Makefile to compile/link glad.c/.o) # SOURCES += ../libs/glad/src/glad.c -# CXXFLAGS = -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD +# CXXFLAGS += -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD ##--------------------------------------------------------------------- ## BUILD FLAGS PER PLATFORM @@ -50,7 +49,7 @@ ifeq ($(UNAME_S), Linux) #LINUX ECHO_MESSAGE = "Linux" LIBS += -lGL -ldl `sdl2-config --libs` - CXXFLAGS += -I../libs/gl3w `sdl2-config --cflags` + CXXFLAGS += `sdl2-config --cflags` CFLAGS = $(CXXFLAGS) endif @@ -59,7 +58,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs` LIBS += -L/usr/local/lib -L/opt/local/lib - CXXFLAGS += -I../libs/gl3w `sdl2-config --cflags` + CXXFLAGS += `sdl2-config --cflags` CXXFLAGS += -I/usr/local/include -I/opt/local/include CFLAGS = $(CXXFLAGS) endif @@ -68,7 +67,7 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) ECHO_MESSAGE = "MinGW" LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2` - CXXFLAGS += -I../libs/gl3w `pkg-config --cflags sdl2` + CXXFLAGS += `pkg-config --cflags sdl2` CFLAGS = $(CXXFLAGS) endif @@ -88,6 +87,9 @@ endif %.o:../libs/gl3w/GL/%.c $(CC) $(CFLAGS) -c -o $@ $< +%.o:../libs/glad/src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + all: $(EXE) @echo Build complete for $(ECHO_MESSAGE) From 404dc0367e03a220279bb34e3fe3cb758cd1d4a4 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 10:41:11 +0200 Subject: [PATCH 104/200] BeginTabItem: Fixed case where right-most tab would create an extraneous draw calls (probably related to other tab fitting code in 1.73 wip) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 35ce1436eb21a..ba3bac87bc652 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6932,7 +6932,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImRect bb(pos, pos + size); // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation) - bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x >= tab_bar->BarRect.Max.x); + bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x > tab_bar->BarRect.Max.x); if (want_clip_rect) PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true); From 45405f0dc9f2a3a08883748319aeba9a5afed6e3 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Thu, 5 Sep 2019 12:59:43 +0300 Subject: [PATCH 105/200] Font: implement a way to draw narrow ellipsis without relying on hardcoded 1 pixel dots. (#2775) This changeset implements several pieces of the puzzle that add up to a narrow ellipsis rendering. ## EllipsisCodePoint `ImFontConfig` and `ImFont` received `ImWchar EllipsisCodePoint = -1;` field. User may configure `ImFontConfig::EllipsisCodePoint` a unicode codepoint that will be used for rendering narrow ellipsis. Not setting this field will automatically detect a suitable character or fall back to rendering 3 dots with minimal spacing between them. Autodetection prefers codepoint 0x2026 (narrow ellipsis) and falls back to 0x0085 (NEXT LINE) when missing. Wikipedia indicates that codepoint 0x0085 was used as ellipsis in some older windows fonts. So does default Dear ImGui font. When user is merging fonts - first configured and present ellipsis codepoint will be used, ellipsis characters from subsequently merged fonts will be ignored. ## Narrow ellipsis Rendering a narrow ellipsis is surprisingly not straightforward task. There are cases when ellipsis is bigger than the last visible character therefore `RenderTextEllipsis()` has to hide last two characters. In a subset of those cases ellipsis is as big as last visible character + space before it. `RenderTextEllipsis()` tries to work around this case by taking free space between glyph edges into account. Code responsible for this functionality is within `if (text_end_ellipsis != text_end_full) { ... }`. ## Fallback (manually rendered dots) There are cases when font does not have ellipsis character defined. In this case RenderTextEllipsis() falls back to rendering ellipsis as 3 dots, but with reduced spacing between them. 1 pixel space is used in all cases. This results in a somewhat wider ellipsis, but avoids issues where spaces between dots are uneven (visible in larger/monospace fonts) or squish dots way too much (visible in default font where dot is essentially a pixel). This fallback method obsoleted `RenderPixelEllipsis()` and this function was removed. Note that fallback ellipsis will always be somewhat wider than it could be, however it will fit in visually into every font used unlike what `RenderPixelEllipsis()` produced. --- imgui.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++---- imgui.h | 2 + imgui_draw.cpp | 39 +++++++++++++------- imgui_internal.h | 1 - 4 files changed, 117 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c5039d637e37b..7921b1d13718a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2489,7 +2489,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. -void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) +void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; if (text_end_full == NULL) @@ -2503,15 +2503,42 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, // min max ellipsis_max // <-> this is generally some padding value - // FIXME-STYLE: RenderPixelEllipsis() style should use actual font data. const ImFont* font = draw_list->_Data->Font; const float font_size = draw_list->_Data->FontSize; - const int ellipsis_dot_count = 3; - const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f; const char* text_end_ellipsis = NULL; + const ImFontGlyph* glyph; + int ellipsis_char_num = 1; + ImWchar ellipsis_codepoint = font->EllipsisCodePoint; + if (ellipsis_codepoint != (ImWchar)-1) + glyph = font->FindGlyph(ellipsis_codepoint); + else + { + ellipsis_codepoint = (ImWchar)'.'; + glyph = font->FindGlyph(ellipsis_codepoint); + ellipsis_char_num = 3; + } + + float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side + float ellipsis_width = ellipsis_glyph_width; // Full width of entire ellipsis + float push_left = 1.f; + + if (ellipsis_char_num > 1) + { + const float spacing_between_dots = 1.f * (draw_list->_Data->FontSize / font->FontSize); + ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; + // Full ellipsis size without free spacing after it. + ellipsis_width = ellipsis_glyph_width * (float)ellipsis_char_num - spacing_between_dots; + if (glyph->X0 > 1.f) + { + // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). + push_left = 0.f; + } + } + float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f); float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { // Always display at least 1 character if there's no room for character + ellipsis @@ -2524,11 +2551,66 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, text_end_ellipsis--; text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } + + if (text_end_ellipsis != text_end_full) + { + // +---- First invisible character we arrived at. + // / +-- Character that we hope to be first invisible. + // [l][i] + // |||| + // \ \__ extra_spacing when two characters got hidden + // \___ extra_spacing when one character got hidden + unsigned c = 0; + float extra_spacing = 0; + const char* text_end_ellipsis_prev = text_end_ellipsis; + text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); + if (c && !ImCharIsBlankW(c)) + { + const ImFontGlyph* hidden_glyph = font->FindGlyph(c); + // Free space after first invisible glyph + extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1; + c = 0; + text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); + if (c && !ImCharIsBlankW(c)) + { + hidden_glyph = font->FindGlyph(text_end_ellipsis[1]); + // Space before next invisible glyph. This intentionally ignores space from the first invisible + // glyph as that space will serve as spacing between ellipsis and last visible character. Without + // doing this we may get into awkward situations where ellipsis pretty much sticks to the last + // visible character. This issue manifests with the default font for word "Brocolli" there both i + // and l are very thin. Unfortunately this makes fonts with wider gaps (like monospace) look a bit + // worse, but it is a fair middle ground. + extra_spacing = hidden_glyph->X0; + } + } + + if (extra_spacing > 0) + { + // Repeat calculation hoping that we will get extra character visible + text_width += extra_spacing; + // Text length calculation is essentially an optimized version of this: + // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + // It avoids calculating entire width of the string. + text_size_clipped_x += font->CalcTextSizeA(font_size, text_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; + } + else + text_end_ellipsis = text_end_ellipsis_prev; + } + RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); - const float ellipsis_x = pos_min.x + text_size_clipped_x + 1.0f; - if (ellipsis_x + ellipsis_width - 1.0f <= ellipsis_max_x) - RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_dot_count); + // This variable pushes ellipsis to the left from last visible character. This is mostly useful when rendering + // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra + // spacing is not needed. + float ellipsis_x = pos_min.x + text_size_clipped_x + push_left; + if (ellipsis_x + ellipsis_width - push_left <= ellipsis_max_x) + { + for (int i = 0; i < ellipsis_char_num; i++) + { + font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_codepoint); + ellipsis_x += ellipsis_glyph_width; + } + } } else { diff --git a/imgui.h b/imgui.h index 42ee53406ee43..d4a81c3bb4708 100644 --- a/imgui.h +++ b/imgui.h @@ -2011,6 +2011,7 @@ struct ImFontConfig bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. + ImWchar EllipsisCodePoint; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] char Name[40]; // Name (strictly to ease debugging) @@ -2192,6 +2193,7 @@ struct ImFont float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) bool DirtyLookupTables; // 1 // out // + ImWchar EllipsisCodePoint; // -1 // out // // Override a codepoint used for ellipsis rendering. // Methods IMGUI_API ImFont(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3eb1067efcd5d..b4801c26a2aaf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1428,6 +1428,7 @@ ImFontConfig::ImFontConfig() RasterizerMultiply = 1.0f; memset(Name, 0, sizeof(Name)); DstFont = NULL; + EllipsisCodePoint = (ImWchar)-1; } //----------------------------------------------------------------------------- @@ -1618,6 +1619,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); } + if (new_font_cfg.DstFont->EllipsisCodePoint == (ImWchar)-1) + new_font_cfg.DstFont->EllipsisCodePoint = font_cfg->EllipsisCodePoint; + // Invalidate texture ClearTexData(); return new_font_cfg.DstFont; @@ -1652,6 +1656,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) font_cfg.SizePixels = 13.0f * 1.0f; if (font_cfg.Name[0] == '\0') ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); + font_cfg.EllipsisCodePoint = (ImWchar)0x0085; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); @@ -2196,6 +2201,26 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) for (int i = 0; i < atlas->Fonts.Size; i++) if (atlas->Fonts[i]->DirtyLookupTables) atlas->Fonts[i]->BuildLookupTable(); + + // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). + // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. + for (int i = 0; i < atlas->Fonts.size(); i++) + { + ImFont* font = atlas->Fonts[i]; + if (font->EllipsisCodePoint == (ImWchar)-1) + { + const ImWchar ellipsis_variants[] = {(ImWchar)0x2026, (ImWchar)0x0085, (ImWchar)0}; + for (int j = 0; ellipsis_variants[j] != (ImWchar) 0; j++) + { + ImWchar ellipsis_codepoint = ellipsis_variants[j]; + if (font->FindGlyph(ellipsis_codepoint) != font->FallbackGlyph) // Verify glyph exists + { + font->EllipsisCodePoint = ellipsis_codepoint; + break; + } + } + } + } } // Retrieve list of range (2 int per range, values are inclusive) @@ -2474,6 +2499,7 @@ ImFont::ImFont() Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; + EllipsisCodePoint = (ImWchar)-1; } ImFont::~ImFont() @@ -3012,7 +3038,6 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // - RenderMouseCursor() // - RenderArrowPointingAt() // - RenderRectFilledRangeH() -// - RenderPixelEllipsis() //----------------------------------------------------------------------------- void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor) @@ -3122,18 +3147,6 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im draw_list->PathFillConvex(col); } -// FIXME: Rendering an ellipsis "..." is a surprisingly tricky problem for us... we cannot rely on font glyph having it, -// and regular dot are typically too wide. If we render a dot/shape ourselves it comes with the risk that it wouldn't match -// the boldness or positioning of what the font uses... -void ImGui::RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, ImU32 col, int count) -{ - ImFont* font = draw_list->_Data->Font; - const float font_scale = draw_list->_Data->FontSize / font->FontSize; - pos.y += (float)(int)(font->DisplayOffset.y + font->Ascent * font_scale + 0.5f - 1.0f); - for (int dot_n = 0; dot_n < count; dot_n++) - draw_list->AddRectFilled(ImVec2(pos.x + dot_n * 2.0f, pos.y), ImVec2(pos.x + dot_n * 2.0f + 1.0f, pos.y + 1.0f), col); -} - //----------------------------------------------------------------------------- // [SECTION] Decompression code //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 9c87d2a14d012..ea8a4099068f7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1635,7 +1635,6 @@ namespace ImGui IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); - IMGUI_API void RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, ImU32 col, int count); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while. From 57623c15ddae10a6b0ba6b206d2502e7951dd705 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 10:00:28 +0200 Subject: [PATCH 106/200] Font: Narrow ellipsis: various minor stylistic tweaks (#2775) --- docs/CHANGELOG.txt | 4 +++ docs/TODO.txt | 1 + imgui.cpp | 61 ++++++++++++++++++++-------------------------- imgui.h | 6 ++--- imgui_demo.cpp | 3 ++- imgui_draw.cpp | 29 ++++++++++------------ 6 files changed, 49 insertions(+), 55 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6e487ae5ca508..36ba83ba87ed0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,10 @@ Other Changes: - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] +- Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly + unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. + Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow + as possible. (#2775) [@rokups] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when diff --git a/docs/TODO.txt b/docs/TODO.txt index 70c64c40f3e89..df413b7e32d46 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -275,6 +275,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: MergeMode: flags to select overwriting or not (this is now very easy with refactored ImFontAtlasBuildWithStbTruetype) - font: free the Alpha buffer if user only requested RGBA. !- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions). + - font: for the purpose of RenderTextEllipsis(), it might be useful that CalcTextSizeA() can ignore the trailing padding? - font: a CalcTextHeight() helper could run faster than CalcTextSize().y - font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX - font: finish CustomRectRegister() to allow mapping Unicode codepoint to custom texture data diff --git a/imgui.cpp b/imgui.cpp index 7921b1d13718a..4a606daa362fa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2506,38 +2506,32 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con const ImFont* font = draw_list->_Data->Font; const float font_size = draw_list->_Data->FontSize; const char* text_end_ellipsis = NULL; - const ImFontGlyph* glyph; - int ellipsis_char_num = 1; - ImWchar ellipsis_codepoint = font->EllipsisCodePoint; - if (ellipsis_codepoint != (ImWchar)-1) - glyph = font->FindGlyph(ellipsis_codepoint); - else + ImWchar ellipsis_char = font->EllipsisChar; + int ellipsis_char_count = 1; + if (ellipsis_char == (ImWchar)-1) { - ellipsis_codepoint = (ImWchar)'.'; - glyph = font->FindGlyph(ellipsis_codepoint); - ellipsis_char_num = 3; + ellipsis_char = (ImWchar)'.'; + ellipsis_char_count = 3; } + const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char); - float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side - float ellipsis_width = ellipsis_glyph_width; // Full width of entire ellipsis - float push_left = 1.f; + float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side + float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis + float push_left = 1.0f; - if (ellipsis_char_num > 1) + if (ellipsis_char_count > 1) { - const float spacing_between_dots = 1.f * (draw_list->_Data->FontSize / font->FontSize); - ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; // Full ellipsis size without free spacing after it. - ellipsis_width = ellipsis_glyph_width * (float)ellipsis_char_num - spacing_between_dots; - if (glyph->X0 > 1.f) - { - // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). - push_left = 0.f; - } + const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize); + ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; + ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots; + if (glyph->X0 > 1.0f) + push_left = 0.0f; // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). } - float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f); - float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + float text_avail_width = ImMax((pos_max.x - ellipsis_total_width) - pos_min.x, 1.0f); + float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { @@ -2547,7 +2541,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con } while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1])) { - // Trim trailing space before ellipsis + // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text) text_end_ellipsis--; text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } @@ -2560,16 +2554,15 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con // |||| // \ \__ extra_spacing when two characters got hidden // \___ extra_spacing when one character got hidden - unsigned c = 0; - float extra_spacing = 0; + unsigned int c = 0; + float extra_spacing = 0.0f; const char* text_end_ellipsis_prev = text_end_ellipsis; text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); if (c && !ImCharIsBlankW(c)) { - const ImFontGlyph* hidden_glyph = font->FindGlyph(c); // Free space after first invisible glyph + const ImFontGlyph* hidden_glyph = font->FindGlyph((ImWchar)c); extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1; - c = 0; text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); if (c && !ImCharIsBlankW(c)) { @@ -2587,11 +2580,11 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con if (extra_spacing > 0) { // Repeat calculation hoping that we will get extra character visible - text_width += extra_spacing; + text_avail_width += extra_spacing; // Text length calculation is essentially an optimized version of this: // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; // It avoids calculating entire width of the string. - text_size_clipped_x += font->CalcTextSizeA(font_size, text_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; + text_size_clipped_x += font->CalcTextSizeA(font_size, text_avail_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; } else text_end_ellipsis = text_end_ellipsis_prev; @@ -2603,14 +2596,12 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra // spacing is not needed. float ellipsis_x = pos_min.x + text_size_clipped_x + push_left; - if (ellipsis_x + ellipsis_width - push_left <= ellipsis_max_x) - { - for (int i = 0; i < ellipsis_char_num; i++) + if (ellipsis_x + ellipsis_total_width - push_left <= ellipsis_max_x) + for (int i = 0; i < ellipsis_char_count; i++) { - font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_codepoint); + font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char); ellipsis_x += ellipsis_glyph_width; } - } } else { diff --git a/imgui.h b/imgui.h index d4a81c3bb4708..9e875f8972ef6 100644 --- a/imgui.h +++ b/imgui.h @@ -2011,7 +2011,7 @@ struct ImFontConfig bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. - ImWchar EllipsisCodePoint; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. + ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] char Name[40]; // Name (strictly to ease debugging) @@ -2188,12 +2188,12 @@ struct ImFont ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. - ImWchar FallbackChar; // 2 // in // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() + ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar() + ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering. float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) bool DirtyLookupTables; // 1 // out // - ImWchar EllipsisCodePoint; // -1 // out // // Override a codepoint used for ellipsis rendering. // Methods IMGUI_API ImFont(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fd1d85a3d55bb..e8e874698a2ab 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3283,7 +3283,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SameLine(); HelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f"); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); - ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); + ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar); + ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar); const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b4801c26a2aaf..dd21523e410db 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1426,9 +1426,9 @@ ImFontConfig::ImFontConfig() MergeMode = false; RasterizerFlags = 0x00; RasterizerMultiply = 1.0f; + EllipsisChar = (ImWchar)-1; memset(Name, 0, sizeof(Name)); DstFont = NULL; - EllipsisCodePoint = (ImWchar)-1; } //----------------------------------------------------------------------------- @@ -1619,8 +1619,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); } - if (new_font_cfg.DstFont->EllipsisCodePoint == (ImWchar)-1) - new_font_cfg.DstFont->EllipsisCodePoint = font_cfg->EllipsisCodePoint; + if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1) + new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; // Invalidate texture ClearTexData(); @@ -1656,7 +1656,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) font_cfg.SizePixels = 13.0f * 1.0f; if (font_cfg.Name[0] == '\0') ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); - font_cfg.EllipsisCodePoint = (ImWchar)0x0085; + font_cfg.EllipsisChar = (ImWchar)0x0085; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); @@ -2204,22 +2204,19 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. + // FIXME: Also note that 0x2026 is currently seldomly included in our font ranges. Because of this we are more likely to use three individual dots. for (int i = 0; i < atlas->Fonts.size(); i++) { ImFont* font = atlas->Fonts[i]; - if (font->EllipsisCodePoint == (ImWchar)-1) - { - const ImWchar ellipsis_variants[] = {(ImWchar)0x2026, (ImWchar)0x0085, (ImWchar)0}; - for (int j = 0; ellipsis_variants[j] != (ImWchar) 0; j++) + if (font->EllipsisChar != (ImWchar)-1) + continue; + const ImWchar ellipsis_variants[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; + for (int j = 0; j < IM_ARRAYSIZE(ellipsis_variants); j++) + if (font->FindGlyphNoFallback(ellipsis_variants[j]) != NULL) // Verify glyph exists { - ImWchar ellipsis_codepoint = ellipsis_variants[j]; - if (font->FindGlyph(ellipsis_codepoint) != font->FallbackGlyph) // Verify glyph exists - { - font->EllipsisCodePoint = ellipsis_codepoint; - break; - } + font->EllipsisChar = ellipsis_variants[j]; + break; } - } } } @@ -2490,6 +2487,7 @@ ImFont::ImFont() FontSize = 0.0f; FallbackAdvanceX = 0.0f; FallbackChar = (ImWchar)'?'; + EllipsisChar = (ImWchar)-1; DisplayOffset = ImVec2(0.0f, 0.0f); FallbackGlyph = NULL; ContainerAtlas = NULL; @@ -2499,7 +2497,6 @@ ImFont::ImFont() Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; - EllipsisCodePoint = (ImWchar)-1; } ImFont::~ImFont() From 1c951dca977e24018110aff7374d7cb3a062e5da Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 11:11:14 +0200 Subject: [PATCH 107/200] Font: Narrow ellipsis: once we know an ellipsis is going to be drawn, we can claim the space between pos_max.x and ellipsis_max.x which gives us enough extra space to not requires the further (and otherwise valid) optimizations. Gets us vastly simplified code, yay. (#2775) --- imgui.cpp | 64 ++++++++----------------------------------------------- 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4a606daa362fa..80e8a280de2d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2496,6 +2496,10 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con text_end_full = FindRenderedTextEnd(text); const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f); + //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255)); + //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255)); + //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255)); + // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels. if (text_size.x > pos_max.x - pos_min.x) { // Hello wo... @@ -2518,7 +2522,6 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis - float push_left = 1.0f; if (ellipsis_char_count > 1) { @@ -2526,13 +2529,11 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize); ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots; - if (glyph->X0 > 1.0f) - push_left = 0.0f; // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). } - float text_avail_width = ImMax((pos_max.x - ellipsis_total_width) - pos_min.x, 1.0f); + // We can now claim the space between pos_max.x and ellipsis_max.x + const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f); float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; - if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { // Always display at least 1 character if there's no room for character + ellipsis @@ -2546,57 +2547,10 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } - if (text_end_ellipsis != text_end_full) - { - // +---- First invisible character we arrived at. - // / +-- Character that we hope to be first invisible. - // [l][i] - // |||| - // \ \__ extra_spacing when two characters got hidden - // \___ extra_spacing when one character got hidden - unsigned int c = 0; - float extra_spacing = 0.0f; - const char* text_end_ellipsis_prev = text_end_ellipsis; - text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); - if (c && !ImCharIsBlankW(c)) - { - // Free space after first invisible glyph - const ImFontGlyph* hidden_glyph = font->FindGlyph((ImWchar)c); - extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1; - text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); - if (c && !ImCharIsBlankW(c)) - { - hidden_glyph = font->FindGlyph(text_end_ellipsis[1]); - // Space before next invisible glyph. This intentionally ignores space from the first invisible - // glyph as that space will serve as spacing between ellipsis and last visible character. Without - // doing this we may get into awkward situations where ellipsis pretty much sticks to the last - // visible character. This issue manifests with the default font for word "Brocolli" there both i - // and l are very thin. Unfortunately this makes fonts with wider gaps (like monospace) look a bit - // worse, but it is a fair middle ground. - extra_spacing = hidden_glyph->X0; - } - } - - if (extra_spacing > 0) - { - // Repeat calculation hoping that we will get extra character visible - text_avail_width += extra_spacing; - // Text length calculation is essentially an optimized version of this: - // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; - // It avoids calculating entire width of the string. - text_size_clipped_x += font->CalcTextSizeA(font_size, text_avail_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; - } - else - text_end_ellipsis = text_end_ellipsis_prev; - } - + // Render text, render ellipsis RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); - - // This variable pushes ellipsis to the left from last visible character. This is mostly useful when rendering - // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra - // spacing is not needed. - float ellipsis_x = pos_min.x + text_size_clipped_x + push_left; - if (ellipsis_x + ellipsis_total_width - push_left <= ellipsis_max_x) + float ellipsis_x = pos_min.x + text_size_clipped_x; + if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x) for (int i = 0; i < ellipsis_char_count; i++) { font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char); From 7d5a17e5e4a36f2cabccfb97e9da4db0983eec56 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 11:33:18 +0200 Subject: [PATCH 108/200] Remove trailing spaces (grep for ' \r?$' in visual studio) --- imconfig.h | 6 +++--- imgui.cpp | 42 +++++++++++++++++++++--------------------- imgui.h | 14 +++++++------- imgui_demo.cpp | 8 ++++---- imgui_draw.cpp | 4 ++-- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 36 ++++++++++++++++++------------------ 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/imconfig.h b/imconfig.h index 22a21db0fc108..45e75ecfcf4f8 100644 --- a/imconfig.h +++ b/imconfig.h @@ -17,7 +17,7 @@ //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts -//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows +//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows // Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. //#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllimport ) @@ -64,9 +64,9 @@ operator MyVec4() const { return MyVec4(x,y,z,w); } */ -//---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices. +//---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices. // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bits indices). -// Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer. +// Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer. // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. //#define ImDrawIdx unsigned int diff --git a/imgui.cpp b/imgui.cpp index c5039d637e37b..b1d8522caa3f3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -575,17 +575,17 @@ CODE Q: Where is the documentation? A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. - Run the examples/ and explore them. - - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. - - The demo covers most features of Dear ImGui, so you can read the code and see its output. + - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. + - The demo covers most features of Dear ImGui, so you can read the code and see its output. - See documentation and comments at the top of imgui.cpp + effectively imgui.h. - - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ + - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application. - - Your programming IDE is your friend, find the type or function declaration to find comments + - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. Q: Which version should I get? - A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe - and recommended to sync to master/latest. The library is fairly stable and regressions tend to be + A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe + and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. You may also peak at the 'docking' branch which includes: - Docking/Merging features (https://github.com/ocornut/imgui/issues/2109) - Multi-viewport features (https://github.com/ocornut/imgui/issues/1542) @@ -597,11 +597,11 @@ CODE for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"? - A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when - when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI - (immediate-mode graphical user interface) was coined before and is being used in variety of other - situations (e.g. Unity uses it own implementation of the IMGUI paradigm). - To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, + A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when + when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI + (immediate-mode graphical user interface) was coined before and is being used in variety of other + situations (e.g. Unity uses it own implementation of the IMGUI paradigm). + To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui". @@ -2488,7 +2488,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. -// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. +// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; @@ -2996,8 +2996,8 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) { // Navigation processing runs prior to clipping early-out // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget - // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests - // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of + // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests + // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). @@ -4044,7 +4044,7 @@ static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* d return; } - // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. // May trigger for you if you are using PrimXXX functions incorrectly. IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); @@ -4053,7 +4053,7 @@ static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* d // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) // If this assert triggers because you are drawing lots of stuff manually: - // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. + // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. // Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents. // - If you want large meshes with more than 64K vertices, you can either: // (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'. @@ -4062,9 +4062,9 @@ static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* d // (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h. // Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time: // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); - // Your own engine or render API may use different parameters or function calls to specify index sizes. + // Your own engine or render API may use different parameters or function calls to specify index sizes. // 2 and 4 bytes indices are generally supported by most graphics API. - // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching + // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching // the 64K limit to split your draw commands in multiple draw lists. if (sizeof(ImDrawIdx) == 2) IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); @@ -4381,7 +4381,7 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key) // Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]! bool ImGui::IsKeyDown(int user_key_index) { - if (user_key_index < 0) + if (user_key_index < 0) return false; ImGuiContext& g = *GImGui; IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); @@ -5741,7 +5741,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->OuterRectClipped.ClipWith(host_rect); // Inner rectangle - // Not affected by window border size. Used by: + // Not affected by window border size. Used by: // - InnerClipRect // - ScrollToBringRectIntoView() // - NavUpdatePageUpPageDown() @@ -5819,7 +5819,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) render_decorations_in_parent = true; if (render_decorations_in_parent) window->DrawList = parent_window->DrawList; - + // Handle title bar, scrollbar, resize grips and resize borders const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); diff --git a/imgui.h b/imgui.h index 42ee53406ee43..6118d5378ea24 100644 --- a/imgui.h +++ b/imgui.h @@ -328,7 +328,7 @@ namespace ImGui IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, + IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, IMGUI_API void PopItemWidth(); IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. @@ -1764,7 +1764,7 @@ struct ImColor // Draw callbacks for advanced uses. // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, -// you can poke into the draw list for that! Draw callback may be useful for example to: +// you can poke into the draw list for that! Draw callback may be useful for example to: // A) Change your GPU render state, // B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. // The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }' @@ -1795,7 +1795,7 @@ struct ImDrawCmd ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; } }; -// Vertex index +// Vertex index // (to allow large meshes with 16-bits indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer back-end) // (to use 32-bits indices: override with '#define ImDrawIdx unsigned int' in imconfig.h) #ifndef ImDrawIdx @@ -1826,7 +1826,7 @@ struct ImDrawChannel }; // Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. -// This is used by the Columns api, so items of each column can be batched together in a same draw call. +// This is used by the Columns api, so items of each column can be batched together in a same draw call. struct ImDrawListSplitter { int _Current; // Current channel number (0) @@ -1867,7 +1867,7 @@ enum ImDrawListFlags_ // Draw command list // This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame, // all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. -// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to +// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to // access the current window draw list and draw custom primitives. // You can interleave normal ImGui:: calls and adding primitives to the current draw list. // All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well) @@ -2126,9 +2126,9 @@ struct ImFontAtlas // [BETA] Custom Rectangles/Glyphs API //------------------------------------------- - // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. + // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. // After calling Build(), you can query the rectangle position and render your pixels. - // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), + // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), // so you can render e.g. custom colorful icons and use them as regular glyphs. // Read misc/fonts/README.txt for more details about using colorful icons. IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fd1d85a3d55bb..3a652a1683383 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -17,7 +17,7 @@ // In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is // essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data // in the same place, to make the demo source code faster to read, faster to write, and smaller in size. -// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be +// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be // reentrant or used in multiple threads. This might be a pattern you will want to use in your code, but most of the real data // you would be editing is likely going to be stored outside your functions. @@ -589,7 +589,7 @@ static void ShowDemoWindowWidgets() { for (int i = 0; i < 5; i++) { - // Use SetNextItemOpen() so set the default state of a node to be open. + // Use SetNextItemOpen() so set the default state of a node to be open. // We could also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing! if (i == 0) ImGui::SetNextItemOpen(true, ImGuiCond_Once); @@ -1109,7 +1109,7 @@ static void ShowDemoWindowWidgets() if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } } - // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, + // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); @@ -2259,7 +2259,7 @@ static void ShowDemoWindowLayout() ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::DragFloat("##csx", &contents_size_x); - ImVec2 p = ImGui::GetCursorScreenPos(); + ImVec2 p = ImGui::GetCursorScreenPos(); ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE); ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE); ImGui::Dummy(ImVec2(0, 10)); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3eb1067efcd5d..f383220111922 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1202,7 +1202,7 @@ void ImDrawListSplitter::ClearFreeMemory() { for (int i = 0; i < _Channels.Size; i++) { - if (i == _Current) + if (i == _Current) memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again _Channels[i]._CmdBuffer.clear(); _Channels[i]._IdxBuffer.clear(); @@ -1307,7 +1307,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list) void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) { IM_ASSERT(idx >= 0 && idx < _Count); - if (_Current == idx) + if (_Current == idx) return; // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer)); diff --git a/imgui_internal.h b/imgui_internal.h index 9c87d2a14d012..ca51e51b7faa0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -809,7 +809,7 @@ struct ImGuiNextWindowData void* SizeCallbackUserData; float BgAlphaVal; ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. - + ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } }; @@ -1710,7 +1710,7 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned ch // Debug Tools // Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. -#ifndef IM_DEBUG_BREAK +#ifndef IM_DEBUG_BREAK #if defined(__clang__) #define IM_DEBUG_BREAK() __builtin_debugtrap() #elif defined (_MSC_VER) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba3bac87bc652..f924bbd1e8ed5 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -399,37 +399,37 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // See the series of events below and the corresponding state reported by dear imgui: //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() -// Frame N+0 (mouse is outside bb) - - - - - - -// Frame N+1 (mouse moves inside bb) - true - - - - +// Frame N+0 (mouse is outside bb) - - - - - - +// Frame N+1 (mouse moves inside bb) - true - - - - // Frame N+2 (mouse button is down) - true true true - true -// Frame N+3 (mouse button is down) - true true - - - +// Frame N+3 (mouse button is down) - true true - - - // Frame N+4 (mouse moves outside bb) - - true - - - // Frame N+5 (mouse moves inside bb) - true true - - - -// Frame N+6 (mouse button is released) true true - - true - -// Frame N+7 (mouse button is released) - true - - - - -// Frame N+8 (mouse moves outside bb) - - - - - - +// Frame N+6 (mouse button is released) true true - - true - +// Frame N+7 (mouse button is released) - true - - - - +// Frame N+8 (mouse moves outside bb) - - - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+2 (mouse button is down) true true true true - true -// Frame N+3 (mouse button is down) - true true - - - -// Frame N+6 (mouse button is released) - true - - true - -// Frame N+7 (mouse button is released) - true - - - - +// Frame N+3 (mouse button is down) - true true - - - +// Frame N+6 (mouse button is released) - true - - true - +// Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+2 (mouse button is down) - true - - - true -// Frame N+3 (mouse button is down) - true - - - - +// Frame N+3 (mouse button is down) - true - - - - // Frame N+6 (mouse button is released) true true - - - - -// Frame N+7 (mouse button is released) - true - - - - +// Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+0 (mouse button is down) - true - - - true -// Frame N+1 (mouse button is down) - true - - - - +// Frame N+1 (mouse button is down) - true - - - - // Frame N+2 (mouse button is released) - true - - - - -// Frame N+3 (mouse button is released) - true - - - - +// Frame N+3 (mouse button is released) - true - - - - // Frame N+4 (mouse button is down) true true true true - true -// Frame N+5 (mouse button is down) - true true - - - +// Frame N+5 (mouse button is down) - true true - - - // Frame N+6 (mouse button is released) - true - - true - -// Frame N+7 (mouse button is released) - true - - - - +// Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // Note that some combinations are supported, // - PressedOnDragDropHold can generally be associated with any flag. @@ -439,7 +439,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // Repeat+ Repeat+ Repeat+ Repeat+ // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick //------------------------------------------------------------------------------------------------------------------------------------------------- -// Frame N+0 (mouse button is down) - true - true +// Frame N+0 (mouse button is down) - true - true // ... - - - - // Frame N + RepeatDelay true true - true // ... - - - - @@ -5507,7 +5507,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); - // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard + // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) { if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) @@ -7291,7 +7291,7 @@ void ImGui::PushColumnsBackground() return; window->DrawList->ChannelsSetCurrent(0); int cmd_size = window->DrawList->CmdBuffer.Size; - PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); + PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); IM_UNUSED(cmd_size); IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd } From 3f986e72d955795ea0306c2b6c1007dc0ad53776 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 12:06:31 +0200 Subject: [PATCH 109/200] Internal: Offset STB_TEXTURE_K_ defines to remove that change from #2541 + sponsors update. --- docs/README.md | 4 ++-- imgui_widgets.cpp | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5a706354fc01c..a07acc79f87b5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -311,10 +311,10 @@ Ongoing dear imgui development is financially supported by users and private spo - Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn. **Salty caramel supporters** -- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, Morten Skaaning, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford. +- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders. **Caramel supporters** -- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis. +- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis. And all other past and present supporters; THANK YOU! (Please contact me if you would like to be added or removed from this list) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f924bbd1e8ed5..3cd0638ba70ca 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3222,21 +3222,21 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im } // We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) -#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left -#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right -#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up -#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down -#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line -#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line -#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text -#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text -#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor -#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor -#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo -#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo -#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word -#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word -#define STB_TEXTEDIT_K_SHIFT 0x20000 +#define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left +#define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right +#define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up +#define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down +#define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line +#define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line +#define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text +#define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text +#define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor +#define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor +#define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo +#define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo +#define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word +#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word +#define STB_TEXTEDIT_K_SHIFT 0x400000 #define STB_TEXTEDIT_IMPLEMENTATION #include "imstb_textedit.h" From b48dc067ae794cd9159397b338a985c0b906404d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 16:16:38 +0200 Subject: [PATCH 110/200] Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) + Fix #2775 --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 ++-- imgui.h | 2 +- imgui_demo.cpp | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 36ba83ba87ed0..0c3a28d68efce 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Other Changes: - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] +- Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) - Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow diff --git a/imgui.cpp b/imgui.cpp index c4b3425d81247..d717fb17d1f2e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3692,7 +3692,7 @@ static void NewFrameSanityChecks() IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!"); IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); - IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); + IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); for (int n = 0; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); @@ -5314,7 +5314,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl ImGuiWindowFlags flags = window->Flags; const bool has_close_button = (p_open != NULL); - const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse); + const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None); // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer) const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; diff --git a/imgui.h b/imgui.h index 965e81a0e311e..a3faa620f71ac 100644 --- a/imgui.h +++ b/imgui.h @@ -1289,7 +1289,7 @@ struct ImGuiStyle float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints(). ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. - ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left. + ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left. float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e7ffdddd49d1e..13877cd55885c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3195,7 +3195,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); ImGui::Text("Alignment"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); - ImGui::Combo("WindowMenuButtonPosition", (int*)&style.WindowMenuButtonPosition, "Left\0Right\0"); + int window_menu_button_position = style.WindowMenuButtonPosition + 1; + if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0")) + style.WindowMenuButtonPosition = window_menu_button_position - 1; ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content."); @@ -3284,7 +3286,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f"); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar); - ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar); + ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar); const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) From 098591fe4c95dd4939d0c6e30d18f6b1ff49e49d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 20:27:15 +0200 Subject: [PATCH 111/200] ImDrawListSplitter: fixed an issue merging channels if the last submitted draw command used a different texture. (#2506) --- docs/CHANGELOG.txt | 1 + imgui_draw.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0c3a28d68efce..dcb8fab1aeec5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other Changes: Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow as possible. (#2775) [@rokups] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) +- ImDrawListSplitter: fixed an issue merging channels if the last submitted draw command used a different texture. (#2506) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e1a023d7b386c..eb173b4422d2d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1301,6 +1301,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list) } draw_list->_IdxWritePtr = idx_write; draw_list->UpdateClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call. + draw_list->UpdateTextureID(); _Count = 1; } From 74e01e62ceadcbc859644657cb98de9271fc266a Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 18 Sep 2019 13:21:12 +0200 Subject: [PATCH 112/200] Fixed unused static function warning for some compilers. (#2793) --- imgui.cpp | 19 +++++++------------ imgui_internal.h | 1 + 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d717fb17d1f2e..8c9dc9a2a8517 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1082,6 +1082,7 @@ static void NavUpdateWindowingOverlay(); static void NavUpdateMoveResult(); static float NavUpdatePageUpPageDown(int allowed_dir_flags); static inline void NavUpdateAnyRequestFlag(); +static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id); static ImVec2 NavCalcPreferredRefPos(); static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); @@ -3344,12 +3345,6 @@ ImDrawList* ImGui::GetBackgroundDrawList() return &GImGui->BackgroundDrawList; } -static ImDrawList* GetForegroundDrawList(ImGuiWindow*) -{ - // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. - return &GImGui->ForegroundDrawList; -} - ImDrawList* ImGui::GetForegroundDrawList() { return &GImGui->ForegroundDrawList; @@ -7882,7 +7877,7 @@ static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect } // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 -static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) +static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -7945,22 +7940,22 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) #if IMGUI_DEBUG_NAV_SCORING char buf[128]; - if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) + if (IsMouseHoveringRect(cand.Min, cand.Max)) { ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); - ImDrawList* draw_list = ImGui::GetForegroundDrawList(window); + ImDrawList* draw_list = GetForegroundDrawList(window); draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100)); draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); - draw_list->AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); + draw_list->AddRectFilled(cand.Max - ImVec2(4,4), cand.Max + CalcTextSize(buf) + ImVec2(4,4), IM_COL32(40,0,0,150)); draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf); } else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate. { - if (ImGui::IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; } + if (IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; } if (quadrant == g.NavMoveDir) { ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center); - ImDrawList* draw_list = ImGui::GetForegroundDrawList(window); + ImDrawList* draw_list = GetForegroundDrawList(window); draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200)); draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf); } diff --git a/imgui_internal.h b/imgui_internal.h index 3d82869cb721c..47da60abc4612 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1495,6 +1495,7 @@ namespace ImGui IMGUI_API void SetCurrentFont(ImFont* font); inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } + inline ImDrawList* GetForegroundDrawList(ImGuiWindow*) { ImGuiContext& g = *GImGui; return &g.ForegroundDrawList; } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. // Init IMGUI_API void Initialize(ImGuiContext* context); From 9d02ed51e3d10e6aff09d10871e7b55b3475dd95 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 18 Sep 2019 17:13:41 +0200 Subject: [PATCH 113/200] TreeNode: Added ImGuiTreeNodeFlags_SpanAvailWidth and ImGuiTreeNodeFlags_SpanFullWidth flags (#2451, #2438, #1897) Added demo bits. --- docs/CHANGELOG.txt | 7 +++++++ imgui.h | 5 +++-- imgui_demo.cpp | 14 +++++++++----- imgui_widgets.cpp | 36 +++++++++++++++++++++--------------- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dcb8fab1aeec5..80df2c16fd990 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,13 @@ Other Changes: - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] +- TreeNode: Added ImGuiTreeNodeFlags_SpanAvailWidth flag. (#2451, #2438, #1897) [@Melix19, @PathogenDavid] + This extends the hit-box to the right-most edge, even if the node is not framed. + (Note: this is not the default in order to allow adding other items on the same line. In the future we will + aim toward refactoring the hit-system to be front-to-back, allowing more natural overlapping of items, + and then we will be able to make this the default.) +- TreeNode: Added ImGuiTreeNodeFlags_SpanFullWidth flag. This extends the hit-box to both the left-most and + right-most edge of the working area, bypassing indentation. - Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) - Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. diff --git a/imgui.h b/imgui.h index a3faa620f71ac..048ac71adf7ca 100644 --- a/imgui.h +++ b/imgui.h @@ -791,9 +791,10 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). - //ImGuiTreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line. In the future we may refactor the hit system to be front-to-back, allowing natural overlaps and then this can become the default. + ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area). ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog // Obsolete names (will be removed) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 13877cd55885c..1f5c66d649764 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -608,7 +608,12 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Advanced, with Selectable nodes")) { HelpMarker("This is a more typical looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); + static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; static bool align_label_with_current_x_position = false; + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnArrow); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanFullWidth); ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position); ImGui::Text("Hello!"); if (align_label_with_current_x_position) @@ -616,12 +621,12 @@ static void ShowDemoWindowWidgets() static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. - ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. for (int i = 0; i < 6; i++) { // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. - ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; - if (selection_mask & (1 << i)) + ImGuiTreeNodeFlags node_flags = base_flags; + const bool is_selected = (selection_mask & (1 << i)); + if (is_selected) node_flags |= ImGuiTreeNodeFlags_Selected; if (i < 3) { @@ -631,7 +636,7 @@ static void ShowDemoWindowWidgets() node_clicked = i; if (node_open) { - ImGui::Text("Blah blah\nBlah Blah"); + ImGui::BulletText("Blah blah\nBlah Blah"); ImGui::TreePop(); } } @@ -654,7 +659,6 @@ static void ShowDemoWindowWidgets() else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection selection_mask = (1 << node_clicked); // Click to single-select } - ImGui::PopStyleVar(); if (align_label_with_current_x_position) ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); ImGui::TreePop(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3cd0638ba70ca..3adfc892fd35e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5177,29 +5177,36 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const ImVec2 label_size = CalcTextSize(label, label_end, false); // We vertically grow up to current line height up the typical widget height. - const float text_base_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); - ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->WorkRect.Max.x, window->DC.CursorPos.y + frame_height)); + ImRect frame_bb; + frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; + frame_bb.Min.y = window->DC.CursorPos.y; + frame_bb.Max.x = window->WorkRect.Max.x; + frame_bb.Max.y = window->DC.CursorPos.y + frame_height; if (display_frame) { - // Framed header expand a little outside the default padding + // Framed header expand a little outside the default padding, to the edge of InnerClipRect + // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f); frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f); } - const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing - const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser - ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); + const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing + const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it + const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser + const ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); + ItemSize(ImVec2(text_width, frame_height), text_offset_y); // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing - // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) - const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y); - bool is_open = TreeNodeBehaviorIsOpen(id, flags); - bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; - + ImRect interact_bb = frame_bb; + if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0) + interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f; + // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. + const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; + bool is_open = TreeNodeBehaviorIsOpen(id, flags); if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) window->DC.TreeStoreMayJumpToParentOnPop |= (1 << window->DC.TreeDepth); @@ -5273,7 +5280,6 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Render const ImU32 text_col = GetColorU32(ImGuiCol_Text); - const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y); ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin; if (display_frame) { @@ -5281,7 +5287,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); RenderNavHighlight(frame_bb, id, nav_highlight_flags); - RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) frame_bb.Max.x -= g.FontSize + style.FramePadding.x; if (g.LogEnabled) @@ -5309,9 +5315,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l } if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y), text_col); + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize*0.50f), text_col); else if (!is_leaf) - RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize*0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogRenderedText(&text_pos, ">"); RenderText(text_pos, label, label_end, false); From 656c515bad460e3e1fd7c190697c6796a7567f29 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 18 Sep 2019 17:21:04 +0200 Subject: [PATCH 114/200] Warning fix. --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1f5c66d649764..0c911dfbdb017 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -625,7 +625,7 @@ static void ShowDemoWindowWidgets() { // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. ImGuiTreeNodeFlags node_flags = base_flags; - const bool is_selected = (selection_mask & (1 << i)); + const bool is_selected = (selection_mask & (1 << i)) != 0; if (is_selected) node_flags |= ImGuiTreeNodeFlags_Selected; if (i < 3) From accb0261b8fd4c1bd32f58b3ecc7a0b732d6006e Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Sat, 31 Aug 2019 18:44:20 +0300 Subject: [PATCH 115/200] ColorPicker / ColorEdit: restore Hue when zeroing Saturation. (#2722, #2770) Issue is fixed by storing last active color picker color and last hue value when active color picker takes rgb as input. Then if current color picker color matches last active color - hue value will be restored. IDs are not used because ColorEdit4() and ColorWidget4() may call each other in hard-to-predict ways and they both push their own IDs on to the stack. We need hue restoration to happen in entire stack of these widgets if topmost widget used hue restoration. Since these widgets operate on exact same color value - color was chosen as a factor deciding which widgets should restore hue. --- imgui_internal.h | 2 ++ imgui_widgets.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/imgui_internal.h b/imgui_internal.h index 47da60abc4612..8fc03a03cdcf5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1012,6 +1012,8 @@ struct ImGuiContext ImFont InputTextPasswordFont; ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets + float ColorEditLastHue; + float ColorEditLastActiveColor[3]; ImVec4 ColorPickerRef; bool DragCurrentAccumDirty; float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3adfc892fd35e..7466acff622db 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4200,7 +4200,12 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB)) ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV)) + { ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); + // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. + if (f[1] == 0 && memcmp(g.ColorEditLastActiveColor, col, sizeof(float) * 3) == 0) + f[0] = g.ColorEditLastHue; + } int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; bool value_changed = false; @@ -4327,7 +4332,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag for (int n = 0; n < 4; n++) f[n] = i[n] / 255.0f; if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB)) + { + g.ColorEditLastHue = f[0]; ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); + memcpy(g.ColorEditLastActiveColor, f, sizeof(float) * 3); + } if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); @@ -4504,7 +4513,12 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl float H = col[0], S = col[1], V = col[2]; float R = col[0], G = col[1], B = col[2]; if (flags & ImGuiColorEditFlags_InputRGB) + { ColorConvertRGBtoHSV(R, G, B, H, S, V); + // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. + if (S == 0 && memcmp(g.ColorEditLastActiveColor, col, sizeof(float) * 3) == 0) + H = g.ColorEditLastHue; + } else if (flags & ImGuiColorEditFlags_InputHSV) ColorConvertHSVtoRGB(H, S, V, R, G, B); @@ -4628,6 +4642,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl if (flags & ImGuiColorEditFlags_InputRGB) { ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); + g.ColorEditLastHue = H; + memcpy(g.ColorEditLastActiveColor, col, sizeof(float) * 3); } else if (flags & ImGuiColorEditFlags_InputHSV) { @@ -4680,7 +4696,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl R = col[0]; G = col[1]; B = col[2]; + float preserve_hue = H; ColorConvertRGBtoHSV(R, G, B, H, S, V); + H = preserve_hue; // Avoids picker losing hue value for 1 frame glitch. } else if (flags & ImGuiColorEditFlags_InputHSV) { From 38d22bc47de97384c2f61619c4da7e53ca71f29b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 20 Sep 2019 15:31:39 +0200 Subject: [PATCH 116/200] ColorPicker / ColorEdit: restore Hue when zeroing Saturation. (#2722, #2770) - changelog, fixed uninitialized variables, tweaks, renaming. --- docs/CHANGELOG.txt | 4 +++- imgui_internal.h | 4 +++- imgui_widgets.cpp | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 80df2c16fd990..b5d0c2546fa37 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,10 +35,12 @@ HOW TO UPDATE? Other Changes: - Nav, Scrolling: Added support for Home/End key. (#787) +- ColorEdit: Disable Hue edit when Saturation==0 instead of letting Hue values jump around. +- ColorEdit, ColorPicker: In HSV display of a RGB stored value, attempt to locally preserve Hue + when Saturation==0, which reduces accidentally lossy interactions. (#2722, 2770) [@rokups] - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). -- ColorEdit: Disable Hue edit when Saturation==0 instead of letting Hue values jump around. - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. - TabBar: feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) diff --git a/imgui_internal.h b/imgui_internal.h index 8fc03a03cdcf5..6dd68b56f643e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1013,7 +1013,7 @@ struct ImGuiContext ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets float ColorEditLastHue; - float ColorEditLastActiveColor[3]; + float ColorEditLastColor[3]; ImVec4 ColorPickerRef; bool DragCurrentAccumDirty; float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings @@ -1158,6 +1158,8 @@ struct ImGuiContext LastValidMousePos = ImVec2(0.0f, 0.0f); TempInputTextId = 0; ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; + ColorEditLastHue = 0.0f; + ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; DragCurrentAccumDirty = false; DragCurrentAccum = 0.0f; DragSpeedDefaultRatio = 1.0f / 100.0f; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7466acff622db..042af86662c1d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4201,9 +4201,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV)) { - ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. - if (f[1] == 0 && memcmp(g.ColorEditLastActiveColor, col, sizeof(float) * 3) == 0) + ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); + if (f[1] == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) f[0] = g.ColorEditLastHue; } int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; @@ -4335,7 +4335,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag { g.ColorEditLastHue = f[0]; ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); - memcpy(g.ColorEditLastActiveColor, f, sizeof(float) * 3); + memcpy(g.ColorEditLastColor, f, sizeof(float) * 3); } if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); @@ -4514,13 +4514,15 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl float R = col[0], G = col[1], B = col[2]; if (flags & ImGuiColorEditFlags_InputRGB) { - ColorConvertRGBtoHSV(R, G, B, H, S, V); // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. - if (S == 0 && memcmp(g.ColorEditLastActiveColor, col, sizeof(float) * 3) == 0) + ColorConvertRGBtoHSV(R, G, B, H, S, V); + if (S == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) H = g.ColorEditLastHue; } else if (flags & ImGuiColorEditFlags_InputHSV) + { ColorConvertHSVtoRGB(H, S, V, R, G, B); + } bool value_changed = false, value_changed_h = false, value_changed_sv = false; @@ -4643,7 +4645,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl { ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); g.ColorEditLastHue = H; - memcpy(g.ColorEditLastActiveColor, col, sizeof(float) * 3); + memcpy(g.ColorEditLastColor, col, sizeof(float) * 3); } else if (flags & ImGuiColorEditFlags_InputHSV) { @@ -4696,9 +4698,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl R = col[0]; G = col[1]; B = col[2]; - float preserve_hue = H; ColorConvertRGBtoHSV(R, G, B, H, S, V); - H = preserve_hue; // Avoids picker losing hue value for 1 frame glitch. + if (S == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately. + H = g.ColorEditLastHue; } else if (flags & ImGuiColorEditFlags_InputHSV) { From f7468d05fe46d72df175afa00478b0148347c7ff Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 20 Sep 2019 15:46:18 +0200 Subject: [PATCH 117/200] Fixed mouse event forwarding in macos example (#2710, #1961) --- docs/CHANGELOG.txt | 2 ++ examples/example_apple_opengl2/main.mm | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b5d0c2546fa37..389f0a64580b7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -77,6 +77,8 @@ Other Changes: - Backends: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. (#2705, #2706) [@vilya] +- Examples: OSX: Fix example_apple_opengl2/main.mm not forwarding mouse clicks and drags correctly. (#1961, #2710) + [@intonarumori, @ElectricMagic] - Misc: Updated stb_rect_pack from 0.99 to 1.00 (fixes by @rygorous: off-by-1 bug in best-fit heuristic, fix handling of rectangles too large to fit inside texture). (#2762) [@tido64] diff --git a/examples/example_apple_opengl2/main.mm b/examples/example_apple_opengl2/main.mm index d11b908d2a61a..72f934a3bfade 100644 --- a/examples/example_apple_opengl2/main.mm +++ b/examples/example_apple_opengl2/main.mm @@ -133,12 +133,6 @@ -(BOOL)resignFirstResponder return (YES); } -// Flip coordinate system upside down on Y --(BOOL)isFlipped -{ - return (YES); -} - -(void)dealloc { animationTimer = nil; @@ -150,6 +144,8 @@ -(void)keyDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self) -(void)flagsChanged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } -(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } -(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } +-(void)mouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } +-(void)mouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } -(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } @end @@ -179,6 +175,7 @@ -(NSWindow*)window _window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES]; [_window setTitle:@"Dear ImGui OSX+OpenGL2 Example"]; + [_window setAcceptsMouseMovedEvents:YES]; [_window setOpaque:YES]; [_window makeKeyAndOrderFront:NSApp]; From a45e3b5bb3e4c228584bb66776d69003303ad9fa Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 20 Sep 2019 19:04:19 +0200 Subject: [PATCH 118/200] Readme, Wiki: Image loading examples. --- docs/README.md | 4 ++-- docs/TODO.txt | 4 ++++ imgui.cpp | 24 ++++-------------------- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/docs/README.md b/docs/README.md index a07acc79f87b5..6ca295ea77830 100644 --- a/docs/README.md +++ b/docs/README.md @@ -244,13 +244,13 @@ See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software usi The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui". **How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?** -
**How can I display an image? What is ImTextureID, how does it works?** +
**How can I display an image? What is ImTextureID, how does it works?** ([examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples))
**Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...**
**How can I use my own math types instead of ImVec2/ImVec4?**
**How can I load a different font than the default?**
**How can I easily use icons in my application?**
**How can I load multiple fonts?** -
**How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?** ([example](https://github.com/ocornut/imgui/wiki/Loading-Font-Example)) +
**How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?** ([examples](https://github.com/ocornut/imgui/wiki/Loading-Font-Example))
**How can I interact with standard C++ types (such as std::string and std::vector)?**
**How can I use the drawing facilities without a Dear ImGui window? (using ImDrawList API)**
**How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)** diff --git a/docs/TODO.txt b/docs/TODO.txt index df413b7e32d46..9c37f6902428c 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -93,6 +93,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there. - input text: a way for the user to provide syntax coloring. - input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count. + - input text: facilitate patterns like if (InputText(..., obj.get_string_ref()) { obj.set_string(...); } relying on internally held buffer. - input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc). - input text multi-line: support for cut/paste without selection (cut/paste the current line) - input text multi-line: line numbers? status bar? (follow up on #200) @@ -111,6 +112,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - layout: more generic alignment state (left/right/centered) for single items? - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding. - layout: vertical alignment of mixed height items (e.g. buttons) within a same line (#1284) + - layout: null layout mode were items are not rendered but user can query GetItemRectMin()/Max/Size. + - layout: (R&D) local multi-pass layout mode. + - layout: (R&D) bind authored layout data (created by an off-line tool), items fetch their pos/size at submission, self-optimize data structures to stable linear access. - group: BeginGroup() needs a border option. (~#1496) - group: IsHovered() after EndGroup() covers whole aabb rather than the intersection of individual items. Is that desirable? diff --git a/imgui.cpp b/imgui.cpp index 8c9dc9a2a8517..af5ffc4bd81fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -622,6 +622,7 @@ CODE Q: How can I display an image? What is ImTextureID, how does it works? A: Short explanation: + - Please read Wiki entry for examples: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures. - Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value. - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason). @@ -669,26 +670,9 @@ CODE This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them. If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using. - Here's a simplified OpenGL example using stb_image.h: - - // Use stb_image.h to load a PNG from disk and turn it into raw RGBA pixel data: - #define STB_IMAGE_IMPLEMENTATION - #include - [...] - int my_image_width, my_image_height; - unsigned char* my_image_data = stbi_load("my_image.png", &my_image_width, &my_image_height, NULL, 4); - - // Turn the RGBA pixel data into an OpenGL texture: - GLuint my_opengl_texture; - glGenTextures(1, &my_opengl_texture); - glBindTexture(GL_TEXTURE_2D, my_opengl_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); - - // Now that we have an OpenGL texture, assuming our imgui rendering function (imgui_impl_xxx.cpp file) takes GLuint as ImTextureID, we can display it: - ImGui::Image((void*)(intptr_t)my_opengl_texture, ImVec2(my_image_width, my_image_height)); + Refer to the Wiki to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11: + + https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa. Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*. From eab03f446758b45f331160ec4edf3af4c17059cf Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 21 Sep 2019 17:18:24 +0200 Subject: [PATCH 119/200] Selectable: Added ImGuiSelectableFlags_AllowItemOverlap flag in public api (was previously internal only). --- docs/CHANGELOG.txt | 1 + imgui.h | 3 ++- imgui_internal.h | 5 ++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 389f0a64580b7..6ccce92897592 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,7 @@ Other Changes: and then we will be able to make this the default.) - TreeNode: Added ImGuiTreeNodeFlags_SpanFullWidth flag. This extends the hit-box to both the left-most and right-most edge of the working area, bypassing indentation. +- Selectable: Added ImGuiSelectableFlags_AllowItemOverlap flag in public api (was previously internal only). - Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) - Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. diff --git a/imgui.h b/imgui.h index 048ac71adf7ca..0657ae04e34cd 100644 --- a/imgui.h +++ b/imgui.h @@ -810,7 +810,8 @@ enum ImGuiSelectableFlags_ ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too - ImGuiSelectableFlags_Disabled = 1 << 3 // Cannot be selected, display grayed out text + ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text + ImGuiSelectableFlags_AllowItemOverlap = 1 << 4 // (WIP) Hit testing to allow subsequent widgets to overlap this one }; // Flags for ImGui::BeginCombo() diff --git a/imgui_internal.h b/imgui_internal.h index 6dd68b56f643e..a27c1849f4ab8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -361,9 +361,8 @@ enum ImGuiSelectableFlagsPrivate_ ImGuiSelectableFlags_PressedOnClick = 1 << 21, ImGuiSelectableFlags_PressedOnRelease = 1 << 22, ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 23, // FIXME: We may be able to remove this (added in 6251d379 for menus) - ImGuiSelectableFlags_AllowItemOverlap = 1 << 24, - ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 25, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. - ImGuiSelectableFlags_SetNavIdOnHover = 1 << 26 + ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. + ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25 }; // Extend ImGuiTreeNodeFlags_ From f47a0a85ccd6c5d35e29c742f80759154a83dbc0 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 21 Sep 2019 17:04:10 +0200 Subject: [PATCH 120/200] ImVector: added find, find_erase, find_erase_unsorted helpers. --- docs/CHANGELOG.txt | 11 ++++++----- imgui.h | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6ccce92897592..fa5d3d16e778b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,11 +41,11 @@ Other Changes: - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). -- TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. -- TabBar: fixed single-tab not shrinking their width down. -- TabBar: feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) +- TabBar: Fixed ScrollToBar request creating bouncing loop when tab is larger than available space. +- TabBar: Fixed single-tab not shrinking their width down. +- TabBar: Feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) (before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations). -- TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. +- TabBar: Improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - Columns, Separator: Fixed a bug where non-visible separators within columns would alter the next row position differently than visible ones. @@ -65,9 +65,10 @@ Other Changes: unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow as possible. (#2775) [@rokups] -- ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) +- ImDrawList: Clarified the name of many parameters so reading the code is a little easier. (#2740) - ImDrawListSplitter: fixed an issue merging channels if the last submitted draw command used a different texture. (#2506) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) +- ImVector: Added find(), find_erase(), find_erase_unsorted() helpers. - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) diff --git a/imgui.h b/imgui.h index 0657ae04e34cd..b5a1155ebad86 100644 --- a/imgui.h +++ b/imgui.h @@ -1273,6 +1273,10 @@ struct ImVector inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; if (it < Data+Size-1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; } inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } + inline T* find(const T& v) { T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } + inline const T* find(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } + inline bool find_erase(const T& v) { const T* it = find(v); if (it < Data + Size) { erase(it); return true; } return false; } + inline bool find_erase_unsorted(const T& v) { const T* it = find(v); if (it < Data + Size) { erase_unsorted(it); return true; } return false; } inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; return (int)off; } }; From 80b3ab7d3e09185355727aa42b69652b9afc3b97 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 22 Sep 2019 22:16:05 +0200 Subject: [PATCH 121/200] TabBar: Fixed single tab shrinking reducing the tab to 0.0f size. Broken by a856c670c17fe70d61e519bf74ccb2559915a2ff. --- imgui_widgets.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 042af86662c1d..ca84674ab08b3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1366,7 +1366,7 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc { if (count == 1) { - items[0].Width -= width_excess; + items[0].Width = ImMax(items[0].Width - width_excess, 1.0f); return; } ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer); @@ -6562,6 +6562,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; tab->Width = ImMin(tab->WidthContents, tab_max_width); + IM_ASSERT(tab->Width > 0.0f); } } From 44cd8e39da53f1a2ac7608ecf891e935eebd7ba9 Mon Sep 17 00:00:00 2001 From: osheriff Date: Sun, 22 Sep 2019 12:52:36 +0200 Subject: [PATCH 122/200] Automatically include the available gl loader header --- examples/imgui_impl_opengl3.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/imgui_impl_opengl3.h b/examples/imgui_impl_opengl3.h index 0f7eef74ddda5..fbf2417cf7d3b 100644 --- a/examples/imgui_impl_opengl3.h +++ b/examples/imgui_impl_opengl3.h @@ -32,7 +32,19 @@ && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \ && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) -#define IMGUI_IMPL_OPENGL_LOADER_GL3W + // to avoid problem with non-clang compilers not having this macro. + #if defined(__has_include) + // check if the header exists, then automatically define the macros .. + #if __has_include() + #define IMGUI_IMPL_OPENGL_LOADER_GLEW + #elif __has_include() + #define IMGUI_IMPL_OPENGL_LOADER_GLAD + #else + #define IMGUI_IMPL_OPENGL_LOADER_GL3W + #endif + #else + #define IMGUI_IMPL_OPENGL_LOADER_GL3W + #endif #endif IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); From 97691643b7fb198831af32207b88d7e4889c6887 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 22 Sep 2019 23:19:04 +0200 Subject: [PATCH 123/200] Backends: OpenGL3: Attempt to automatically detect default GL loader by using __has_include. Followup to 44cd8e3 (#2798) --- docs/CHANGELOG.txt | 1 + examples/example_glfw_opengl3/main.cpp | 7 +++-- examples/example_sdl_opengl3/main.cpp | 7 +++-- examples/imgui_impl_opengl3.cpp | 33 ++++++++++++++++++-- examples/imgui_impl_opengl3.h | 43 ++++++++++++++------------ 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fa5d3d16e778b..29b993f5c7db0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,6 +74,7 @@ Other Changes: usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) - Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before ImGui_ImplOpenGL3_NewFrame() if for some reason they wanted. +- Backends: OpenGL3: Attempt to automatically detect default GL loader by using __has_include. (#2798) [@o-micron] - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 76174a1f8449a..4833d1b05500d 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -7,9 +7,10 @@ #include "imgui_impl_opengl3.h" #include -// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually. -// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad. -// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. +// About Desktop OpenGL function loaders: +// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. +// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). +// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. #if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) #include // Initialize with gl3wInit() #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index ae1ef5b32a178..19d34e9ad5d06 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -9,9 +9,10 @@ #include #include -// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually. -// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad. -// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. +// About Desktop OpenGL function loaders: +// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. +// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). +// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. #if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) #include // Initialize with gl3wInit() #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 199638e85f567..189814f49d277 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -1,5 +1,5 @@ // dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline -// - Desktop GL: 3.x 4.x +// - Desktop GL: 2.x 3.x 4.x // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility. // 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. @@ -79,12 +80,21 @@ // Auto-detect GL version #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) -#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" +#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" +#undef IMGUI_IMPL_OPENGL_LOADER_GL3W +#undef IMGUI_IMPL_OPENGL_LOADER_GLEW +#undef IMGUI_IMPL_OPENGL_LOADER_GLAD +#undef IMGUI_IMPL_OPENGL_LOADER_CUSTOM #elif defined(__EMSCRIPTEN__) -#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" +#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" +#undef IMGUI_IMPL_OPENGL_LOADER_GL3W +#undef IMGUI_IMPL_OPENGL_LOADER_GLEW +#undef IMGUI_IMPL_OPENGL_LOADER_GLAD +#undef IMGUI_IMPL_OPENGL_LOADER_CUSTOM #endif #endif +// GL includes #if defined(IMGUI_IMPL_OPENGL_ES2) #include #elif defined(IMGUI_IMPL_OPENGL_ES3) @@ -149,6 +159,23 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) strcpy(g_GlslVersionString, glsl_version); strcat(g_GlslVersionString, "\n"); + // Dummy construct to make it easily visible in the IDE and debugger which GL loader has been selected. + // The code actually never uses the 'gl_loader' variable! It is only here so you can read it! + // If auto-detection fails or doesn't select the same GL loader file as used by your application, + // you are likely to get a crash below. + // You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. + const char* gl_loader = "Unknown"; + IM_UNUSED(gl_loader); +#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) + gl_loader = "GL3W"; +#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) + gl_loader = "GLEW"; +#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) + gl_loader = "GLAD"; +#else IMGUI_IMPL_OPENGL_LOADER_CUSTOM + gl_loader = "Custom"; +#endif + // Make a dummy GL call (we don't actually need the result) // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. diff --git a/examples/imgui_impl_opengl3.h b/examples/imgui_impl_opengl3.h index fbf2417cf7d3b..1cb790b164fe5 100644 --- a/examples/imgui_impl_opengl3.h +++ b/examples/imgui_impl_opengl3.h @@ -1,5 +1,5 @@ // dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline -// - Desktop GL: 3.x 4.x +// - Desktop GL: 2.x 3.x 4.x // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) @@ -23,37 +23,42 @@ #pragma once +// Backend API +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); + +// (Optional) Called by Init/NewFrame/Shutdown +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); + // Specific OpenGL versions //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android -// Set default OpenGL3 loader to be gl3w -#if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \ +// Desktop OpenGL: attempt to detect default GL loader based on available header files. +// If auto-detection fails or doesn't select the same GL loader file as used by your application, +// you are likely to get a crash in ImGui_ImplOpenGL3_Init(). +// You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. +#if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \ + && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ + && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \ && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) - // to avoid problem with non-clang compilers not having this macro. #if defined(__has_include) - // check if the header exists, then automatically define the macros .. #if __has_include() #define IMGUI_IMPL_OPENGL_LOADER_GLEW #elif __has_include() #define IMGUI_IMPL_OPENGL_LOADER_GLAD - #else + #elif __has_include() #define IMGUI_IMPL_OPENGL_LOADER_GL3W + #else + #error "Cannot detect OpenGL loader!" #endif #else - #define IMGUI_IMPL_OPENGL_LOADER_GL3W + #define IMGUI_IMPL_OPENGL_LOADER_GL3W // Default to GL3W #endif #endif -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); - -// Called by Init/NewFrame/Shutdown -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); From 25849234f60a4197c9cbb94b1fc249a971e74543 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Sep 2019 12:45:52 +0200 Subject: [PATCH 124/200] Internal: Tree: tweaks (initially tried to implement auto-scrolling, stashed) --- docs/CHANGELOG.txt | 19 +++++++++---------- docs/TODO.txt | 2 +- imgui.cpp | 2 +- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 9 ++++++--- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 29b993f5c7db0..68adbaf02f88e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,8 +41,8 @@ Other Changes: - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). -- TabBar: Fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: Fixed single-tab not shrinking their width down. +- TabBar: Fixed clicking on a tab larger than tab-bar width creating a bouncing feedback loop. - TabBar: Feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768) (before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations). - TabBar: Improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. @@ -50,8 +50,8 @@ Other Changes: - Columns, Separator: Fixed a bug where non-visible separators within columns would alter the next row position differently than visible ones. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] -- DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. -- DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] +- DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edits to the value. +- DragScalar: Fixed dragging of unsigned values on ARM cpu (float to uint cast is undefined). (#2780) [@dBagrat] - TreeNode: Added ImGuiTreeNodeFlags_SpanAvailWidth flag. (#2451, #2438, #1897) [@Melix19, @PathogenDavid] This extends the hit-box to the right-most edge, even if the node is not framed. (Note: this is not the default in order to allow adding other items on the same line. In the future we will @@ -66,20 +66,19 @@ Other Changes: Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow as possible. (#2775) [@rokups] - ImDrawList: Clarified the name of many parameters so reading the code is a little easier. (#2740) -- ImDrawListSplitter: fixed an issue merging channels if the last submitted draw command used a different texture. (#2506) +- ImDrawListSplitter: Fixed merging channels if the last submitted draw command used a different texture. (#2506) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - ImVector: Added find(), find_erase(), find_erase_unsorted() helpers. - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) - Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() - before ImGui_ImplOpenGL3_NewFrame() if for some reason they wanted. + before ImGui_ImplOpenGL3_NewFrame(), which sometimes can be convenient. - Backends: OpenGL3: Attempt to automatically detect default GL loader by using __has_include. (#2798) [@o-micron] -- Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, - would generally make the debug layer complain (Added in 1.72). -- Backends: Vulkan: Added support for specifying multisample count. - Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values - to use, default is non-multisampled as before. (#2705, #2706) [@vilya] +- Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, which would + generally make the DX11 debug layer complain (bug added in 1.72). +- Backends: Vulkan: Added support for specifying multisample count. Set 'ImGui_ImplVulkan_InitInfo::MSAASamples' to + one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. (#2705, #2706) [@vilya] - Examples: OSX: Fix example_apple_opengl2/main.mm not forwarding mouse clicks and drags correctly. (#1961, #2710) [@intonarumori, @ElectricMagic] - Misc: Updated stb_rect_pack from 0.99 to 1.00 (fixes by @rygorous: off-by-1 bug in best-fit heuristic, diff --git a/docs/TODO.txt b/docs/TODO.txt index 9c37f6902428c..07f6676bb971c 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -63,7 +63,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395) - widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h. - widgets: add visuals for Disabled/ReadOnly mode and expose publicly (#211) - - widgets: add always-allow-overlap mode. This should perhaps be the default. + - widgets: add always-allow-overlap mode. This should perhaps be the default? one problem is that highlight after mouse-wheel scrolling gets deferred, makes scrolling more flickery. - widgets: start exposing PushItemFlag() and ImGuiItemFlags - widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260 - widgets: activate by identifier (trigger button, focus given id) diff --git a/imgui.cpp b/imgui.cpp index af5ffc4bd81fe..e25ca0764353a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5901,7 +5901,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.TextWrapPosStack.resize(0); window->DC.CurrentColumns = NULL; window->DC.TreeDepth = 0; - window->DC.TreeStoreMayJumpToParentOnPop = 0x00; + window->DC.TreeMayJumpToParentOnPopMask = 0x00; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); diff --git a/imgui_internal.h b/imgui_internal.h index a27c1849f4ab8..0a585f3491155 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1208,7 +1208,7 @@ struct IMGUI_API ImGuiWindowTempData float CurrLineTextBaseOffset; float PrevLineTextBaseOffset; int TreeDepth; - ImU32 TreeStoreMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. + ImU32 TreeMayJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. ImGuiID LastItemId; ImGuiItemStatusFlags LastItemStatusFlags; ImRect LastItemRect; // Interaction rect @@ -1249,7 +1249,7 @@ struct IMGUI_API ImGuiWindowTempData CurrLineSize = PrevLineSize = ImVec2(0.0f, 0.0f); CurrLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; TreeDepth = 0; - TreeStoreMayJumpToParentOnPop = 0x00; + TreeMayJumpToParentOnPopMask = 0x00; LastItemId = 0; LastItemStatusFlags = 0; LastItemRect = LastItemDisplayRect = ImRect(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ca84674ab08b3..ded5d8810d8bd 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5228,7 +5228,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; bool is_open = TreeNodeBehaviorIsOpen(id, flags); if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - window->DC.TreeStoreMayJumpToParentOnPop |= (1 << window->DC.TreeDepth); + window->DC.TreeMayJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); bool item_add = ItemAdd(interact_bb, id); window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; @@ -5380,13 +5380,16 @@ void ImGui::TreePop() Unindent(); window->DC.TreeDepth--; + ImU32 tree_depth_mask = (1 << window->DC.TreeDepth); + + // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled) if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) - if (g.NavIdIsAlive && (window->DC.TreeStoreMayJumpToParentOnPop & (1 << window->DC.TreeDepth))) + if (g.NavIdIsAlive && (window->DC.TreeMayJumpToParentOnPopMask & tree_depth_mask)) { SetNavID(window->IDStack.back(), g.NavLayer); NavMoveRequestCancel(); } - window->DC.TreeStoreMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1; + window->DC.TreeMayJumpToParentOnPopMask &= tree_depth_mask - 1; IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. PopID(); From 52deb415e0ed9bc042f8eacfea5114ad3d562455 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Sep 2019 14:53:49 +0200 Subject: [PATCH 125/200] Internal: Refactored internal RenderMouseCursor so colors can be specified. (#2614) --- imgui.cpp | 2 +- imgui_draw.cpp | 6 +----- imgui_internal.h | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e25ca0764353a..1557d59590bb3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4274,7 +4274,7 @@ void ImGui::Render() // Draw software mouse cursor if requested if (g.IO.MouseDrawCursor) - RenderMouseCursor(&g.ForegroundDrawList, g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor); + RenderMouseCursor(&g.ForegroundDrawList, g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48)); if (!g.ForegroundDrawList.VtxBuffer.empty()) AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.ForegroundDrawList); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index eb173b4422d2d..2cbf209b70847 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3038,16 +3038,12 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // - RenderRectFilledRangeH() //----------------------------------------------------------------------------- -void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor) +void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) { if (mouse_cursor == ImGuiMouseCursor_None) return; IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); - const ImU32 col_shadow = IM_COL32(0, 0, 0, 48); - const ImU32 col_border = IM_COL32(0, 0, 0, 255); // Black - const ImU32 col_fill = IM_COL32(255, 255, 255, 255); // White - ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas; ImVec2 offset, size, uv[4]; if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) diff --git a/imgui_internal.h b/imgui_internal.h index 0a585f3491155..acd2d2567464f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1636,7 +1636,7 @@ namespace ImGui // Render helpers (those functions don't access any ImGui state!) IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); - IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow); + IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); From ca858c084b5dfbb2b899a781db142408182f2efe Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Sep 2019 15:31:05 +0200 Subject: [PATCH 126/200] Demo tweaks. Comments. Compacting the rarely used AutoFitXXX fields in ImGuiWindowTempData. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 +-- imgui_demo.cpp | 66 ++++++++++++++++++++++++++++++++-------------- imgui_internal.h | 34 ++++++++++++------------ 4 files changed, 66 insertions(+), 39 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 68adbaf02f88e..554ea04598c92 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -169,6 +169,7 @@ Other Changes: - Demo: Log, Console: Using a simpler stateless pattern for auto-scrolling. - Demo: Widgets: Showing how to use the format parameter of Slider/Drag functions to display the name of an enum value instead of the underlying integer value. +- Demo: Renamed the "Help" menu to "Tools" (more accurate). - Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer. - Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them. - Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), diff --git a/imgui.cpp b/imgui.cpp index 1557d59590bb3..f276b5f4e9ee7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2704,8 +2704,8 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) BeginOrderWithinContext = -1; PopupId = 0; AutoFitFramesX = AutoFitFramesY = -1; - AutoFitOnlyGrows = false; AutoFitChildAxises = 0x00; + AutoFitOnlyGrows = false; AutoPosLastDirection = ImGuiDir_None; HiddenFramesCanSkipItems = HiddenFramesCannotSkipItems = 0; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; @@ -4729,7 +4729,7 @@ static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size ImGuiWindow* child_window = g.CurrentWindow; child_window->ChildId = id; - child_window->AutoFitChildAxises = auto_fit_axises; + child_window->AutoFitChildAxises = (ImS8)auto_fit_axises; // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually. // While this is not really documented/defined, it seems that the expected thing to do. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0c911dfbdb017..09f3dae06333f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -106,8 +106,6 @@ Index of this file: #define IM_NEWLINE "\n" #endif -#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) - //----------------------------------------------------------------------------- // [SECTION] Forward Declarations, Helpers //----------------------------------------------------------------------------- @@ -153,8 +151,11 @@ void ImGui::ShowUserGuide() { ImGuiIO& io = ImGui::GetIO(); ImGui::BulletText("Double-click on title bar to collapse window."); - ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents)."); - ImGui::BulletText("Click and drag on any empty space to move window."); + ImGui::BulletText("Click and drag on lower corner to resize window\n(double-click to auto fit window to its contents)."); + if (io.ConfigWindowsMoveFromTitleBarOnly) + ImGui::BulletText("Click and drag on title bar to move window."); + else + ImGui::BulletText("Click and drag on any empty space to move window."); ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text."); if (io.FontAllowUserScaling) @@ -175,6 +176,12 @@ void ImGui::ShowUserGuide() //----------------------------------------------------------------------------- // [SECTION] Demo Window / ShowDemoWindow() //----------------------------------------------------------------------------- +// - ShowDemoWindowWidgets() +// - ShowDemoWindowLayout() +// - ShowDemoWindowPopups() +// - ShowDemoWindowColumns() +// - ShowDemoWindowMisc() +//----------------------------------------------------------------------------- // We split the contents of the big ShowDemoWindow() function into smaller functions (because the link time of very large functions grow non-linearly) static void ShowDemoWindowWidgets(); @@ -216,7 +223,7 @@ void ImGui::ShowDemoWindow(bool* p_open) if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); - // Dear ImGui Apps (accessible from the "Help" menu) + // Dear ImGui Apps (accessible from the "Tools" menu) static bool show_app_metrics = false; static bool show_app_style_editor = false; static bool show_app_about = false; @@ -289,7 +296,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::MenuItem("Documents", NULL, &show_app_documents); ImGui::EndMenu(); } - if (ImGui::BeginMenu("Help")) + if (ImGui::BeginMenu("Tools")) { ImGui::MenuItem("Metrics", NULL, &show_app_metrics); ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); @@ -307,7 +314,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("PROGRAMMER GUIDE:"); ImGui::BulletText("Please see the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!"); ImGui::BulletText("Please see the comments in imgui.cpp."); - ImGui::BulletText("Please see the examples/ in application."); + ImGui::BulletText("Please see the examples/ application."); ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls."); ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls."); ImGui::Separator(); @@ -1495,6 +1502,8 @@ static void ShowDemoWindowWidgets() // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo. ImGui::BulletText("Drag and drop in standard widgets"); + ImGui::SameLine(); + HelpMarker("You can drag from the colored squares."); ImGui::Indent(); static float col1[3] = { 1.0f,0.0f,0.2f }; static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; @@ -1527,8 +1536,8 @@ static void ShowDemoWindowWidgets() // Our buttons are both drag sources and drag targets here! if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); // Set payload to carry the index of our item (could be anything) - if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } // Display preview (could be anything, e.g. when dragging an image we could decide to display the filename and a small preview of the image, etc.) + ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); // Set payload to carry the index of our item (could be anything) + if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } // Display preview (could be anything, e.g. when dragging an image we could decide to display the filename and a small preview of the image, etc.) if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); } if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); } ImGui::EndDragDropSource(); @@ -1567,19 +1576,18 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)")) { - // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined. - // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code). + // Submit an item (various types available) so we can query their status in the following block. static int item_type = 1; - static bool b = false; - static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; - static char str[16] = {}; ImGui::Combo("Item Type", &item_type, "Text\0Button\0Button (w/ repeat)\0Checkbox\0SliderFloat\0InputText\0InputFloat\0InputFloat3\0ColorEdit4\0MenuItem\0TreeNode (w/ double-click)\0ListBox\0"); ImGui::SameLine(); HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions."); bool ret = false; + static bool b = false; + static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; + static char str[16] = {}; if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button - if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater) + if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater) if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) @@ -1589,6 +1597,11 @@ static void ShowDemoWindowWidgets() if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) if (item_type == 10){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. if (item_type == 11){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + + // Display the value of IsItemHovered() and other common item state functions. + // Note that the ImGuiHoveredFlags_XXX flags can be combined. + // Because BulletText is an item itself and that would affect the output of IsItemXXX functions, + // we query every state in a single call to avoid storing them and to simplify the code ImGui::BulletText( "Return value = %d\n" "IsItemFocused() = %d\n" @@ -1631,7 +1644,8 @@ static void ShowDemoWindowWidgets() if (embed_all_inside_a_child_window) ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true); - // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined. + // Testing IsWindowFocused() function with its various flags. + // Note that the ImGuiFocusedFlags_XXX flags can be combined. ImGui::BulletText( "IsWindowFocused() = %d\n" "IsWindowFocused(_ChildWindows) = %d\n" @@ -1644,7 +1658,8 @@ static void ShowDemoWindowWidgets() ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); - // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined. + // Testing IsWindowHovered() function with its various flags. + // Note that the ImGuiHoveredFlags_XXX flags can be combined. ImGui::BulletText( "IsWindowHovered() = %d\n" "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" @@ -2798,6 +2813,8 @@ static void ShowDemoWindowMisc() { if (ImGui::CollapsingHeader("Filtering")) { + // Helper class to easy setup a text filter. + // You may want to implement a more feature-full filtering scheme in your own application. static ImGuiTextFilter filter; ImGui::Text("Filter usage:\n" " \"\" display all lines\n" @@ -2815,12 +2832,14 @@ static void ShowDemoWindowMisc() { ImGuiIO& io = ImGui::GetIO(); + // Display ImGuiIO output flags ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("WantTextInput: %d", io.WantTextInput); ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); + // Display Keyboard/Mouse state if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) { if (ImGui::IsMousePosValid()) @@ -2953,7 +2972,7 @@ static void ShowDemoWindowMisc() //----------------------------------------------------------------------------- // [SECTION] About Window / ShowAboutWindow() -// Access from Dear ImGui Demo -> Help -> About +// Access from Dear ImGui Demo -> Tools -> About //----------------------------------------------------------------------------- void ImGui::ShowAboutWindow(bool* p_open) @@ -2965,7 +2984,7 @@ void ImGui::ShowAboutWindow(bool* p_open) } ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Separator(); - ImGui::Text("By Omar Cornut and all dear imgui contributors."); + ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); static bool show_config_info = false; @@ -3085,6 +3104,10 @@ void ImGui::ShowAboutWindow(bool* p_open) //----------------------------------------------------------------------------- // [SECTION] Style Editor / ShowStyleEditor() //----------------------------------------------------------------------------- +// - ShowStyleSelector() +// - ShowFontSelector() +// - ShowStyleEditor() +//----------------------------------------------------------------------------- // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options. // Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally. @@ -3379,6 +3402,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) //----------------------------------------------------------------------------- // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar() //----------------------------------------------------------------------------- +// - ShowExampleAppMainMenuBar() +// - ShowExampleMenuFile() +//----------------------------------------------------------------------------- // Demonstrate creating a "main" fullscreen menu bar and populating it. // Note the difference between BeginMainMenuBar() and BeginMenuBar(): @@ -4174,7 +4200,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open) { struct CustomConstraints // Helper functions to demonstrate programmatic constraints { - static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } + static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = (data->DesiredSize.x > data->DesiredSize.y ? data->DesiredSize.x : data->DesiredSize.y); } static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } }; diff --git a/imgui_internal.h b/imgui_internal.h index acd2d2567464f..edc0fb06f7df1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1199,20 +1199,20 @@ struct ImGuiContext // FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered. struct IMGUI_API ImGuiWindowTempData { - ImVec2 CursorPos; + ImVec2 CursorPos; // Current emitting position, in absolute coordinates. ImVec2 CursorPosPrevLine; - ImVec2 CursorStartPos; // Initial position in client area with padding + ImVec2 CursorStartPos; // Initial position after Begin(), generally ~ window position + WindowPadding. ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Used to calculate window->ContentSize at the beginning of next frame ImVec2 CurrLineSize; ImVec2 PrevLineSize; - float CurrLineTextBaseOffset; + float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added). float PrevLineTextBaseOffset; - int TreeDepth; - ImU32 TreeMayJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. - ImGuiID LastItemId; - ImGuiItemStatusFlags LastItemStatusFlags; - ImRect LastItemRect; // Interaction rect - ImRect LastItemDisplayRect; // End-user display rect (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) + int TreeDepth; // Current tree depth. + ImU32 TreeMayJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. + ImGuiID LastItemId; // ID for last item + ImGuiItemStatusFlags LastItemStatusFlags; // Status flags for last item (see ImGuiItemStatusFlags_) + ImRect LastItemRect; // Interaction rect for last item + ImRect LastItemDisplayRect; // End-user display rect for last item (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) int NavLayerCurrentMask; // = (1 << NavLayerCurrent) used by ItemAdd prior to clipping. int NavLayerActiveMask; // Which layer have been written to (result from previous frame) @@ -1222,7 +1222,7 @@ struct IMGUI_API ImGuiWindowTempData bool MenuBarAppending; // FIXME: Remove this ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImVector ChildWindows; - ImGuiStorage* StateStorage; + ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) ImGuiLayoutType LayoutType; ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() int FocusCounterAll; // Counter for focus/tabbing system. Start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign) @@ -1287,9 +1287,9 @@ struct IMGUI_API ImGuiWindow ImVec2 SizeFull; // Size when non collapsed ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding. ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize(). - ImVec2 WindowPadding; // Window padding at the time of begin. - float WindowRounding; // Window rounding at the time of begin. - float WindowBorderSize; // Window border size at the time of begin. + ImVec2 WindowPadding; // Window padding at the time of Begin(). + float WindowRounding; // Window rounding at the time of Begin(). + float WindowBorderSize; // Window border size at the time of Begin(). int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)! ImGuiID MoveId; // == window->GetID("#MOVE") ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window) @@ -1298,7 +1298,7 @@ struct IMGUI_API ImGuiWindow ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered ImVec2 ScrollbarSizes; // Size taken by scrollbars on each axis - bool ScrollbarX, ScrollbarY; + bool ScrollbarX, ScrollbarY; // Are scrollbars visible? bool Active; // Set to true on Begin(), unless Collapsed bool WasActive; bool WriteAccessed; // Set to true when any widget access the current window @@ -1313,9 +1313,9 @@ struct IMGUI_API ImGuiWindow short BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. short BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - int AutoFitFramesX, AutoFitFramesY; + ImS8 AutoFitFramesX, AutoFitFramesY; + ImS8 AutoFitChildAxises; bool AutoFitOnlyGrows; - int AutoFitChildAxises; ImGuiDir AutoPosLastDirection; int HiddenFramesCanSkipItems; // Hide the window for N frames int HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size @@ -1338,7 +1338,7 @@ struct IMGUI_API ImGuiWindow ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. int LastFrameActive; // Last frame number the window was Active. - float LastTimeActive; + float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there) float ItemWidthDefault; ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; From e100523917e00c7a7ee1c71309e0cd80a8ba3b27 Mon Sep 17 00:00:00 2001 From: goran-w <44604769+goran-w@users.noreply.github.com> Date: Tue, 30 Oct 2018 15:52:27 +0100 Subject: [PATCH 127/200] CollapsingHeader: Added support for ImGuiTreeNodeFlags_Bullet and ImGuiTreeNodeFlags_Leaf on framed nodes. (#2159, #2160) The Bullet and Leaf ImGuiTreeNodeFlags are now taken into account for Framed/CollapsingHeader tree nodes as well. TreeNodeEx() can be used to specify these flags. A choice was made to left-adjust the Framed text when no Bullet/Arrow is rendered, since this was deemed to look better in the Framed context (especially when considering that CollapsingHeader is drawn using NoTreePushOnOpen, so child/sibling Text items etc will often be non-indented). --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 11 ++++++++++- imgui_widgets.cpp | 14 +++++++++----- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 554ea04598c92..63e96fe000fae 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,8 @@ Other Changes: and then we will be able to make this the default.) - TreeNode: Added ImGuiTreeNodeFlags_SpanFullWidth flag. This extends the hit-box to both the left-most and right-most edge of the working area, bypassing indentation. +- CollapsingHeader: Added support for ImGuiTreeNodeFlags_Bullet and ImGuiTreeNodeFlags_Leaf on framed nodes, + mostly for consistency. (#2159, #2160) [@goran-w] - Selectable: Added ImGuiSelectableFlags_AllowItemOverlap flag in public api (was previously internal only). - Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) - Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 09f3dae06333f..492158d119041 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -677,7 +677,7 @@ static void ShowDemoWindowWidgets() { static bool closable_group = true; ImGui::Checkbox("Show 2nd header", &closable_group); - if (ImGui::CollapsingHeader("Header")) + if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None)) { ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); for (int i = 0; i < 5; i++) @@ -689,6 +689,10 @@ static void ShowDemoWindowWidgets() for (int i = 0; i < 5; i++) ImGui::Text("More content %d", i); } + /* + if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet)) + ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); + */ ImGui::TreePop(); } @@ -696,6 +700,11 @@ static void ShowDemoWindowWidgets() { ImGui::BulletText("Bullet point 1"); ImGui::BulletText("Bullet point 2\nOn multiple lines"); + if (ImGui::TreeNode("Tree node")) + { + ImGui::BulletText("Another bullet point"); + ImGui::TreePop(); + } ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); ImGui::Bullet(); ImGui::SmallButton("Button"); ImGui::TreePop(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ded5d8810d8bd..d9dc4ec6e7b4e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5214,7 +5214,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser - const ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); + ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); ItemSize(ImVec2(text_width, frame_height), text_offset_y); // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing @@ -5307,7 +5307,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); RenderNavHighlight(frame_bb, id, nav_highlight_flags); - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); + if (flags & ImGuiTreeNodeFlags_Bullet) + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); + else if (!is_leaf) + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); + else // Leaf without bullet, left-adjusted text + text_pos.x -= text_offset_x; if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) frame_bb.Max.x -= g.FontSize + style.FramePadding.x; if (g.LogEnabled) @@ -5333,11 +5338,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); RenderNavHighlight(frame_bb, id, nav_highlight_flags); } - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize*0.50f), text_col); + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize*0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogRenderedText(&text_pos, ">"); RenderText(text_pos, label, label_end, false); From 664f9e76b919226fb4854698e5d535cf68ff6a02 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 24 Sep 2019 15:46:08 +0200 Subject: [PATCH 128/200] Documentation: Various tweaks and improvements to the README page. [@ker0chan] --- docs/CHANGELOG.txt | 1 + docs/README.md | 90 ++++++++++++++++++++++------------------------ 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 63e96fe000fae..851dd5615f761 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,6 +74,7 @@ Other Changes: - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) +- Documentation: Various tweaks and improvements to the README page. [@ker0chan] - Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before ImGui_ImplOpenGL3_NewFrame(), which sometimes can be convenient. - Backends: OpenGL3: Attempt to automatically detect default GL loader by using __has_include. (#2798) [@o-micron] diff --git a/docs/README.md b/docs/README.md index 6ca295ea77830..36ca6d6ffb511 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,9 +3,9 @@ dear imgui [![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) -_(This library is available under a free and permissive licence, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.)_ +(This library is available under a free and permissive licence, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.) -Businesses: support continued development via invoiced technical support & maintenance contracts: +Businesses: support continued development via invoiced technical support, maintenance, sponsoring contracts:
  _E-mail: omarcornut at gmail dot com_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon: @@ -14,14 +14,23 @@ Individuals/hobbyists: support continued maintenance and development via the mon Individuals/hobbyists: support continued maintenance and development via PayPal:
  [![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=WGHNC6MBFLZ2S) -Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). +---- -Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. +Dear ImGui is a **bloat-free graphical user interface library for C++**. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). + +Dear ImGui is designed to **enable fast iterations** and to **empower programmers** to create **content creation tools and visualization / debug tools** (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. See [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui), [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Gallery](https://github.com/ocornut/imgui/issues/2529) pages to get an idea of its use cases. +| [Usage](#usage) - [How it works](#how-it-works) - [Demo](#demo) - [Integration](#integration) | +:----------------------------------------------------------: | +| [Upcoming changes](#upcoming-changes) - [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](#sponsors) - [Credits](#credits) - [License](#license) | +| [Wiki](https://github.com/ocornut/imgui/wiki) - [Language & frameworks bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) | + +### Usage + Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: - imgui.cpp - imgui.h @@ -36,12 +45,12 @@ Dear ImGui is self-contained within a few files that you can easily copy and com No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. -### Usage +Backends for a variety of graphics api and rendering platforms are provided in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. -Your code passes mouse/keyboard/gamepad inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it from \_anywhere\_ in your program loop: +The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices (see example applications for more details). After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop: Code: -```cpp +```cp ImGui::Text("Hello, world %d", 123); if (ImGui::Button("Save")) { @@ -88,6 +97,8 @@ ImGui::End(); Result:
![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_03_color.gif) +Dear ImGui allows you **create elaborate tools** as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. + ### How it works Check out the References section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. @@ -96,18 +107,18 @@ Dear ImGui outputs vertex buffers and command lists that you can easily render i _A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._ -Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. +### Demo -Demo Binaries -------------- +Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of Dear ImGui features and examples. + +![screenshot demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png) You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: - [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, Dear ImGui 1.72 WIP built 2019/07/15, master branch, 5 executables) The demo applications are unfortunately not yet DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. -Bindings --------- +### Integration Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you about an hour to integrate Dear ImGui in your custom engine. Make sure to spend time reading the FAQ, the comments and other documentation! @@ -158,8 +169,8 @@ Frameworks: For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/). Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. -Roadmap -------- +### Upcoming Changes + Some of the goals for 2019 are: - Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public `docking` branch looking for feedback) - Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public `docking` branch looking for feedback) @@ -168,18 +179,9 @@ Some of the goals for 2019 are: - Make Columns better. (they are currently pretty terrible!) - Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. -Gallery -------- -User screenshots: -
[Gallery Part 1](https://github.com/ocornut/imgui/issues/123) (Feb 2015 to Feb 2016) -
[Gallery Part 2](https://github.com/ocornut/imgui/issues/539) (Feb 2016 to Aug 2016) -
[Gallery Part 3](https://github.com/ocornut/imgui/issues/772) (Aug 2016 to Jan 2017) -
[Gallery Part 4](https://github.com/ocornut/imgui/issues/973) (Jan 2017 to Aug 2017) -
[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 to Feb 2018) -
[Gallery Part 6](https://github.com/ocornut/imgui/issues/1607) (Feb 2018 to June 2018) -
[Gallery Part 7](https://github.com/ocornut/imgui/issues/1902) (June 2018 to January 2019) -
[Gallery Part 8](https://github.com/ocornut/imgui/issues/2265) (January 2019 to May 2019) -
[Gallery Part 9](https://github.com/ocornut/imgui/issues/2529) (May 2019 onward) +### Gallery + +For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/2529)! Custom engine [![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) @@ -187,14 +189,10 @@ Custom engine Custom engine [![screenshot tool](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) -Demo window -![screenshot demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png) - [Tracy Profiler](https://bitbucket.org/wolfpld/tracy) ![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/tracy_profiler.png) -References ----------- +### References The Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because "Retained Mode" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works. - [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html). @@ -206,18 +204,14 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This See the [Wiki](https://github.com/ocornut/imgui/wiki) for more references and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks. -Support -------- +### Support, Frequently Asked Questions (FAQ) -If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: please post on the Discourse forums: https://discourse.dearimgui.org. +If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org). Otherwise for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. Private support is available for paying customers. -Frequently Asked Question (FAQ) -------------------------------- - **Where is the documentation?** This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. @@ -278,12 +272,12 @@ Dear ImGui takes advantage of a few C++ languages features for convenience but n There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings. -Support dear imgui ------------------- +How to help +----------- **How can I help?** -- You may participate in the [Discourse forums](https://discourse.dearimgui.org) and the GitHub [issues tracker](https://github.com/ocornut/imgui/issues). +- You may participate in the [Discord server](https://discord.gg/NgJ4SEP), [Discourse forums](https://discourse.dearimgui.org), GitHub [issues tracker](https://github.com/ocornut/imgui/issues). - You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it. - See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas. - Have your company financially support this project. @@ -292,7 +286,7 @@ Support dear imgui Your contributions are keeping this project alive. The library is available under a free and permissive licence, but continued maintenance and development are a full-time endeavor and I would like to grow the team. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced technical support and maintenance contracts. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal. Thank you! -Businesses: support continued development via invoiced technical support & maintenance contracts: +Businesses: support continued development via invoiced technical support, maintenance, sponsoring contracts:
  _E-mail: omarcornut at gmail dot com_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon: @@ -301,20 +295,22 @@ Individuals/hobbyists: support continued maintenance and development via the mon Individuals/hobbyists: support continued maintenance and development via PayPal:
  [![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=WGHNC6MBFLZ2S) -Ongoing dear imgui development is financially supported by users and private sponsors, recently: +### Sponsors + +Ongoing Dear ImGui development is financially supported by users and private sponsors, recently: -**Platinum-chocolate sponsors** +*Platinum-chocolate sponsors* - Blizzard Entertainment - Google -**Double-chocolate sponsors** +*Double-chocolate sponsors* - Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn. -**Salty caramel supporters** +*Salty caramel supporters* - Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders. -**Caramel supporters** -- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis. +*Caramel supporters* +- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis, Matt Reyer. And all other past and present supporters; THANK YOU! (Please contact me if you would like to be added or removed from this list) From 293f74e9964630eb35cf41b4bbd839f5136bae36 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 24 Sep 2019 16:00:53 +0200 Subject: [PATCH 129/200] Update README.md --- docs/README.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/README.md b/docs/README.md index 36ca6d6ffb511..c8c80cb31e30e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,7 +9,7 @@ Businesses: support continued development via invoiced technical support, mainte
  _E-mail: omarcornut at gmail dot com_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon: -
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_01.png)](http://www.patreon.com/imgui) +
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_02.png)](http://www.patreon.com/imgui) Individuals/hobbyists: support continued maintenance and development via PayPal:
  [![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=WGHNC6MBFLZ2S) @@ -22,12 +22,10 @@ Dear ImGui is designed to **enable fast iterations** and to **empower programmer Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. -See [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui), [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Gallery](https://github.com/ocornut/imgui/issues/2529) pages to get an idea of its use cases. - | [Usage](#usage) - [How it works](#how-it-works) - [Demo](#demo) - [Integration](#integration) | :----------------------------------------------------------: | | [Upcoming changes](#upcoming-changes) - [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](#sponsors) - [Credits](#credits) - [License](#license) | -| [Wiki](https://github.com/ocornut/imgui/wiki) - [Language & frameworks bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) | +| [Wiki](https://github.com/ocornut/imgui/wiki) - [Language & frameworks bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) | ### Usage @@ -45,9 +43,9 @@ Dear ImGui is self-contained within a few files that you can easily copy and com No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. -Backends for a variety of graphics api and rendering platforms are provided in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. +Backends for a variety of graphics api and rendering platforms along with example applications are provided in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. -The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices (see example applications for more details). After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop: +The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices. After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop: Code: ```cp @@ -109,12 +107,12 @@ _A common misunderstanding is to mistake immediate mode gui for immediate mode r ### Demo -Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of Dear ImGui features and examples. +Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of features and examples. ![screenshot demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png) You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, Dear ImGui 1.72 WIP built 2019/07/15, master branch, 5 executables) +- [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, 1.72 WIP built 2019/07/15, master branch, 5 executables) The demo applications are unfortunately not yet DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. @@ -172,12 +170,12 @@ For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Binding ### Upcoming Changes Some of the goals for 2019 are: -- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public `docking` branch looking for feedback) -- Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public `docking` branch looking for feedback) +- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) +- Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) - Add an automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435)) -- Make Columns better. (they are currently pretty terrible!) -- Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. +- Make Columns better. They are currently pretty terrible! New Tables API coming Q4 2019! +- Make the examples look better, improve styles, improve font support, make the examples hi-DPI and multi-DPI aware. ### Gallery @@ -290,7 +288,7 @@ Businesses: support continued development via invoiced technical support, mainte
  _E-mail: omarcornut at gmail dot com_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon: -
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_01.png)](http://www.patreon.com/imgui) +
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_02.png)](http://www.patreon.com/imgui) Individuals/hobbyists: support continued maintenance and development via PayPal:
  [![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=WGHNC6MBFLZ2S) From d5efe161572c894baed5865dee4db943a54fa0c3 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 24 Sep 2019 16:33:47 +0200 Subject: [PATCH 130/200] Version 1.73 --- docs/CHANGELOG.txt | 7 ++++--- examples/README.txt | 2 +- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- misc/fonts/README.txt | 10 ++++++---- 9 files changed, 19 insertions(+), 16 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 851dd5615f761..219e9fced006d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -30,10 +30,11 @@ HOW TO UPDATE? ----------------------------------------------------------------------- - VERSION 1.73 WIP (In Progress) + VERSION 1.73 (Released 2019-09-24) ----------------------------------------------------------------------- Other Changes: + - Nav, Scrolling: Added support for Home/End key. (#787) - ColorEdit: Disable Hue edit when Saturation==0 instead of letting Hue values jump around. - ColorEdit, ColorPicker: In HSV display of a RGB stored value, attempt to locally preserve Hue @@ -63,7 +64,7 @@ Other Changes: mostly for consistency. (#2159, #2160) [@goran-w] - Selectable: Added ImGuiSelectableFlags_AllowItemOverlap flag in public api (was previously internal only). - Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) -- Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly +- Font: Better ellipsis ("...") drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow as possible. (#2775) [@rokups] @@ -84,7 +85,7 @@ Other Changes: one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. (#2705, #2706) [@vilya] - Examples: OSX: Fix example_apple_opengl2/main.mm not forwarding mouse clicks and drags correctly. (#1961, #2710) [@intonarumori, @ElectricMagic] -- Misc: Updated stb_rect_pack from 0.99 to 1.00 (fixes by @rygorous: off-by-1 bug in best-fit heuristic, +- Misc: Updated stb_rect_pack.h from 0.99 to 1.00 (fixes by @rygorous: off-by-1 bug in best-fit heuristic, fix handling of rectangles too large to fit inside texture). (#2762) [@tido64] diff --git a/examples/README.txt b/examples/README.txt index 7e46c8432ab65..031a53b97b822 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- - dear imgui, v1.73 WIP + dear imgui, v1.73 ----------------------------------------------------------------------- examples/README.txt (This is the README file for the examples/ folder. See docs/ for more documentation) diff --git a/imgui.cpp b/imgui.cpp index f276b5f4e9ee7..93b15ddb94a0e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.73 // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index b5a1155ebad86..9697c80db755a 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.73 // (headers) // See imgui.cpp file for documentation. @@ -46,8 +46,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.73 WIP" -#define IMGUI_VERSION_NUM 17203 +#define IMGUI_VERSION "1.73" +#define IMGUI_VERSION_NUM 17300 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 492158d119041..ec1ada820a133 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.73 // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 2cbf209b70847..845cd04e86cf9 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.73 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index edc0fb06f7df1..6d3931039e891 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.73 // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d9dc4ec6e7b4e..bcd051e577262 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 WIP +// dear imgui, v1.73 // (widgets code) /* diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index b8790af627b3a..51a97f93424c6 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -1,7 +1,9 @@ -dear imgui, v1.73 WIP -(Font Readme) - ---------------------------------------- +---------------------------------------------------------------------- + dear imgui, v1.73 +---------------------------------------------------------------------- + misc/fonts/README.txt + This is the Readme dedicated to fonts. +---------------------------------------------------------------------- The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer), a 13 pixels high, pixel-perfect font used by default. From f0f5301612dbaa2caeede3091df6aee1c872dbdf Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Wed, 25 Sep 2019 01:06:14 +0300 Subject: [PATCH 131/200] Backends: OpenGL3: Commented out extra tokens at end of #else directive (#2804) --- examples/imgui_impl_opengl3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 189814f49d277..e1eee236850b2 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -172,7 +172,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) gl_loader = "GLEW"; #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) gl_loader = "GLAD"; -#else IMGUI_IMPL_OPENGL_LOADER_CUSTOM +#else // IMGUI_IMPL_OPENGL_LOADER_CUSTOM gl_loader = "Custom"; #endif From c262276988da6ae4b16911d9c56fc8d9226e7319 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Sep 2019 14:27:56 +0200 Subject: [PATCH 132/200] Version 1.74 WIP --- docs/CHANGELOG.txt | 11 +++++++++++ examples/README.txt | 2 +- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- misc/fonts/README.txt | 2 +- 9 files changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 219e9fced006d..8ef15ad7f64b5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -29,6 +29,17 @@ HOW TO UPDATE? - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.74 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking Changes: +- + +Other Changes: +- + + ----------------------------------------------------------------------- VERSION 1.73 (Released 2019-09-24) ----------------------------------------------------------------------- diff --git a/examples/README.txt b/examples/README.txt index 031a53b97b822..23c6bdb96f7ba 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- - dear imgui, v1.73 + dear imgui, v1.74 WIP ----------------------------------------------------------------------- examples/README.txt (This is the README file for the examples/ folder. See docs/ for more documentation) diff --git a/imgui.cpp b/imgui.cpp index 93b15ddb94a0e..cee65ff842029 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 +// dear imgui, v1.74 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index 9697c80db755a..8696ef4dfa0b0 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.73 +// dear imgui, v1.74 WIP // (headers) // See imgui.cpp file for documentation. @@ -46,8 +46,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.73" -#define IMGUI_VERSION_NUM 17300 +#define IMGUI_VERSION "1.74 WIP" +#define IMGUI_VERSION_NUM 17301 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ec1ada820a133..41c26546d6877 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 +// dear imgui, v1.74 WIP // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 845cd04e86cf9..4a6dce6d1cbca 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 +// dear imgui, v1.74 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 6d3931039e891..19f2bfef15d63 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.73 +// dear imgui, v1.74 WIP // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index bcd051e577262..838f936715c79 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.73 +// dear imgui, v1.74 WIP // (widgets code) /* diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 51a97f93424c6..39e0dd48dd3a8 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -1,5 +1,5 @@ ---------------------------------------------------------------------- - dear imgui, v1.73 + dear imgui, v1.74 WIP ---------------------------------------------------------------------- misc/fonts/README.txt This is the Readme dedicated to fonts. From 0dad3f436b2ae06267ee9c8e2df39bc6cd9d9e18 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Sep 2019 15:16:30 +0200 Subject: [PATCH 133/200] Fix harmless float calculation overflow. (#2813) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index cee65ff842029..77eeb4c4b7949 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2711,6 +2711,8 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); + InnerRect = ImRect(0.0f, 0.0f, 0.0f, 0.0f); // Clear so the InnerRect.GetSize() code in Begin() doesn't lead to overflow even if the result isn't used. + LastFrameActive = -1; LastTimeActive = -1.0f; ItemWidthDefault = 0.0f; From eb5223276c8d4169f40ab063bd2fd9e66b2e8716 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Sep 2019 20:54:37 +0200 Subject: [PATCH 134/200] Update README.md --- docs/README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index c8c80cb31e30e..de68bdabcf476 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,7 +6,7 @@ dear imgui (This library is available under a free and permissive licence, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.) Businesses: support continued development via invoiced technical support, maintenance, sponsoring contracts: -
  _E-mail: omarcornut at gmail dot com_ +
  _E-mail: contact @ dearimgui dot org_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_02.png)](http://www.patreon.com/imgui) @@ -51,9 +51,7 @@ Code: ```cp ImGui::Text("Hello, world %d", 123); if (ImGui::Button("Save")) -{ - // do stuff -} + MySaveFunction(); ImGui::InputText("string", buf, IM_ARRAYSIZE(buf)); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ``` @@ -99,7 +97,7 @@ Dear ImGui allows you **create elaborate tools** as well as very short-lived one ### How it works -Check out the References section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. +Check out the [References](#references) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes required to render them is fairly small. Because Dear ImGui doesn't know or touch graphics state directly, you can call its functions anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. @@ -107,23 +105,25 @@ _A common misunderstanding is to mistake immediate mode gui for immediate mode r ### Demo -Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of features and examples. +Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. ![screenshot demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png) You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, 1.72 WIP built 2019/07/15, master branch, 5 executables) +- [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, 1.72 WIP, built 2019/07/15, master branch, 5 executables) -The demo applications are unfortunately not yet DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. +The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your style with `style.ScaleAllSizes()`. ### Integration -Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you about an hour to integrate Dear ImGui in your custom engine. Make sure to spend time reading the FAQ, the comments and other documentation! +On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/examples) files without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom binding using your custom engine functions if you wish so. + +Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the FAQ, comments, and one of the examples/ application!** -_NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ +_NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users!). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ -Languages: (third-party bindings) -- C: [cimgui](https://github.com/cimgui/cimgui) (2018: now auto-generated! you can use its json output to generate bindings for other languages) +Languages: +- C: [cimgui](https://github.com/cimgui/cimgui) (auto-generated! **you can use its json output to generate bindings for other languages**) - C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) - D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui) @@ -139,7 +139,7 @@ Languages: (third-party bindings) - Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy) or [ogre-imgui](https://github.com/OGRECave/ogre-imgui) - Ruby: [ruby-imgui](https://github.com/vaiorabbit/ruby-imgui) - Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) or [imgui-rust](https://github.com/nsf/imgui-rust) -- Swift [swift-imgui](https://github.com/mnmly/Swift-imgui) +- Swift: [swift-imgui](https://github.com/mnmly/Swift-imgui) Frameworks: - Renderers: DirectX 9/10/11/12, Metal, OpenGL2, OpenGL3+/ES2/ES3, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) @@ -266,7 +266,7 @@ You can alter the look of the interface to some degree: changing colors, sizes, **Why using C++ (as opposed to C)?** -Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. +Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings. @@ -285,7 +285,7 @@ How to help Your contributions are keeping this project alive. The library is available under a free and permissive licence, but continued maintenance and development are a full-time endeavor and I would like to grow the team. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced technical support and maintenance contracts. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal. Thank you! Businesses: support continued development via invoiced technical support, maintenance, sponsoring contracts: -
  _E-mail: omarcornut at gmail dot com_ +
  _E-mail: contact @ dearimgui dot org_ Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
  [![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_02.png)](http://www.patreon.com/imgui) @@ -316,13 +316,13 @@ And all other past and present supporters; THANK YOU! Credits ------- -Developed by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect contributors to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com). +Developed by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect contributors to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com) (Vita). I first discovered the IMGUI paradigm at [Q-Games](http://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it. Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license). -Embeds [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain). +Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain). Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub. From 893056a2094a254f0ceab74edc4aa9f1d73df3de Mon Sep 17 00:00:00 2001 From: Denys Nahurnyi Date: Tue, 1 Oct 2019 22:49:44 +0300 Subject: [PATCH 135/200] Fix syntax typos in README (#2819) --- docs/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/README.md b/docs/README.md index de68bdabcf476..b4540c17ef183 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@ dear imgui [![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) -(This library is available under a free and permissive licence, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.) +(This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.) Businesses: support continued development via invoiced technical support, maintenance, sponsoring contracts:
  _E-mail: contact @ dearimgui dot org_ @@ -206,7 +206,7 @@ See the [Wiki](https://github.com/ocornut/imgui/wiki) for more references and [B If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org). -Otherwise for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. +Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. Private support is available for paying customers. @@ -218,8 +218,8 @@ Private support is available for paying customers. - The demo covers most features of Dear ImGui, so you can read the code and see its output. - See documentation and comments at the top of imgui.cpp + effectively imgui.h. - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application. - - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. - - We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. + - Your programming IDE is your friend, find the type or function declaration to find comments associated with it. + - We obviously need better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. **Which version should I get?** @@ -233,7 +233,7 @@ See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software usi **Why the odd dual naming, "Dear ImGui" vs "ImGui"?** -The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui". +The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses its own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui". **How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?**
**How can I display an image? What is ImTextureID, how does it works?** ([examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples)) @@ -256,7 +256,7 @@ See the FAQ in [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cp Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. -Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. +Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. **Can you reskin the look of Dear ImGui?** @@ -282,7 +282,7 @@ How to help **How can I help financing further development of Dear ImGui?** -Your contributions are keeping this project alive. The library is available under a free and permissive licence, but continued maintenance and development are a full-time endeavor and I would like to grow the team. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced technical support and maintenance contracts. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal. Thank you! +Your contributions are keeping this project alive. The library is available under a free and permissive license, but continued maintenance and development are a full-time endeavor and I would like to grow the team. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced technical support and maintenance contracts. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal. Thank you! Businesses: support continued development via invoiced technical support, maintenance, sponsoring contracts:
  _E-mail: contact @ dearimgui dot org_ From a2f3dcfc9755ae5b4d4110c31e4101437f7554be Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Oct 2019 11:38:30 +0200 Subject: [PATCH 136/200] Added comment about SDL and SDL_INIT_GAMECONTROLLER. (#2809) --- docs/TODO.txt | 5 +++-- examples/example_sdl_directx11/main.cpp | 2 ++ examples/example_sdl_opengl2/main.cpp | 2 ++ examples/example_sdl_opengl3/main.cpp | 2 ++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index 07f6676bb971c..7ca24ca87cc93 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -262,16 +262,17 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - drag and drop: fix/support/options for overlapping drag sources. - drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725) - drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233 - - drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. + - drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. (see 2018/01/11 post in #143) - drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725) - drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637) - drag and drop: make it easier and provide a demo to have tooltip both are source and target site, with a more detailed one on target site (tooltip ordering problem) - drag and drop: demo with reordering nodes (in a list, or a tree node). (#143) - drag and drop: test integrating with os drag and drop (make it easy to do a naive WM_DROPFILE integration) - drag and drop: allow for multiple payload types. (#143) - - drag and drop: make payload optional? (#143) + - drag and drop: make payload optional? payload promise? (see 2018/01/11 post in #143) - drag and drop: (#143) "both an in-process pointer and a promise to generate a serialized version, for whether the drag ends inside or outside the same process" - drag and drop: feedback when hovering a region blocked by modal (mouse cursor "NO"?) + - node/graph editor (#306) - pie menus patterns (#434) - markup: simple markup language for color change? (#902) diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl_directx11/main.cpp index ae523fe90b9e5..680f179e72204 100644 --- a/examples/example_sdl_directx11/main.cpp +++ b/examples/example_sdl_directx11/main.cpp @@ -26,6 +26,8 @@ void CleanupRenderTarget(); int main(int, char**) { // Setup SDL + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index 1222c250c40c5..9bc88d90baefa 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -17,6 +17,8 @@ int main(int, char**) { // Setup SDL + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index 19d34e9ad5d06..1641546593356 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -27,6 +27,8 @@ int main(int, char**) { // Setup SDL + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); From 892dfb1dea65644b1c6f9882b9c883a837b18369 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Oct 2019 11:38:30 +0200 Subject: [PATCH 137/200] InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) Small refactor of ActiveIdUsingXXX inputs flags toward a little more consistent system. (#2637) --- docs/CHANGELOG.txt | 4 ++-- imgui.cpp | 43 +++++++++++++++++++++++++------------------ imgui.h | 1 - imgui_internal.h | 18 ++++++++++++------ imgui_widgets.cpp | 20 ++++++++++++-------- 5 files changed, 51 insertions(+), 35 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8ef15ad7f64b5..a46b3af886d5d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,10 +34,10 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Breaking Changes: -- +- Other Changes: -- +- InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 77eeb4c4b7949..3e3cb4e47c18e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1064,7 +1064,7 @@ static void NavUpdate(); static void NavUpdateWindowing(); static void NavUpdateWindowingOverlay(); static void NavUpdateMoveResult(); -static float NavUpdatePageUpPageDown(int allowed_dir_flags); +static float NavUpdatePageUpPageDown(); static inline void NavUpdateAnyRequestFlag(); static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id); @@ -2867,8 +2867,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) } } g.ActiveId = id; - g.ActiveIdAllowNavDirFlags = 0; - g.ActiveIdBlockNavInputFlags = 0; g.ActiveIdAllowOverlap = false; g.ActiveIdWindow = window; g.ActiveIdHasBeenEditedThisFrame = false; @@ -2877,6 +2875,12 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.ActiveIdIsAlive = id; g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; } + + // Clear declaration of inputs claimed by the widget + // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) + g.ActiveIdUsingNavDirMask = 0x00; + g.ActiveIdUsingNavInputMask = 0x00; + g.ActiveIdUsingKeyInputMask = 0x00; } // FIXME-NAV: The existence of SetNavID/SetNavIDWithRectRel/SetFocusID is incredibly messy and confusing and needs some explanation or refactoring. @@ -3157,7 +3161,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // Process TAB/Shift-TAB to tab *OUT* of the currently focused item. // (Note that we can always TAB out of a widget that doesn't allow tabbing in) - if (g.ActiveId == id && g.FocusTabPressed && !(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_KeyTab_)) && g.FocusRequestNextWindow == NULL) + if (g.ActiveId == id && g.FocusTabPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.FocusRequestNextWindow == NULL) { g.FocusRequestNextWindow = window; g.FocusRequestNextCounterTab = window->DC.FocusCounterTab + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. @@ -3782,6 +3786,11 @@ void ImGui::NewFrame() g.ActiveIdIsJustActivated = false; if (g.TempInputTextId != 0 && g.ActiveId != g.TempInputTextId) g.TempInputTextId = 0; + if (g.ActiveId == 0) + { + g.ActiveIdUsingNavDirMask = g.ActiveIdUsingNavInputMask = 0; + g.ActiveIdUsingKeyInputMask = 0; + } // Drag and drop g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; @@ -8271,7 +8280,6 @@ static void ImGui::NavUpdate() NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_); NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ ); NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ ); - NAV_MAP_KEY(ImGuiKey_Tab, ImGuiNavInput_KeyTab_ ); if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; if (g.IO.KeyShift) @@ -8349,7 +8357,7 @@ static void ImGui::NavUpdate() { if (g.ActiveId != 0) { - if (!(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_Cancel))) + if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel)) ClearActiveID(); } else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) @@ -8411,17 +8419,16 @@ static void ImGui::NavUpdate() g.NavNextActivateId = 0; // Initiate directional inputs request - const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; if (g.NavMoveRequestForward == ImGuiNavForward_None) { g.NavMoveDir = ImGuiDir_None; g.NavMoveRequestFlags = ImGuiNavMoveFlags_None; - if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + if (g.NavWindow && !g.NavWindowingTarget && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1 << ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Left; } - if ((allowed_dir_flags & (1 << ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Right; } - if ((allowed_dir_flags & (1 << ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Up; } - if ((allowed_dir_flags & (1 << ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Down; } + if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Left; } + if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Right; } + if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Up; } + if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Down; } } g.NavMoveClipDir = g.NavMoveDir; } @@ -8438,7 +8445,7 @@ static void ImGui::NavUpdate() // FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag? float nav_scoring_rect_offset_y = 0.0f; if (nav_keyboard_active) - nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags); + nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(); // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match if (g.NavMoveDir != ImGuiDir_None) @@ -8585,7 +8592,7 @@ static void ImGui::NavUpdateMoveResult() } // Handle PageUp/PageDown/Home/End keys -static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) +static float ImGui::NavUpdatePageUpPageDown() { ImGuiContext& g = *GImGui; if (g.NavMoveDir != ImGuiDir_None || g.NavWindow == NULL) @@ -8594,10 +8601,10 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) return 0.0f; ImGuiWindow* window = g.NavWindow; - const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); - const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); - const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); - const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp); + const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown); + const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home); + const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End); if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed { if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) diff --git a/imgui.h b/imgui.h index 8696ef4dfa0b0..a7e5fd7ebddd3 100644 --- a/imgui.h +++ b/imgui.h @@ -986,7 +986,6 @@ enum ImGuiNavInput_ // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them. // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[]. ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt - ImGuiNavInput_KeyTab_, // tab // = Tab key ImGuiNavInput_KeyLeft_, // move left // = Arrow keys ImGuiNavInput_KeyRight_, // move right ImGuiNavInput_KeyUp_, // move up diff --git a/imgui_internal.h b/imgui_internal.h index 19f2bfef15d63..dcb8f4f5fe2d4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -900,8 +900,9 @@ struct ImGuiContext bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedThisFrame; - int ActiveIdAllowNavDirFlags; // Active widget allows using directional navigation (e.g. can activate a button and move away from it) - int ActiveIdBlockNavInputFlags; + ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those directional navigation requests (e.g. can activate a button and move away from it) + ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs. + ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array. ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) @@ -1092,8 +1093,9 @@ struct ImGuiContext ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedThisFrame = false; - ActiveIdAllowNavDirFlags = 0x00; - ActiveIdBlockNavInputFlags = 0x00; + ActiveIdUsingNavDirMask = 0x00; + ActiveIdUsingNavInputMask = 0x00; + ActiveIdUsingKeyInputMask = 0x00; ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; ActiveIdSource = ImGuiInputSource_None; @@ -1584,9 +1586,13 @@ namespace ImGui IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel); // Inputs + // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. + inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } + inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } + inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } IMGUI_API bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); - inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { const int key_index = GImGui->IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } - inline bool IsNavInputDown(ImGuiNavInput n) { return GImGui->IO.NavInputs[n] > 0.0f; } + inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { ImGuiContext& g = *GImGui; const int key_index = g.IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } + inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; } inline bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) { return GetNavInputAmount(n, mode) > 0.0f; } inline bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiInputReadMode mode) { return (GetNavInputAmount(n1, mode) + GetNavInputAmount(n2, mode)) > 0.0f; } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 838f936715c79..3f5a24f7cbaee 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -557,7 +557,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool SetActiveID(id, window); if ((nav_activated_by_code || nav_activated_by_inputs) && !(flags & ImGuiButtonFlags_NoNavFocus)) SetFocusID(id, window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } } @@ -2093,7 +2092,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id) { temp_input_start = true; @@ -2542,7 +2541,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id) { temp_input_start = true; @@ -2696,7 +2695,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); + g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } // Draw frame @@ -3505,12 +3504,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); + + // Declare our inputs IM_ASSERT(ImGuiNavInput_COUNT < 32); - g.ActiveIdBlockNavInputFlags = (1 << ImGuiNavInput_Cancel); + if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) + g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); + g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Home) | ((ImU64)1 << ImGuiKey_End); + if (is_multiline) + g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_PageUp) | ((ImU64)1 << ImGuiKey_PageDown); // FIXME-NAV: Page up/down actually not supported yet by widget, but claim them ahead. if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character. - g.ActiveIdBlockNavInputFlags |= (1 << ImGuiNavInput_KeyTab_); - if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory)) - g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); + g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Tab); } // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) From a6c3be4bda0a18a189a2e75de96290671ddadb18 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 3 Oct 2019 15:59:36 +0200 Subject: [PATCH 138/200] Internals: Tweaks to ItemSize() should be harmless. Added DebugDrawItemRect() helper. --- imgui.cpp | 16 ++++++++-------- imgui_internal.h | 8 +++++--- imgui_widgets.cpp | 1 + 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3e3cb4e47c18e..4e95e0115ebb5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2969,7 +2969,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla } // Advance cursor given item size for layout. -void ImGui::ItemSize(const ImVec2& size, float text_offset_y) +void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -2978,28 +2978,28 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y) // Always align ourselves on pixel boundaries const float line_height = ImMax(window->DC.CurrLineSize.y, size.y); - const float text_base_offset = ImMax(window->DC.CurrLineTextBaseOffset, text_offset_y); //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line + window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] window->DC.PrevLineSize.y = line_height; - window->DC.PrevLineTextBaseOffset = text_base_offset; - window->DC.CurrLineSize.y = window->DC.CurrLineTextBaseOffset = 0.0f; + window->DC.CurrLineSize.y = 0.0f; + window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); + window->DC.CurrLineTextBaseOffset = 0.0f; // Horizontal layout mode if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) SameLine(); } -void ImGui::ItemSize(const ImRect& bb, float text_offset_y) +void ImGui::ItemSize(const ImRect& bb, float text_baseline_y) { - ItemSize(bb.GetSize(), text_offset_y); + ItemSize(bb.GetSize(), text_baseline_y); } // Declare item bounding box for clipping and interaction. diff --git a/imgui_internal.h b/imgui_internal.h index dcb8f4f5fe2d4..df96fd8bce3b5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -383,6 +383,7 @@ enum ImGuiSeparatorFlags_ // This is going to be exposed in imgui.h when stabilized enough. enum ImGuiItemFlags_ { + ImGuiItemFlags_None = 0, ImGuiItemFlags_NoTabStop = 1 << 0, // false ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211 @@ -1541,8 +1542,8 @@ namespace ImGui IMGUI_API void PushOverrideID(ImGuiID id); // Basic Helpers for widget code - IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); - IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); + IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = 0.0f); + IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = 0.0f); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); @@ -1704,7 +1705,8 @@ namespace ImGui IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); // Debug Tools - inline void DebugStartItemPicker() { GImGui->DebugItemPickerActive = true; } + inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); } + inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } } // namespace ImGui diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3f5a24f7cbaee..a16cff3c40f18 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -112,6 +112,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const //------------------------------------------------------------------------- // [SECTION] Widgets: Text, etc. //------------------------------------------------------------------------- +// - TextEx() [Internal] // - TextUnformatted() // - Text() // - TextV() From 1425bec7a450e378db20930c1e9f47601dc1f45b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 3 Oct 2019 16:57:14 +0200 Subject: [PATCH 139/200] Demo: Text baseline demo tweaks. --- imgui_demo.cpp | 136 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 46 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 41c26546d6877..036d90688de72 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2047,55 +2047,99 @@ static void ShowDemoWindowLayout() if (ImGui::TreeNode("Text Baseline Alignment")) { - HelpMarker("This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets."); - - ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("One\nTwo\nThree"); - - ImGui::Button("HOP##1"); ImGui::SameLine(); - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Button("HOP##2"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Button("TEST##1"); ImGui::SameLine(); - ImGui::Text("TEST"); ImGui::SameLine(); - ImGui::SmallButton("TEST##2"); - - ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets. - ImGui::Text("Text aligned to Widget"); ImGui::SameLine(); - ImGui::Button("Widget##1"); ImGui::SameLine(); - ImGui::Text("Widget"); ImGui::SameLine(); - ImGui::SmallButton("Widget##2"); ImGui::SameLine(); - ImGui::Button("Widget##3"); - - // Tree - const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImGui::Button("Button##1"); - ImGui::SameLine(0.0f, spacing); - if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + { + ImGui::BulletText("Text baseline:"); + ImGui::SameLine(); + HelpMarker("This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets."); + ImGui::Indent(); - ImGui::AlignTextToFramePadding(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). - bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); - if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + ImGui::Text("KO Blahblah"); ImGui::SameLine(); + ImGui::Button("Some framed item"); ImGui::SameLine(); + HelpMarker("Baseline of button will look misaligned with text.."); - // Bullet - ImGui::Button("Button##3"); - ImGui::SameLine(0.0f, spacing); - ImGui::BulletText("Bullet text"); + // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets. + // Because we don't know what's coming after the Text() statement, we need to move the text baseline down by FramePadding.y + ImGui::AlignTextToFramePadding(); + ImGui::Text("OK Blahblah"); ImGui::SameLine(); + ImGui::Button("Some framed item"); ImGui::SameLine(); + HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y"); - ImGui::AlignTextToFramePadding(); - ImGui::BulletText("Node"); - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); + // SmallButton() uses the same vertical padding as Text + ImGui::Button("TEST##1"); ImGui::SameLine(); + ImGui::Text("TEST"); ImGui::SameLine(); + ImGui::SmallButton("TEST##2"); + + // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets. + ImGui::AlignTextToFramePadding(); + ImGui::Text("Text aligned to framed item"); ImGui::SameLine(); + ImGui::Button("Item##1"); ImGui::SameLine(); + ImGui::Text("Item"); ImGui::SameLine(); + ImGui::SmallButton("Item##2"); ImGui::SameLine(); + ImGui::Button("Item##3"); + + ImGui::Unindent(); + } + + ImGui::Spacing(); + + { + ImGui::BulletText("Multi-line text:"); + ImGui::Indent(); + ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + + ImGui::Text("Banana"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("One\nTwo\nThree"); + + ImGui::Button("HOP##1"); ImGui::SameLine(); + ImGui::Text("Banana"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + + ImGui::Button("HOP##2"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + ImGui::Unindent(); + } + + ImGui::Spacing(); + + { + ImGui::BulletText("Misc items:"); + ImGui::Indent(); + + // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button + ImGui::Button("80x80", ImVec2(80, 80)); + ImGui::SameLine(); + ImGui::Button("50x50", ImVec2(50, 50)); + ImGui::SameLine(); + ImGui::Button("Button()"); + ImGui::SameLine(); + ImGui::SmallButton("SmallButton()"); + + // Tree + const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; + ImGui::Button("Button##1"); + ImGui::SameLine(0.0f, spacing); + if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + + ImGui::AlignTextToFramePadding(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). + bool node_open = ImGui::TreeNode("Node##2");// Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. + ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); + if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + + // Bullet + ImGui::Button("Button##3"); + ImGui::SameLine(0.0f, spacing); + ImGui::BulletText("Bullet text"); + + ImGui::AlignTextToFramePadding(); + ImGui::BulletText("Node"); + ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); + ImGui::Unindent(); + } ImGui::TreePop(); } From ccb2a947a27d9fe5c711a7d7bc5ab18c6fa0b78b Mon Sep 17 00:00:00 2001 From: domgho Date: Fri, 4 Oct 2019 11:57:20 +0200 Subject: [PATCH 140/200] Internal: SliderBehaviorT: Condition '!is_decimal' is always true (#2828) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a16cff3c40f18..26e1d648a284d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2430,7 +2430,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ FLOATTYPE v_new_off_f = (v_max - v_min) * clicked_t; TYPE v_new_off_floor = (TYPE)(v_new_off_f); TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5); - if (!is_decimal && v_new_off_floor < v_new_off_round) + if (v_new_off_floor < v_new_off_round) v_new = v_min + v_new_off_round; else v_new = v_min + v_new_off_floor; From ee3373d067ed253ee70087818a16b0b1210e1b8c Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 4 Oct 2019 19:21:29 +0200 Subject: [PATCH 141/200] TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a46b3af886d5d..e1cd2ad9c64e3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -38,6 +38,8 @@ Breaking Changes: Other Changes: - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) +- TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow + incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) ----------------------------------------------------------------------- diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 26e1d648a284d..d6631a17dbf53 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5270,9 +5270,11 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { if (pressed) { + const float arrow_x1 = text_pos.x - text_offset_x; + const float arrow_x2 = arrow_x1 + g.FontSize + padding.x * 2.0f; toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) || (g.NavActivateId == id); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover); + toggled |= IsMouseHoveringRect(ImVec2(arrow_x1, interact_bb.Min.y), ImVec2(arrow_x2, interact_bb.Max.y)) && (!g.NavDisableMouseHover); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) toggled |= g.IO.MouseDoubleClicked[0]; if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again. From f1f321d3f6d585df3d6320a23e5b69885d392405 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 5 Oct 2019 16:07:00 +0200 Subject: [PATCH 142/200] Update README.md --- docs/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/README.md b/docs/README.md index b4540c17ef183..7d29ace914276 100644 --- a/docs/README.md +++ b/docs/README.md @@ -120,9 +120,14 @@ On most platforms and when using C++, **you should be able to use a combination Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the FAQ, comments, and one of the examples/ application!** -_NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users!). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ +_NB: third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users!). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ -Languages: +Officially maintained bindings in repository: +- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. +- Platforms: GLFW, SDL2, Win32, Glut, OSX. +- Others: Allegro5, Marmalade. + +Third-party - Languages bindings: - C: [cimgui](https://github.com/cimgui/cimgui) (auto-generated! **you can use its json output to generate bindings for other languages**) - C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) @@ -141,11 +146,7 @@ Languages: - Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) or [imgui-rust](https://github.com/nsf/imgui-rust) - Swift: [swift-imgui](https://github.com/mnmly/Swift-imgui) -Frameworks: -- Renderers: DirectX 9/10/11/12, Metal, OpenGL2, OpenGL3+/ES2/ES3, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Platform: GLFW, SDL, Win32, OSX, GLUT: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Framework: Allegro 5, Emscripten, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) +Third-party - Engines/Frameworks bindings: - bsf: [bsfimgui](https://github.com/pgruenbacher/bsfImgui) - Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) - Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551) @@ -164,6 +165,7 @@ Frameworks: - SFML: [imgui-sfml](https://github.com/eliasdaler/imgui-sfml) - Software renderer: [imgui_software_renderer](https://github.com/emilk/imgui_software_renderer) - Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) +- Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/). Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. From 73fa6509a516c2b43478947e6cc713c538ce2ec2 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 5 Oct 2019 16:53:28 +0200 Subject: [PATCH 143/200] Internal: InputTextEx: tweaked a bit of code (should be a no-op) --- imgui.cpp | 2 +- imgui_widgets.cpp | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4e95e0115ebb5..7bf2bf597e439 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4303,7 +4303,7 @@ void ImGui::Render() } // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. -// CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize) +// CalcTextSize("") should return ImVec2(0.0f, g.FontSize) ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) { ImGuiContext& g = *GImGui; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d6631a17dbf53..1561c157460a3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3404,11 +3404,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ BeginGroup(); const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); + const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line + const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y); + + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); + const ImRect total_bb(frame_bb.Min, frame_bb.Min + total_size); ImGuiWindow* draw_window = window; + ImVec2 inner_size = frame_size; if (is_multiline) { if (!ItemAdd(total_bb, id, &frame_bb)) @@ -3423,9 +3426,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ EndGroup(); return false; } - draw_window = GetCurrentWindow(); + draw_window = g.CurrentWindow; // Child window draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight - size.x -= draw_window->ScrollbarSizes.x; + inner_size.x -= draw_window->ScrollbarSizes.x; } else { @@ -3914,7 +3917,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); } - const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size + const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + inner_size.x, frame_bb.Min.y + inner_size.y); // Not using frame_bb.Max because we have adjusted size ImVec2 draw_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; ImVec2 text_size(0.0f, 0.0f); @@ -3995,7 +3998,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224) if (is_multiline) - text_size = ImVec2(size.x, line_count * g.FontSize); + text_size = ImVec2(inner_size.x, line_count * g.FontSize); } // Scroll @@ -4004,11 +4007,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Horizontal scroll in chunks of quarter width if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll)) { - const float scroll_increment_x = size.x * 0.25f; + const float scroll_increment_x = inner_size.x * 0.25f; if (cursor_offset.x < state->ScrollX) state->ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x); - else if (cursor_offset.x - size.x >= state->ScrollX) - state->ScrollX = (float)(int)(cursor_offset.x - size.x + scroll_increment_x); + else if (cursor_offset.x - inner_size.x >= state->ScrollX) + state->ScrollX = (float)(int)(cursor_offset.x - inner_size.x + scroll_increment_x); } else { @@ -4021,8 +4024,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ float scroll_y = draw_window->Scroll.y; if (cursor_offset.y - g.FontSize < scroll_y) scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); - else if (cursor_offset.y - size.y >= scroll_y) - scroll_y = cursor_offset.y - size.y; + else if (cursor_offset.y - inner_size.y >= scroll_y) + scroll_y = cursor_offset.y - inner_size.y; draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag draw_window->Scroll.y = scroll_y; } @@ -4093,7 +4096,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { // Render text only (no selection, no cursor) if (is_multiline) - text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width + text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width else if (!is_displaying_hint && g.ActiveId == id) buf_display_end = buf_display + state->CurLenA; else if (!is_displaying_hint) From 323412dd23bb414c8885ee545a5ca0aaa3a40e84 Mon Sep 17 00:00:00 2001 From: Harris Brakmic Date: Sun, 6 Oct 2019 13:02:01 +0200 Subject: [PATCH 144/200] Examples: Allegro5: updated build instructions for macOS --- examples/example_allegro5/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/example_allegro5/README.md b/examples/example_allegro5/README.md index 5ef455576fe6d..10d9d6e94e6f2 100644 --- a/examples/example_allegro5/README.md +++ b/examples/example_allegro5/README.md @@ -9,12 +9,14 @@ Note that the back-end supports _BOTH_ 16-bit and 32-bit indices, but 32-bit ind # How to Build -### On Ubuntu 14.04+ +### On Ubuntu 14.04+ and macOS ```bash -g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. main.cpp ../imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_primitives -o allegro5_example +g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. main.cpp ../imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_main -lallegro_primitives -o allegro5_example ``` +On macOS, install Allegro with homebrew: `brew install allegro`. + ### On Windows with Visual Studio's CLI You may install Allegro using vcpkg: From 8aad3482a412af966082c297d5c7f05e070b7d98 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 Oct 2019 17:22:55 +0200 Subject: [PATCH 145/200] ImVector: Fixed index_from_ptr() not asserting when passed end() element. --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index a7e5fd7ebddd3..1db78b4a60145 100644 --- a/imgui.h +++ b/imgui.h @@ -1276,7 +1276,7 @@ struct ImVector inline const T* find(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } inline bool find_erase(const T& v) { const T* it = find(v); if (it < Data + Size) { erase(it); return true; } return false; } inline bool find_erase_unsorted(const T& v) { const T* it = find(v); if (it < Data + Size) { erase_unsorted(it); return true; } return false; } - inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; return (int)off; } + inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; return (int)off; } }; //----------------------------------------------------------------------------- From 3b271b1847f0cf159cfd0dfeaa171034fcab2507 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 Oct 2019 17:52:31 +0200 Subject: [PATCH 146/200] Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 47 +++++++++++++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e1cd2ad9c64e3..64bbe6bde3e76 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -40,6 +40,7 @@ Other Changes: - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) +- Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] ----------------------------------------------------------------------- diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 036d90688de72..0eeec9801fbf8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1506,24 +1506,21 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Drag and Drop")) { + if (ImGui::TreeNode("Drag and drop in standard widgets")) { // ColorEdit widgets automatically act as drag source and drag target. // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo. - ImGui::BulletText("Drag and drop in standard widgets"); - ImGui::SameLine(); HelpMarker("You can drag from the colored squares."); - ImGui::Indent(); - static float col1[3] = { 1.0f,0.0f,0.2f }; - static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; + static float col1[3] = { 1.0f, 0.0f, 0.2f }; + static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; ImGui::ColorEdit3("color 1", col1); ImGui::ColorEdit4("color 2", col2); - ImGui::Unindent(); + ImGui::TreePop(); } + if (ImGui::TreeNode("Drag and drop to copy/swap items")) { - ImGui::BulletText("Drag and drop to copy/swap items"); - ImGui::Indent(); enum Mode { Mode_Copy, @@ -1577,7 +1574,31 @@ static void ShowDemoWindowWidgets() } ImGui::PopID(); } - ImGui::Unindent(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Drag to reorder items (simple)")) + { + // Simple reordering + HelpMarker("We don't use the drag and drop api at all here! Instead we query when the item is held but not hovered, and order items accordingly."); + static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" }; + for (int n = 0; n < IM_ARRAYSIZE(item_names); n++) + { + const char* item = item_names[n]; + ImGui::Selectable(item); + + if (ImGui::IsItemActive() && !ImGui::IsItemHovered()) + { + int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1); + if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names)) + { + item_names[n] = item_names[n_next]; + item_names[n_next] = item; + ImGui::ResetMouseDragDelta(); + } + } + } + ImGui::TreePop(); } ImGui::TreePop(); @@ -1607,10 +1628,10 @@ static void ShowDemoWindowWidgets() if (item_type == 10){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. if (item_type == 11){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } - // Display the value of IsItemHovered() and other common item state functions. + // Display the value of IsItemHovered() and other common item state functions. // Note that the ImGuiHoveredFlags_XXX flags can be combined. - // Because BulletText is an item itself and that would affect the output of IsItemXXX functions, - // we query every state in a single call to avoid storing them and to simplify the code + // Because BulletText is an item itself and that would affect the output of IsItemXXX functions, + // we query every state in a single call to avoid storing them and to simplify the code ImGui::BulletText( "Return value = %d\n" "IsItemFocused() = %d\n" @@ -1653,7 +1674,7 @@ static void ShowDemoWindowWidgets() if (embed_all_inside_a_child_window) ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true); - // Testing IsWindowFocused() function with its various flags. + // Testing IsWindowFocused() function with its various flags. // Note that the ImGuiFocusedFlags_XXX flags can be combined. ImGui::BulletText( "IsWindowFocused() = %d\n" From 927472f5ff978bcc9f67708316481a3fcae4c04d Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 Oct 2019 19:14:08 +0200 Subject: [PATCH 147/200] Combo: Added _NoMove flag to prevent window from docking, which has an effect in Docking branch (in Master was not noticeable as the Combo code kept repositioning the window). (#2835) --- imgui_widgets.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1561c157460a3..0da7353e2719d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1505,8 +1505,10 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF SetNextWindowPos(pos); } + // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() + ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; + // Horizontally align ourselves with the framed text - ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y)); bool ret = Begin(name, NULL, window_flags); PopStyleVar(); From bf746c4215b92b764a7101b8673d24beb3e0c996 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 11 Oct 2019 12:03:43 +0200 Subject: [PATCH 148/200] DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the datato clarify how they are used, and more comments redirecting to the demo code. (#2844) --- docs/CHANGELOG.txt | 2 + imgui.h | 14 ++-- imgui_internal.h | 10 +-- imgui_widgets.cpp | 158 +++++++++++++++++++++++---------------------- 4 files changed, 96 insertions(+), 88 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 64bbe6bde3e76..1d8e7e790421a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -40,6 +40,8 @@ Other Changes: - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) +- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data + to clarify how they are used, and more comments redirecting to the demo code. (#2844) - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] diff --git a/imgui.h b/imgui.h index 1db78b4a60145..1675fc6c65f6f 100644 --- a/imgui.h +++ b/imgui.h @@ -438,8 +438,8 @@ namespace ImGui IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL); - IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f); - IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f); + IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, float power = 1.0f); + IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, float power = 1.0f); // Widgets: Sliders // - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds. @@ -453,11 +453,11 @@ namespace ImGui IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d"); IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d"); IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d"); - IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); - IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); + IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f); + IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f); IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* 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* format = "%d"); - IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); + IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f); // Widgets: Input with Keyboard // - If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h @@ -474,8 +474,8 @@ namespace ImGui IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* v, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. diff --git a/imgui_internal.h b/imgui_internal.h index df96fd8bce3b5..201a071c162f9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1666,8 +1666,8 @@ namespace ImGui // Widgets low-level behaviors IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); - IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags); - IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); + IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, float power, ImGuiDragFlags flags); + IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging @@ -1683,13 +1683,13 @@ namespace ImGui // Data type helpers IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); - IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format); + IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); - IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format); + IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format); // InputText IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); + IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format); inline bool TempInputTextIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputTextId == id); } // Color diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0da7353e2719d..a92eb5a99f414 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1680,25 +1680,25 @@ const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type) return &GDataTypeInfo[data_type]; } -int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) +int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format) { // Signedness doesn't matter when pushing integer arguments if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) - return ImFormatString(buf, buf_size, format, *(const ImU32*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data); if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) - return ImFormatString(buf, buf_size, format, *(const ImU64*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data); if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, format, *(const float*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const float*)p_data); if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, format, *(const double*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const double*)p_data); if (data_type == ImGuiDataType_S8) - return ImFormatString(buf, buf_size, format, *(const ImS8*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data); if (data_type == ImGuiDataType_U8) - return ImFormatString(buf, buf_size, format, *(const ImU8*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data); if (data_type == ImGuiDataType_S16) - return ImFormatString(buf, buf_size, format, *(const ImS16*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data); if (data_type == ImGuiDataType_U16) - return ImFormatString(buf, buf_size, format, *(const ImU16*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data); IM_ASSERT(0); return 0; } @@ -1755,7 +1755,7 @@ void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* // User can input math operators (e.g. +100) to edit a numerical values. // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. -bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format) +bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format) { while (ImCharIsBlankA(*buf)) buf++; @@ -1781,7 +1781,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b int data_backup[2]; const ImGuiDataTypeInfo* type_info = ImGui::DataTypeGetInfo(data_type); IM_ASSERT(type_info->Size <= sizeof(data_backup)); - memcpy(data_backup, data_ptr, type_info->Size); + memcpy(data_backup, p_data, type_info->Size); if (format == NULL) format = type_info->ScanFmt; @@ -1790,7 +1790,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b int arg1i = 0; if (data_type == ImGuiDataType_S32) { - int* v = (int*)data_ptr; + int* v = (int*)p_data; int arg0i = *v; float arg1f = 0.0f; if (op && sscanf(initial_value_buf, format, &arg0i) < 1) @@ -1805,7 +1805,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b { // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in format = "%f"; - float* v = (float*)data_ptr; + float* v = (float*)p_data; float arg0f = *v, arg1f = 0.0f; if (op && sscanf(initial_value_buf, format, &arg0f) < 1) return false; @@ -1819,7 +1819,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b else if (data_type == ImGuiDataType_Double) { format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis - double* v = (double*)data_ptr; + double* v = (double*)p_data; double arg0f = *v, arg1f = 0.0; if (op && sscanf(initial_value_buf, format, &arg0f) < 1) return false; @@ -1834,7 +1834,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b { // All other types assign constant // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future. - sscanf(buf, format, data_ptr); + sscanf(buf, format, p_data); } else { @@ -1842,18 +1842,18 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b int v32; sscanf(buf, format, &v32); if (data_type == ImGuiDataType_S8) - *(ImS8*)data_ptr = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX); + *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX); else if (data_type == ImGuiDataType_U8) - *(ImU8*)data_ptr = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX); + *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX); else if (data_type == ImGuiDataType_S16) - *(ImS16*)data_ptr = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX); + *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX); else if (data_type == ImGuiDataType_U16) - *(ImU16*)data_ptr = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX); + *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX); else IM_ASSERT(0); } - return memcmp(data_backup, data_ptr, type_info->Size) != 0; + return memcmp(data_backup, p_data, type_info->Size) != 0; } static float GetMinimumStepAtDecimalPrecision(int decimal_precision) @@ -2023,7 +2023,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const return true; } -bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags) +bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, float power, ImGuiDragFlags flags) { ImGuiContext& g = *GImGui; if (g.ActiveId == id) @@ -2038,30 +2038,32 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_s switch (data_type) { - case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, v_min ? *(const ImS8*) v_min : IM_S8_MIN, v_max ? *(const ImS8*)v_max : IM_S8_MAX, format, power, flags); if (r) *(ImS8*)v = (ImS8)v32; return r; } - case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, v_min ? *(const ImU8*) v_min : IM_U8_MIN, v_max ? *(const ImU8*)v_max : IM_U8_MAX, format, power, flags); if (r) *(ImU8*)v = (ImU8)v32; return r; } - case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, v_min ? *(const ImS16*)v_min : IM_S16_MIN, v_max ? *(const ImS16*)v_max : IM_S16_MAX, format, power, flags); if (r) *(ImS16*)v = (ImS16)v32; return r; } - case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, v_min ? *(const ImU16*)v_min : IM_U16_MIN, v_max ? *(const ImU16*)v_max : IM_U16_MAX, format, power, flags); if (r) *(ImU16*)v = (ImU16)v32; return r; } - case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power, flags); - case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power, flags); - case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power, flags); - case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power, flags); - case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power, flags); - case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)v, v_speed, v_min ? *(const double*)v_min : -DBL_MAX, v_max ? *(const double*)v_max : DBL_MAX, format, power, flags); + case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, power, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } + case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, power, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; } + case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, power, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; } + case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, power, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; } + case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, power, flags); + case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, power, flags); + case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, power, flags); + case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, power, flags); + case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, power, flags); + case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, power, flags); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); return false; } -bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) +// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional. +// Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. +bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; if (power != 1.0f) - IM_ASSERT(v_min != NULL && v_max != NULL); // When using a power curve the drag needs to have known bounds + IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; @@ -2104,7 +2106,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa } } if (temp_input_is_active || temp_input_start) - return TempInputTextScalar(frame_bb, id, label, data_type, v, format); + return TempInputTextScalar(frame_bb, id, label, data_type, p_data, format); // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); @@ -2112,13 +2114,13 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); // Drag behavior - const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None); + const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, power, ImGuiDragFlags_None); if (value_changed) MarkItemEdited(id); // 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 + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); + const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); if (label_size.x > 0.0f) @@ -2128,7 +2130,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa return value_changed; } -bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min, const void* v_max, const char* format, float power) +bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2145,10 +2147,10 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int PushID(i); if (i > 0) SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragScalar("", data_type, v, v_speed, v_min, v_max, format, power); + value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, power); PopID(); PopItemWidth(); - v = (void*)((char*)v + type_size); + p_data = (void*)((char*)p_data + type_size); } PopID(); @@ -2474,39 +2476,41 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ // For 32-bits and larger types, slider bounds are limited to half the natural type range. // So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok. // It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders. -bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb) +bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb) { switch (data_type) { - case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)v_min, *(const ImS8*)v_max, format, power, flags, out_grab_bb); if (r) *(ImS8*)v = (ImS8)v32; return r; } - case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)v_min, *(const ImU8*)v_max, format, power, flags, out_grab_bb); if (r) *(ImU8*)v = (ImU8)v32; return r; } - case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)v_min, *(const ImS16*)v_max, format, power, flags, out_grab_bb); if (r) *(ImS16*)v = (ImS16)v32; return r; } - case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)v_min, *(const ImU16*)v_max, format, power, flags, out_grab_bb); if (r) *(ImU16*)v = (ImU16)v32; return r; } + case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } + case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; } + case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; } + case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; } case ImGuiDataType_S32: - IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2); - return SliderBehaviorT(bb, id, data_type, (ImS32*)v, *(const ImS32*)v_min, *(const ImS32*)v_max, format, power, flags, out_grab_bb); + IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN/2 && *(const ImS32*)p_max <= IM_S32_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, power, flags, out_grab_bb); case ImGuiDataType_U32: - IM_ASSERT(*(const ImU32*)v_max <= IM_U32_MAX/2); - return SliderBehaviorT(bb, id, data_type, (ImU32*)v, *(const ImU32*)v_min, *(const ImU32*)v_max, format, power, flags, out_grab_bb); + IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, power, flags, out_grab_bb); case ImGuiDataType_S64: - IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2); - return SliderBehaviorT(bb, id, data_type, (ImS64*)v, *(const ImS64*)v_min, *(const ImS64*)v_max, format, power, flags, out_grab_bb); + IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN/2 && *(const ImS64*)p_max <= IM_S64_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, power, flags, out_grab_bb); case ImGuiDataType_U64: - IM_ASSERT(*(const ImU64*)v_max <= IM_U64_MAX/2); - return SliderBehaviorT(bb, id, data_type, (ImU64*)v, *(const ImU64*)v_min, *(const ImU64*)v_max, format, power, flags, out_grab_bb); + IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, power, flags, out_grab_bb); case ImGuiDataType_Float: - IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f); - return SliderBehaviorT(bb, id, data_type, (float*)v, *(const float*)v_min, *(const float*)v_max, format, power, flags, out_grab_bb); + IM_ASSERT(*(const float*)p_min >= -FLT_MAX/2.0f && *(const float*)p_max <= FLT_MAX/2.0f); + return SliderBehaviorT(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, power, flags, out_grab_bb); case ImGuiDataType_Double: - IM_ASSERT(*(const double*)v_min >= -DBL_MAX/2.0f && *(const double*)v_max <= DBL_MAX/2.0f); - return SliderBehaviorT(bb, id, data_type, (double*)v, *(const double*)v_min, *(const double*)v_max, format, power, flags, out_grab_bb); + IM_ASSERT(*(const double*)p_min >= -DBL_MAX/2.0f && *(const double*)p_max <= DBL_MAX/2.0f); + return SliderBehaviorT(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, power, flags, out_grab_bb); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); return false; } -bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power) +// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required. +// Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. +bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2553,7 +2557,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co } } if (temp_input_is_active || temp_input_start) - return TempInputTextScalar(frame_bb, id, label, data_type, v, format); + return TempInputTextScalar(frame_bb, id, label, data_type, p_data, format); // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); @@ -2562,7 +2566,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co // Slider behavior ImRect grab_bb; - const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_None, &grab_bb); + const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, power, ImGuiSliderFlags_None, &grab_bb); if (value_changed) MarkItemEdited(id); @@ -2572,7 +2576,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co // 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 + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); + const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); if (label_size.x > 0.0f) @@ -2668,7 +2672,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format); } -bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power) +bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2708,7 +2712,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d // Slider behavior ImRect grab_bb; - const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb); + const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb); if (value_changed) MarkItemEdited(id); @@ -2719,7 +2723,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding char value_buf[64]; - const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); + const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); @@ -2832,7 +2836,7 @@ int ImParseFormatPrecision(const char* fmt, int default_precision) // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets) // FIXME: Facilitate using this in variety of other situations. -bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format) +bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format) { ImGuiContext& g = *GImGui; @@ -2845,7 +2849,7 @@ bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, char fmt_buf[32]; char data_buf[32]; format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); - DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format); + DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); ImStrTrimBlanks(data_buf); g.CurrentWindow->DC.CursorPos = bb.Min; @@ -2860,14 +2864,16 @@ bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, } if (value_changed) { - value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL); + value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); if (value_changed) MarkItemEdited(id); } return value_changed; } -bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags) +// Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. +// Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. +bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2880,7 +2886,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p format = DataTypeGetInfo(data_type)->PrintFmt; char buf[64]; - DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); + DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); bool value_changed = false; if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) @@ -2888,7 +2894,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p flags |= ImGuiInputTextFlags_AutoSelectAll; flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselve by comparing the actual data rather than the string. - if (step != NULL) + if (p_step != NULL) { const float button_size = GetFrameHeight(); @@ -2896,7 +2902,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p PushID(label); SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view - value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format); + value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); // Step buttons const ImVec2 backup_frame_padding = style.FramePadding; @@ -2907,13 +2913,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) { - DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); + DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); value_changed = true; } SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("+", ImVec2(button_size, button_size), button_flags)) { - DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); + DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); value_changed = true; } @@ -2931,7 +2937,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p else { if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) - value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format); + value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); } if (value_changed) MarkItemEdited(window->DC.LastItemId); @@ -2939,7 +2945,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p return value_changed; } -bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags) +bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2956,10 +2962,10 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in PushID(i); if (i > 0) SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= InputScalar("", data_type, v, step, step_fast, format, flags); + value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags); PopID(); PopItemWidth(); - v = (void*)((char*)v + type_size); + p_data = (void*)((char*)p_data + type_size); } PopID(); From 378035c6ff4a0cbd92140a4b39e41dbd0ba915be Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Mon, 30 Sep 2019 21:16:30 -0700 Subject: [PATCH 149/200] Fixed backspace handling on MacOS (fixed https://github.com/ocornut/imgui/issues/2817). Allow null view passing as parameter to ImGui_ImplOSX_NewFrame --- examples/imgui_impl_osx.h | 2 +- examples/imgui_impl_osx.mm | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/imgui_impl_osx.h b/examples/imgui_impl_osx.h index 66df252767388..fe066eec4bf8a 100644 --- a/examples/imgui_impl_osx.h +++ b/examples/imgui_impl_osx.h @@ -13,5 +13,5 @@ IMGUI_API bool ImGui_ImplOSX_Init(); IMGUI_API void ImGui_ImplOSX_Shutdown(); -IMGUI_API void ImGui_ImplOSX_NewFrame(NSView *_Nonnull view); +IMGUI_API void ImGui_ImplOSX_NewFrame(NSView *_Nullable view); IMGUI_API bool ImGui_ImplOSX_HandleEvent(NSEvent *_Nonnull event, NSView *_Nullable view); diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index 9042e15f9807f..fd548bf6ce584 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -150,9 +150,12 @@ void ImGui_ImplOSX_NewFrame(NSView* view) { // Setup display size ImGuiIO& io = ImGui::GetIO(); - const float dpi = [view.window backingScaleFactor]; - io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height); - io.DisplayFramebufferScale = ImVec2(dpi, dpi); + if (view) + { + const float dpi = [view.window backingScaleFactor]; + io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height); + io.DisplayFramebufferScale = ImVec2(dpi, dpi); + } // Setup time step if (g_Time == 0.0) @@ -250,7 +253,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) for (int i = 0; i < len; i++) { int c = [str characterAtIndex:i]; - if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF)) + if (!io.KeyCtrl && !((c >= 0xF700 && c <= 0xFFFF) || c == 127)) io.AddInputCharacter((unsigned int)c); // We must reset in case we're pressing a sequence of special keys while keeping the command pressed From fc10ba8d24ddc8b43d46d6c75b586ed75cdfb6b4 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 11 Oct 2019 14:20:04 +0200 Subject: [PATCH 150/200] Amend f0238ece9cba67ecabef438008fea53682bd6bc7 (#2817, #2818) --- docs/CHANGELOG.txt | 1 + examples/imgui_impl_osx.mm | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1d8e7e790421a..734920389d489 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,7 @@ Other Changes: - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data to clarify how they are used, and more comments redirecting to the demo code. (#2844) - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] +- Backends: OSX: Fix using Backspace key. (#2817, #2818) [@DiligentGraphics] ----------------------------------------------------------------------- diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index fd548bf6ce584..a491616a587c5 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -14,7 +14,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2019-07-21: Readded clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change). +// 2019-10-11: Inputs: Fix using Backspace key. +// 2019-07-21: Re-added clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change). // 2019-05-28: Inputs: Added mouse cursor shape and visibility support. // 2019-05-18: Misc: Removed clipboard handlers as they are now supported by core imgui.cpp. // 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range. @@ -40,13 +41,13 @@ bool ImGui_ImplOSX_Init() ImGuiIO& io = ImGui::GetIO(); // Setup back-end capabilities flags - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) //io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy) io.BackendPlatformName = "imgui_impl_osx"; - // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array. const int offset_for_function_keys = 256 - 0xF700; io.KeyMap[ImGuiKey_Tab] = '\t'; io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys; @@ -232,7 +233,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) } } else - #endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + #endif // MAC_OS_X_VERSION_MAX_ALLOWED { wheel_dx = [event deltaX]; wheel_dy = [event deltaY]; @@ -253,7 +254,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) for (int i = 0; i < len; i++) { int c = [str characterAtIndex:i]; - if (!io.KeyCtrl && !((c >= 0xF700 && c <= 0xFFFF) || c == 127)) + if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF) && c != 127) io.AddInputCharacter((unsigned int)c); // We must reset in case we're pressing a sequence of special keys while keeping the command pressed From aeb64814995d624f6b3c2122d9e8312474e168f6 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 12 Oct 2019 14:25:18 +0200 Subject: [PATCH 151/200] InputText: Filter out Ascii 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) --- docs/CHANGELOG.txt | 3 ++- imgui_widgets.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 734920389d489..1ec907e8a9ad9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -38,12 +38,13 @@ Breaking Changes: Other Changes: - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) +- InputText: Filter out Ascii 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data to clarify how they are used, and more comments redirecting to the demo code. (#2844) - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] -- Backends: OSX: Fix using Backspace key. (#2817, #2818) [@DiligentGraphics] +- Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] ----------------------------------------------------------------------- diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a92eb5a99f414..a1560a2c36734 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3331,6 +3331,10 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f return false; } + // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) + if (c == 127) + return false; + // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME) if (c >= 0xE000 && c <= 0xF8FF) return false; From cba84df7b59b0e181d53ca18721184391fa208f9 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 12 Oct 2019 17:05:08 +0200 Subject: [PATCH 152/200] Update README.md --- docs/README.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/README.md b/docs/README.md index 7d29ace914276..373f498fd9ea0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -97,7 +97,7 @@ Dear ImGui allows you **create elaborate tools** as well as very short-lived one ### How it works -Check out the [References](#references) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. +Check out the Wiki's [About the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#About-the-IMGUI-paradigm) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes required to render them is fairly small. Because Dear ImGui doesn't know or touch graphics state directly, you can call its functions anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. @@ -192,17 +192,11 @@ Custom engine [Tracy Profiler](https://bitbucket.org/wolfpld/tracy) ![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/tracy_profiler.png) -### References +### Wiki -The Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because "Retained Mode" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works. -- [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html). -- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf). -- [Jari Komppa's tutorial on building an IMGUI library](http://iki.fi/sol/imgui/). -- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861). -- [Nicolas Guillemot's CppCon'16 flash-talk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k). -- [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/). +See [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles. -See the [Wiki](https://github.com/ocornut/imgui/wiki) for more references and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks. +See [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#Articles-about-the-IMGUI-paradigm) to read/watch about the Immediate Mode GUI paradigm. ### Support, Frequently Asked Questions (FAQ) @@ -210,7 +204,7 @@ If you are new to Dear ImGui and have issues with: compiling, linking, adding fo Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. -Private support is available for paying customers. +Paid private support is available for business customers (E-mail: _contact @ dearimgui dot org_). **Where is the documentation?** From 1c73a0c17e02d44d3a814c477b9badf00c9913dd Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 12 Oct 2019 17:18:44 +0200 Subject: [PATCH 153/200] Bindings --- docs/README.md | 51 +++++++++----------------------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/docs/README.md b/docs/README.md index 373f498fd9ea0..4a0d75de599da 100644 --- a/docs/README.md +++ b/docs/README.md @@ -122,52 +122,19 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ _NB: third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users!). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ -Officially maintained bindings in repository: +Officially maintained bindings (in repository): - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. - Platforms: GLFW, SDL2, Win32, Glut, OSX. - Others: Allegro5, Marmalade. -Third-party - Languages bindings: -- C: [cimgui](https://github.com/cimgui/cimgui) (auto-generated! **you can use its json output to generate bindings for other languages**) -- C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) -- ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) -- D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui) -- Go: [imgui-go](https://github.com/inkyblackness/imgui-go) or [go-imgui](https://github.com/Armored-Dragon/go-imgui) -- Haxe/hxcpp: [linc_imgui](https://github.com/Aidan63/linc_imgui) -- Java: [jimgui](https://github.com/ice1000/jimgui) -- JavaScript: [imgui-js](https://github.com/flyover/imgui-js) -- Julia: [CImGui.jl](https://github.com/Gnimuc/CImGui.jl) -- Lua: [LuaJIT-ImGui](https://github.com/sonoro1234/LuaJIT-ImGui), [imgui_lua_bindings](https://github.com/patrickriordan/imgui_lua_bindings) or [lua-ffi-bindings](https://github.com/thenumbernine/lua-ffi-bindings) -- Odin: [odin-dear_imgui](https://github.com/ThisDrunkDane/odin-dear_imgui) -- Pascal: [imgui-pas](https://github.com/dpethes/imgui-pas) -- PureBasic: [pb-cimgui](https://github.com/hippyau/pb-cimgui) -- Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy) or [ogre-imgui](https://github.com/OGRECave/ogre-imgui) -- Ruby: [ruby-imgui](https://github.com/vaiorabbit/ruby-imgui) -- Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) or [imgui-rust](https://github.com/nsf/imgui-rust) -- Swift: [swift-imgui](https://github.com/mnmly/Swift-imgui) - -Third-party - Engines/Frameworks bindings: -- bsf: [bsfimgui](https://github.com/pgruenbacher/bsfImgui) -- Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) -- Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551) -- Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI) -- GML/GameMakerStudio2: [ImGuiGML](https://marketplace.yoyogames.com/assets/6221/imguigml) -- Irrlicht: [IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI) -- Ogre: [ogre-imgui](https://github.com/OGRECave/ogre-imgui) -- OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui) -- OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c) -- ORX: [ImGuiOrx](https://github.com/thegwydd/ImGuiOrx), [#1843](https://github.com/ocornut/imgui/pull/1843) -- px_render: [px_render_imgui.h](https://github.com/pplux/px/blob/master/px_render_imgui.h), [#1935](https://github.com/ocornut/imgui/pull/1935) -- LÖVE+Lua: [love-imgui](https://github.com/slages/love-imgui) -- Magnum: [ImGuiIntegration](https://doc.magnum.graphics/magnum/namespaceMagnum_1_1ImGuiIntegration.html) ([example](https://doc.magnum.graphics/magnum/examples-imgui.html)) -- NanoRT: [syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort) -- Qt: [imgui-qt3d](https://github.com/alpqr/imgui-qt3d) / [QOpenGLWindow (qtimgui)](https://github.com/ocornut/imgui/issues/1910) / [QtDirect3D](https://github.com/giladreich/QtDirect3D) / [qt6](https://github.com/alpqr/qvk6/tree/imgui/examples/rhi/imguidemo) -- SFML: [imgui-sfml](https://github.com/eliasdaler/imgui-sfml) -- Software renderer: [imgui_software_renderer](https://github.com/emilk/imgui_software_renderer) -- Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) -- Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) - -For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/). Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. +Third-party Languages bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): +- C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +- The C ([cimgui](https://github.com/cimgui/cimgui)) bindings are auto-generated, **you can use its json output to generate bindings for other languages**. + +Third-party Engines/Frameworks bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): +- bsf, Cinder, Cocos2d-x, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... + +Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. ### Upcoming Changes From 58411033e262dde5be104f617495389f0cb01f67 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 12 Oct 2019 17:21:11 +0200 Subject: [PATCH 154/200] Bindings --- docs/README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4a0d75de599da..cb7a50befb750 100644 --- a/docs/README.md +++ b/docs/README.md @@ -120,19 +120,15 @@ On most platforms and when using C++, **you should be able to use a combination Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the FAQ, comments, and one of the examples/ application!** -_NB: third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users!). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ - Officially maintained bindings (in repository): - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. - Platforms: GLFW, SDL2, Win32, Glut, OSX. -- Others: Allegro5, Marmalade. - -Third-party Languages bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): -- C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- The C ([cimgui](https://github.com/cimgui/cimgui)) bindings are auto-generated, **you can use its json output to generate bindings for other languages**. +- Frameworks: Allegro5, Marmalade. -Third-party Engines/Frameworks bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): -- bsf, Cinder, Cocos2d-x, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): +- Languages: C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +- Frameworks: bsf, Cinder, Cocos2d-x, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +- Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. From 23eabd5991a23eee18de35d73ee6017a9a9d1a2f Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 12 Oct 2019 17:41:56 +0200 Subject: [PATCH 155/200] Emscripten --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index cb7a50befb750..98972a8d5c383 100644 --- a/docs/README.md +++ b/docs/README.md @@ -123,7 +123,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ Officially maintained bindings (in repository): - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. - Platforms: GLFW, SDL2, Win32, Glut, OSX. -- Frameworks: Allegro5, Marmalade. +- Frameworks: Emscripten, Allegro5, Marmalade. Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): - Languages: C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... From 8c4dcbfa45cd3669d0bdf56c517ef2b875528172 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 12 Oct 2019 17:56:32 +0200 Subject: [PATCH 156/200] Diligent Engine --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 98972a8d5c383..c2d42591e3a8e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -127,7 +127,7 @@ Officially maintained bindings (in repository): Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): - Languages: C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- Frameworks: bsf, Cinder, Cocos2d-x, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +- Frameworks: bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. From 67e4cd5cc6ce1432ddf574b25008fce16ea1f5ed Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 14 Oct 2019 14:08:56 +0200 Subject: [PATCH 157/200] Comments, some logging for NavInitRequest debugging Moved OpenPopupOnItemClick() next to BeginPopupContextItem() --- docs/README.md | 2 +- imgui.cpp | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index c2d42591e3a8e..2cb47404eed0a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -127,7 +127,7 @@ Officially maintained bindings (in repository): Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): - Languages: C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- Frameworks: bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +- Frameworks: Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. diff --git a/imgui.cpp b/imgui.cpp index 7bf2bf597e439..59f6fa82299e5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -955,9 +955,6 @@ CODE - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug". - - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle - of a deep nested inner loop in your code. - - tip: you can call Render() multiple times (e.g for VR renders). - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui! */ @@ -7511,19 +7508,6 @@ void ImGui::OpenPopupEx(ImGuiID id) } } -bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - { - ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! - IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - OpenPopupEx(id); - return true; - } - return false; -} - void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup) { ImGuiContext& g = *GImGui; @@ -7693,6 +7677,19 @@ void ImGui::EndPopup() End(); } +bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + { + ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! + IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) + OpenPopupEx(id); + return true; + } + return false; +} + // This is a helper to handle the simplest case of associating one named popup to one given widget. // You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). // You can pass a NULL str_id to use the identifier of the last item. @@ -8181,6 +8178,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) init_for_nav = true; + //IMGUI_DEBUG_LOG("[Nav] NavInitWindow() init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer); if (init_for_nav) { SetNavID(0, g.NavLayer); @@ -8297,6 +8295,7 @@ static void ImGui::NavUpdate() if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove) && g.NavWindow) { // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) + //IMGUI_DEBUG_LOG("[Nav] Apply NavInitRequest result: 0x%08X Layer %d in \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name); if (g.NavInitRequestFromMove) SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); else @@ -8455,6 +8454,7 @@ static void ImGui::NavUpdate() } if (g.NavMoveRequest && g.NavId == 0) { + //IMGUI_DEBUG_LOG("[Nav] NavInitRequest from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer); g.NavInitRequest = g.NavInitRequestFromMove = true; g.NavInitResultId = 0; g.NavDisableHighlight = false; From c7bdec7e18801efe300ab46ccacc44f10f8bb3f7 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 14 Oct 2019 22:43:04 +0200 Subject: [PATCH 158/200] InputText, Nav: Fixed Left!Right keys broken when activating Keyboard Navigation. (#787) Amend 892dfb1 --- imgui_internal.h | 2 +- imgui_widgets.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 201a071c162f9..83b66955d836d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1648,7 +1648,7 @@ namespace ImGui IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - // 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while. + // [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while] inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); } inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); } #endif diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a1560a2c36734..a955daad58bc4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3523,6 +3523,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Declare our inputs IM_ASSERT(ImGuiNavInput_COUNT < 32); + g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); From a41f0b2df47193c3c755f0703dfba85c4baec253 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 14 Oct 2019 23:07:06 +0200 Subject: [PATCH 159/200] Inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. IMPORTANT: Renamed internal CalcTypematicPressedRepeatAmount to CalcTypematicRepeatAmount and reordered the t1, t0 arguments to t0, t1 !! If you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix. The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). Fixed the code and altered default io.KeyRepeatRate,Delay from 0.250,0.050 to 0.300,0.050 to compensate. If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. --- docs/CHANGELOG.txt | 11 +++++++++-- imgui.cpp | 34 +++++++++++++++++++++++----------- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1ec907e8a9ad9..16d53e0219d95 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,11 +34,18 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Breaking Changes: -- +- Inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used + by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. + If you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can + add +io.KeyRepeatDelay to it to compensate for the fix. + The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). + Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). + Fixed the code and altered default io.KeyRepeatRate,Delay from 0.250,0.050 to 0.300,0.050 to compensate. + If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. Other Changes: - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) -- InputText: Filter out Ascii 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) +- InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data diff --git a/imgui.cpp b/imgui.cpp index 59f6fa82299e5..03ad95fdc0e6d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -369,6 +369,10 @@ CODE When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. + if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix. + The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). + If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names. @@ -1206,7 +1210,7 @@ ImGuiIO::ImGuiIO() MouseDoubleClickMaxDist = 6.0f; for (int i = 0; i < ImGuiKey_COUNT; i++) KeyMap[i] = -1; - KeyRepeatDelay = 0.250f; + KeyRepeatDelay = 0.275f; KeyRepeatRate = 0.050f; UserData = NULL; @@ -4402,14 +4406,22 @@ bool ImGui::IsKeyDown(int user_key_index) return g.IO.KeysDown[user_key_index]; } -int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate) +// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) +// t1 = current time (e.g.: g.Time) +// An event is triggered at: +// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N +int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate) { - if (t == 0.0f) + if (t1 == 0.0f) return 1; - if (t <= repeat_delay || repeat_rate <= 0.0f) + if (t0 >= t1) return 0; - const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate); - return (count > 0) ? count : 0; + if (repeat_rate <= 0.0f) + return (t0 < repeat_delay) && (t1 >= repeat_delay); + const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate); + const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate); + const int count = count_t1 - count_t0; + return count; } int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) @@ -4419,7 +4431,7 @@ int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_r return 0; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); const float t = g.IO.KeysDownDuration[key_index]; - return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate); + return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate); } bool ImGui::IsKeyPressed(int user_key_index, bool repeat) @@ -4471,7 +4483,7 @@ bool ImGui::IsMouseClicked(int button, bool repeat) if (repeat && t > g.IO.KeyRepeatDelay) { // FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold. - int amount = CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.5f); + int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f); if (amount > 0) return true; } @@ -8228,11 +8240,11 @@ float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. return (t == 0.0f) ? 1.0f : 0.0f; if (mode == ImGuiInputReadMode_Repeat) - return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); + return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.80f); if (mode == ImGuiInputReadMode_RepeatSlow) - return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f); + return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f); if (mode == ImGuiInputReadMode_RepeatFast) - return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f); + return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f); return 0.0f; } diff --git a/imgui_internal.h b/imgui_internal.h index 83b66955d836d..e7868613f81cb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1581,7 +1581,7 @@ namespace ImGui IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); - IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); + IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void SetNavID(ImGuiID id, int nav_layer); IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a955daad58bc4..b2398a00fcb0d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -487,7 +487,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { hovered = true; SetHoveredID(id); - if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy + if (CalcTypematicRepeatAmount(g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, g.HoveredIdTimer + 0.0001f, 0.70f, 0.00f)) { pressed = true; FocusWindow(window); From c21fdabb438f611f263d264f14fcd021df531bb4 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 15 Oct 2019 13:00:04 +0200 Subject: [PATCH 160/200] Doc: Readme: moving contents to FAQ. --- docs/README.md | 97 ++++++++---------- imgui.cpp | 265 ++++++++----------------------------------------- 2 files changed, 82 insertions(+), 280 deletions(-) diff --git a/docs/README.md b/docs/README.md index 2cb47404eed0a..1991b9547e356 100644 --- a/docs/README.md +++ b/docs/README.md @@ -118,7 +118,7 @@ The demo applications are not DPI aware so expect some blurriness on a 4K screen On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/examples) files without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom binding using your custom engine functions if you wish so. -Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the FAQ, comments, and one of the examples/ application!** +Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://github.com/ocornut/imgui/wiki/FAQ), comments, and one of the examples/ application!** Officially maintained bindings (in repository): - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. @@ -144,7 +144,7 @@ Some of the goals for 2019 are: ### Gallery -For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/2529)! +For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/2847)! Custom engine [![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) @@ -155,79 +155,62 @@ Custom engine [Tracy Profiler](https://bitbucket.org/wolfpld/tracy) ![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/tracy_profiler.png) -### Wiki - -See [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles. - -See [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#Articles-about-the-IMGUI-paradigm) to read/watch about the Immediate Mode GUI paradigm. - ### Support, Frequently Asked Questions (FAQ) -If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org). - -Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. - -Paid private support is available for business customers (E-mail: _contact @ dearimgui dot org_). +Most common questions will be answered by the [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/wiki/FAQ) page, e.g.: -**Where is the documentation?** +**Basics** +- "Where is the documentation?" +- "Which version should I get?" +- "Why the names "Dear ImGui" vs "ImGui"?" - This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. - - Run the examples/ applications and explore them. - - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. - - The demo covers most features of Dear ImGui, so you can read the code and see its output. - - See documentation and comments at the top of imgui.cpp + effectively imgui.h. - - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application. - - Your programming IDE is your friend, find the type or function declaration to find comments associated with it. - - We obviously need better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. +**Community** +- "How can I help?" -**Which version should I get?** +**Concerns** +- "Who uses Dear ImGui?" +- "Can you create elaborate/serious tools with Dear ImGui?" +- "Can you reskin the look of Dear ImGui?" +- "Why using C++ (as opposed to C)?" -I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. +**Integration** +- "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?" +- "How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)" +- "I integrated Dear ImGui in my engine and the text or lines are blurry.." +- "I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.." -You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features in the `docking` branch. Many projects are using this branch and it is kept in sync with master regularly. +**Usage** +- "Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label?" +- "How can I display an image? What is ImTextureID, how does it work?" +- "How can I use my own math types instead of ImVec2/ImVec4?" +- "How can I interact with standard C++ types (such as std::string and std::vector)?" +- "How can I use low-level drawing facilities? (using ImDrawList API)" -**Who uses Dear ImGui?** +**Fonts, Text** +- "How can I load a different font than the default?" +- "How can I easily use icons in my application?" +- "How can I load multiple fonts?" +- "How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?" -See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! +See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles. -**Why the odd dual naming, "Dear ImGui" vs "ImGui"?** +See: [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#Articles-about-the-IMGUI-paradigm) to read/learn about the Immediate Mode GUI paradigm. -The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses its own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui". - -**How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?** -
**How can I display an image? What is ImTextureID, how does it works?** ([examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples)) -
**Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...** -
**How can I use my own math types instead of ImVec2/ImVec4?** -
**How can I load a different font than the default?** -
**How can I easily use icons in my application?** -
**How can I load multiple fonts?** -
**How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?** ([examples](https://github.com/ocornut/imgui/wiki/Loading-Font-Example)) -
**How can I interact with standard C++ types (such as std::string and std::vector)?** -
**How can I use the drawing facilities without a Dear ImGui window? (using ImDrawList API)** -
**How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)** -
**I integrated Dear ImGui in my engine and the text or lines are blurry..** -
**I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..** -
**How can I help?** - -See the FAQ in [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for answers. - -**Can you create elaborate/serious tools with Dear ImGui?** - -Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. +If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org). -Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. +Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. -**Can you reskin the look of Dear ImGui?** +Paid private support is available for business customers (E-mail: _contact @ dearimgui dot org_). -You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Below is a screenshot from [LumixEngine](https://github.com/nem0/LumixEngine) with custom colors + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged): +**Which version should I get?** -![LumixEngine](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/lumix-201710-rearranged.png) +I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. -**Why using C++ (as opposed to C)?** +You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features in the `docking` branch. Many projects are using this branch and it is kept in sync with master regularly. -Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. +**Who uses Dear ImGui?** -There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings. +See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! Also see the [Gallery Threads](https://github.com/ocornut/imgui/issues/2847)! How to help ----------- diff --git a/imgui.cpp b/imgui.cpp index 03ad95fdc0e6d..390f555fa2cc6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6,7 +6,7 @@ // Get latest version at https://github.com/ocornut/imgui // Releases change-log at https://github.com/ocornut/imgui/releases // Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started -// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2529 +// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2847 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). @@ -36,7 +36,8 @@ DOCUMENTATION - This is how a simple rendering function may look like. - Using gamepad/keyboard navigation controls. - API BREAKING CHANGES (read me when you update!) -- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS +- FREQUENTLY ASKED QUESTIONS (FAQ) + - All answers in https://github.com/ocornut/imgui/wiki/FAQ - Where is the documentation? - Which version should I get? - Who uses Dear ImGui? @@ -576,6 +577,13 @@ CODE FREQUENTLY ASKED QUESTIONS (FAQ), TIPS ====================================== + All answers in: https://github.com/ocornut/imgui/wiki/FAQ + Some answers are copied down here to facilitate searching in code or because they are most likely to + be varying depending on your version of the code. + + Q&A: Basics + =========== + Q: Where is the documentation? A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. - Run the examples/ and explore them. @@ -588,26 +596,20 @@ CODE associated to it. Q: Which version should I get? - A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe - and recommended to sync to master/latest. The library is fairly stable and regressions tend to be - fixed fast when reported. You may also peak at the 'docking' branch which includes: - - Docking/Merging features (https://github.com/ocornut/imgui/issues/2109) - - Multi-viewport features (https://github.com/ocornut/imgui/issues/1542) - Many projects are using this branch and it is kept in sync with master regularly. + Q: Why the names "Dear ImGui" vs "ImGui"? + A: See https://github.com/ocornut/imgui/wiki/FAQ + + Q&A: Concerns + ============= Q: Who uses Dear ImGui? - A: See "Quotes" (https://github.com/ocornut/imgui/wiki/Quotes) and - "Software using Dear ImGui" (https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages - for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! - - Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"? - A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when - when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI - (immediate-mode graphical user interface) was coined before and is being used in variety of other - situations (e.g. Unity uses it own implementation of the IMGUI paradigm). - To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, - longer name "Dear ImGui" that people can use to refer to this specific library. - Please try to refer to this library as "Dear ImGui". + Q: Can you create elaborate/serious tools with Dear ImGui? + Q: Can you reskin the look of Dear ImGui? + Q: Why using C++ (as opposed to C)? + A: See https://github.com/ocornut/imgui/wiki/FAQ + + Q&A: Integration + ================ Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application? A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } ) @@ -623,76 +625,14 @@ CODE Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) + + Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) + Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. + Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + A: See https://github.com/ocornut/imgui/wiki/FAQ - Q: How can I display an image? What is ImTextureID, how does it works? - A: Short explanation: - - Please read Wiki entry for examples: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - - You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures. - - Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value. - - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason). - Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward. - - Long explanation: - - Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. - At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code - to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.). - - Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API. - We carry the information to identify a "texture" in the ImTextureID type. - ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice. - Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function. - - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying - an image from the end-user perspective. This is what the _examples_ rendering functions are using: - - OpenGL: ImTextureID = GLuint (see ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp) - DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp) - DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp) - DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp) - - For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID. - Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure - tying together both the texture and information about its format and how to read it. - - If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about - the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase - is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them. - If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID - representation suggested by the example bindings is probably the best choice. - (Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer) - - User code may do: - - // Cast our texture type to ImTextureID / void* - MyTexture* texture = g_CoffeeTableTexture; - ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height)); - - The renderer function called after ImGui::Render() will receive that same value that the user code passed: - - // Cast ImTextureID / void* stored in the draw command as our texture type - MyTexture* texture = (MyTexture*)pcmd->TextureId; - MyEngineBindTexture2D(texture); - - Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. - This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them. - If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using. - - Refer to the Wiki to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11: - - https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - - C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa. - Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*. - Examples: - - GLuint my_tex = XXX; - void* my_void_ptr; - my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer) - my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint - - ID3D11ShaderResourceView* my_dx11_srv = XXX; - void* my_void_ptr; - my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void* - my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView* - - Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated. + Q&A: Usage + ---------- Q: Why are multiple widgets reacting when I interact with a single one? Q: How can I have multiple widgets with the same label or with an empty label? @@ -810,141 +750,25 @@ CODE e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. See what makes more sense in your situation! + Q: How can I display an image? What is ImTextureID, how does it works? + A: See https://github.com/ocornut/imgui/wiki/FAQ and https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples + Q: How can I use my own math types instead of ImVec2/ImVec4? - A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions. - This way you'll be able to use your own types everywhere, e.g. passing glm::vec2 to ImGui functions instead of ImVec2. + Q: How can I interact with standard C++ types (such as std::string and std::vector)? + Q: How can I use low-level drawing facilities? (using ImDrawList API) + A: See https://github.com/ocornut/imgui/wiki/FAQ - Q: How can I load a different font than the default? - A: Use the font atlas to load the TTF/OTF file you want: - ImGuiIO& io = ImGui::GetIO(); - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); - io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code. - (Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.) - (Read the 'misc/fonts/README.txt' file for more details about font loading.) - - New programmers: remember that in C/C++ and most programming languages if you want to use a - backslash \ within a string literal, you need to write it double backslash "\\": - io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG (you are escape the M here!) - io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT - io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT + Q&A: Fonts, Text + ================ + Q: How can I load a different font than the default? Q: How can I easily use icons in my application? - A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you - main font. Then you can refer to icons within your strings. - You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment. - (Read the 'misc/fonts/README.txt' file for more details about icons font loading.) - With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas, - and copying your own graphics data into it. See misc/fonts/README.txt about using the AddCustomRectFontGlyph API. - Q: How can I load multiple fonts? - A: Use the font atlas to pack them into a single texture: - (Read the 'misc/fonts/README.txt' file and the code in ImFontAtlas for more details.) - - ImGuiIO& io = ImGui::GetIO(); - ImFont* font0 = io.Fonts->AddFontDefault(); - ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); - ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels); - io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - // the first loaded font gets used by default - // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime - - // Options - ImFontConfig config; - config.OversampleH = 2; - config.OversampleV = 1; - config.GlyphOffset.y -= 1.0f; // Move everything by 1 pixels up - config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config); - - // Combine multiple fonts into one (e.g. for icon fonts) - static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 }; - ImFontConfig config; - config.MergeMode = true; - io.Fonts->AddFontDefault(); - io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs - Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. - - // Add default Japanese ranges - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); - - // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need) - ImVector ranges; - ImFontGlyphRangesBuilder builder; - builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters) - builder.AddChar(0x7262); // Add a specific character - builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges - builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); - - All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 - by using the u8"hello" syntax. Specifying literal in your source code using a local code page - (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! - Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - - Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter(). - The applications in examples/ are doing that. - Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). - You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state. - Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for - the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly. + A: See https://github.com/ocornut/imgui/wiki/FAQ and misc/fonts/README.txt - Q: How can I interact with standard C++ types (such as std::string and std::vector)? - A: - Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers), - and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use - any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases. - - To use ImGui::InputText() with a std::string or any resizable string class, see misc/cpp/imgui_stdlib.h. - - To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API - lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API. - Prefer using them over the old and awkward Combo()/ListBox() api. - - Generally for most high-level types you should be able to access the underlying data type. - You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code). - - Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass - to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application. - Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances. - Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those - are not configurable and not the same across implementations. - - If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount - of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern - is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead. - One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str - This is a small helper where you can instance strings with configurable local buffers length. Many game engines will - provide similar or better string helpers. - - Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - A: - You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags. - (The ImGuiWindowFlags_NoDecoration flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse) - Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - - You can call ImGui::GetBackgroundDrawList() or ImGui::GetForegroundDrawList() and use those draw list to display - contents behind or over every other imgui windows (one bg/fg drawlist per viewport). - - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create - your own ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data. - - Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) - A: - You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls". - (short version: map gamepad inputs into the io.NavInputs[] array + set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad) - - You can share your computer mouse seamlessly with your console/tablet/phone using Synergy (https://symless.com/synergy) - This is the preferred solution for developer productivity. - In particular, the "micro-synergy-client" repository (https://github.com/symless/micro-synergy-client) has simple - and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect - to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer. - Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols. - - You may also use a third party solution such as Remote ImGui (https://github.com/JordiRos/remoteimgui) which sends - the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine. - - For touch inputs, you can increase the hit box of widgets (via the style.TouchPadding setting) to accommodate - for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing - for screen real-estate and precision. - - Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. - A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). - Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. - - Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: You are probably mishandling the clipping rectangles in your render function. - Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). + Q&A: Community + ============== Q: How can I help? A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt @@ -952,15 +776,10 @@ CODE - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui. - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README. - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1902). Visuals are ideal as they inspire other programmers. + You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/2847). Visuals are ideal as they inspire other programmers. But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). - - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. - this is also useful to set yourself in the context of another window (to get/set other settings) - - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug". - - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui! - */ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) From 6892b8157825e69a3c426b4d49842a0a96ef82c8 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 15 Oct 2019 16:20:27 +0300 Subject: [PATCH 161/200] Remove trailing spaces from bunch of files. (cherry picked from commit 50e0f8d4ddf4c426f62f346c8260a927f6b7c779) --- examples/example_glfw_opengl2/main.cpp | 4 ++-- examples/example_glfw_vulkan/main.cpp | 4 ++-- examples/example_sdl_directx11/main.cpp | 2 +- examples/example_sdl_opengl2/main.cpp | 2 +- examples/example_sdl_opengl3/main.cpp | 2 +- examples/example_sdl_vulkan/main.cpp | 4 ++-- examples/imgui_impl_opengl3.cpp | 4 ++-- examples/imgui_impl_opengl3.h | 4 ++-- examples/imgui_impl_vulkan.cpp | 2 +- examples/imgui_impl_vulkan.h | 8 ++++---- imgui.cpp | 4 ++-- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index 0a7aa3c3fc419..4b4a5fe3ba659 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -134,9 +134,9 @@ int main(int, char**) glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); - // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), + // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), // you may need to backup/reset/restore current shader using the commented lines below. - //GLint last_program; + //GLint last_program; //glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); //glUseProgram(0); ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index fc3c1efb1bb26..fb92bad8330fd 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -4,7 +4,7 @@ // Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. // - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h. // You will use those if you want to use this rendering back-end in your engine/app. -// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by +// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by // the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code. // Read comments in imgui_impl_vulkan.h. @@ -194,7 +194,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) } } -// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. +// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. // Your real engine/app may not use them. static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height) { diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl_directx11/main.cpp index 680f179e72204..b6345bd1773ea 100644 --- a/examples/example_sdl_directx11/main.cpp +++ b/examples/example_sdl_directx11/main.cpp @@ -26,7 +26,7 @@ void CleanupRenderTarget(); int main(int, char**) { // Setup SDL - // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index 9bc88d90baefa..9a0f07c614490 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -17,7 +17,7 @@ int main(int, char**) { // Setup SDL - // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index 1641546593356..03cd3a7bdd907 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -27,7 +27,7 @@ int main(int, char**) { // Setup SDL - // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, + // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems, // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 12c262e9a32e7..1969b45252eb7 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -4,7 +4,7 @@ // Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. // - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h. // You will use those if you want to use this rendering back-end in your engine/app. -// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by +// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by // the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code. // Read comments in imgui_impl_vulkan.h. @@ -186,7 +186,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) } } -// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. +// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. // Your real engine/app may not use them. static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height) { diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index e1eee236850b2..d7b108ef36281 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -159,9 +159,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) strcpy(g_GlslVersionString, glsl_version); strcat(g_GlslVersionString, "\n"); - // Dummy construct to make it easily visible in the IDE and debugger which GL loader has been selected. + // Dummy construct to make it easily visible in the IDE and debugger which GL loader has been selected. // The code actually never uses the 'gl_loader' variable! It is only here so you can read it! - // If auto-detection fails or doesn't select the same GL loader file as used by your application, + // If auto-detection fails or doesn't select the same GL loader file as used by your application, // you are likely to get a crash below. // You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. const char* gl_loader = "Unknown"; diff --git a/examples/imgui_impl_opengl3.h b/examples/imgui_impl_opengl3.h index 1cb790b164fe5..75f8f8c8f6474 100644 --- a/examples/imgui_impl_opengl3.h +++ b/examples/imgui_impl_opengl3.h @@ -40,8 +40,8 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android // Desktop OpenGL: attempt to detect default GL loader based on available header files. -// If auto-detection fails or doesn't select the same GL loader file as used by your application, -// you are likely to get a crash in ImGui_ImplOpenGL3_Init(). +// If auto-detection fails or doesn't select the same GL loader file as used by your application, +// you are likely to get a crash in ImGui_ImplOpenGL3_Init(). // You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. #if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \ && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 9d977f0056597..2b8a3702c0f03 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -16,7 +16,7 @@ // Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. // - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h. // You will use those if you want to use this rendering back-end in your engine/app. -// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by +// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by // the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code. // Read comments in imgui_impl_vulkan.h. diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index f2bf92938b07d..5b0bd7b3127cf 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -16,7 +16,7 @@ // Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. // - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h. // You will use those if you want to use this rendering back-end in your engine/app. -// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by +// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by // the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code. // Read comments in imgui_impl_vulkan.h. @@ -116,9 +116,9 @@ struct ImGui_ImplVulkanH_Window ImGui_ImplVulkanH_Frame* Frames; ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; - ImGui_ImplVulkanH_Window() - { - memset(this, 0, sizeof(*this)); + ImGui_ImplVulkanH_Window() + { + memset(this, 0, sizeof(*this)); PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; ClearEnable = true; } diff --git a/imgui.cpp b/imgui.cpp index 390f555fa2cc6..fc15533393c2b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2327,7 +2327,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis - + if (ellipsis_char_count > 1) { // Full ellipsis size without free spacing after it. @@ -2335,7 +2335,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots; } - + // We can now claim the space between pos_max.x and ellipsis_max.x const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f); float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; From 9d6b2b096b20fa654c84fd8bb4d9631c250b33d6 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 15 Oct 2019 15:48:46 +0300 Subject: [PATCH 162/200] Ignore directories created by JetBrains IDEs. (cherry picked from commit c470de572c2f63e7ba5eeb7d97bc1f4bc114b375) --- examples/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/.gitignore b/examples/.gitignore index d56b94f0dba6d..2b5671a8672a4 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -40,3 +40,7 @@ example_sdl_opengl3/example_sdl_opengl3 ## Dear ImGui Ini files imgui.ini + +## JetBrains IDEs +.idea +cmake-build-* From 5fc427a49e1f2935b26e211ddcd5b9c32e3eee61 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 16 Oct 2019 11:03:41 +0200 Subject: [PATCH 163/200] Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. (#2848) --- docs/CHANGELOG.txt | 2 + docs/FAQ.md | 510 +++++++++++++++++++++++++++++++++++++++++++++ imgui.cpp | 52 ++--- 3 files changed, 528 insertions(+), 36 deletions(-) create mode 100644 docs/FAQ.md diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 16d53e0219d95..ee9fcdd2e18a4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,8 @@ Other Changes: incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data to clarify how they are used, and more comments redirecting to the demo code. (#2844) +- Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut] +- Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] diff --git a/docs/FAQ.md b/docs/FAQ.md new file mode 100644 index 0000000000000..9fc3623488e1b --- /dev/null +++ b/docs/FAQ.md @@ -0,0 +1,510 @@ +# FAQ (Frequenty Asked Questions) + +You may browse this document at: + https://github.com/ocornut/imgui/blob/master/docs/FAQ.md +or use any Markdown viewer. + + +## Index + +| **Q&A: Basics** | +:---------------------------------------------------------- | +| [Where is the documentation?](#q-where-is-the-documentation) | +| [Which version should I get?](#q-which-version-should-i-get) | +| [Why the names "Dear ImGui" vs "ImGui"?](#q-why-names-dear-imgui-vs-imgui) | +| **Q&A: Concerns** | +| [Who uses Dear ImGui?](#q-who-uses-dear-imgui) | +| [Can you create elaborate/serious tools with Dear ImGui?](#q-can-you-create-elaborateserious-tools-with-dear-imgui) | +| [Can you reskin the look of Dear ImGui?](#q-can-you-reskin-the-look-of-dear-imgui) | +| [Why using C++ (as opposed to C)?](#q-why-using-c-as-opposed-to-c) | +| **Q&A: Integration** | +| [How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-to-my-application) | +| [How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)](#q-how-can-i-use-this-without-a-mouse-without-a-keyboard-or-without-a-screen-gamepad-input-share-remote-display) | +| [I integrated Dear ImGui in my engine and the text or lines are blurry..](#q-i-integrated-dear-imgui-in-my-engine-and-the-text-or-lines-are-blurry) | +| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) | +| **Q&A: Usage** | +| [Why are multiple widgets reacting when I interact with a single one?
How can I have multiple widgets with the same label or with an empty label?](#q-why-are-multiple-widgets-reacting-when-i-interact-with-a-single-one-q-how-can-i-have-multiple-widgets-with-the-same-label-or-with-an-empty-label) | +| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| +| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) | +| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) | +| [How can I use low-level drawing facilities? (using ImDrawList API)](#q-how-can-i-use-low-level-drawing-facilities-using-imdrawlist-api) | +| **Q&A: Fonts, Text** | +| [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default) | +| [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) | +| [How can I load multiple fonts?](#q-how-can-i-load-multiple-fonts) | +| [How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?](#q-how-can-i-display-and-input-non-latin-characters-such-as-chinese-japanese-korean-cyrillic) | +| **Q&A: Community** | +| [How can I help?](#q-how-can-i-help) | + + +# Q&A: Basics + +### Q: Where is the documentation? + +**This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.** +- Run the examples/ and explore them. +- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. +- The demo covers most features of Dear ImGui, so you can read the code and see its output. +- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h). +- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. +- Your programming IDE is your friend, find the type or function declaration to find comments associated to it. + +--- + +### Q: Which version should I get? +I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. + +You may also peak at the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes: +- [Docking/Merging features](https://github.com/ocornut/imgui/issues/2109) +- [Multi-viewport features](https://github.com/ocornut/imgui/issues/1542) + +Many projects are using this branch and it is kept in sync with master regularly. + +--- + +### Q: Why the names "Dear ImGui" vs "ImGui"? + +**TL;DR: Please try to refer to this library as "Dear ImGui".** + +The library started its life as "ImGui" due to the fact that I didn't give it a proper name when when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. + +##### [Return to Index](#index) + + +# Q&A: Concerns + +### Q: Who uses Dear ImGui? + +You may take a look at: + +- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) +- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) +- [Gallery](https://github.com/ocornut/imgui/issues/2847) + +### Q: Can you create elaborate/serious tools with Dear ImGui? + +Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. + +Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. + +Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm. + +### Q: Can you reskin the look of Dear ImGui? + +Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it. + +A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119)) +![minipars](https://user-images.githubusercontent.com/314805/63589441-d9794f00-c5b1-11e9-8d96-cfc1b93702f7.png) + +### Q: Why using C++ (as opposed to C)? + +Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. + +There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings. + +##### [Return to Index](#index) + + +# Q&A: Integration + +### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application? + +You can read the `io.WantCaptureMouse`, `io.WantCaptureKeyboard` and `io.WantTextInput` flags from the ImGuiIO structure. + +e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }` + +- When `io.WantCaptureMouse` is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application. +- When `io.WantCaptureKeyboard` is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application. +- When `io.WantTextInput` is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS). + +**Note:** You should always pass your mouse/keyboard inputs to Dear ImGui, even when the io.WantCaptureXXX flag are set false. + This is because imgui needs to detect that you clicked in the void to unfocus its own windows. + +**Note:** The `io.WantCaptureMouse` is more accurate that any manual attempt to "check if the mouse is hovering a window" (don't do that!). It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. Those flags are updated by `ImGui::NewFrame()`. Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to `UpdateHoveredWindowAndCaptureFlags()`. + +**Note:** Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have `io.WantCaptureKeyboard == false`. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) + +--- + +### Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) +- You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls". +(short version: map gamepad inputs into the io.NavInputs[] array + set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad`). +- You can share your computer mouse seamlessly with your console/tablet/phone using [Synergy](https://symless.com/synergy) +This is the preferred solution for developer productivity. +In particular, the [micro-synergy-client repository](https://github.com/symless/micro-synergy-client) has simple +and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect +to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer. +Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols. +- You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui) or [imgui-ws](https://github.com/ggerganov/imgui-ws) which sends the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine. See Wiki index for most details. +- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate +for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing +for screen real-estate and precision. + +--- + +### Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. +In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). +Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. + +--- + +### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. +You are probably mishandling the clipping rectangles in your render function. +Rectangles provided by ImGui are defined as +`(x1=left,y1=top,x2=right,y2=bottom)` +and **NOT** as +`(x1,y1,width,height)` + +##### [Return to Index](#index) + + +# Q&A: Usage + +### Q: Why are multiple widgets reacting when I interact with a single one?
Q: How can I have multiple widgets with the same label or with an empty label? + +A primer on labels and the ID Stack... + +Dear ImGui internally need to uniquely identify UI elements. +Elements that are typically not clickable (such as calls to the Text functions) don't need an ID. +Interactive widgets (such as calls to Button buttons) need a unique ID. +Unique ID are used internally to track active widgets and occasionally associate state to widgets. +Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element. + +- Unique ID are often derived from a string label: +```c +Button("OK"); // Label = "OK", ID = hash of (..., "OK") +Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel") +``` +- ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having +two buttons labeled "OK" in different windows or different tree locations is fine. +We used "..." above to signify whatever was already pushed to the ID stack previously: +```c +Begin("MyWindow"); +Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK") +End(); +Begin("MyOtherWindow"); +Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK") +End(); +``` +- If you have a same ID twice in the same location, you'll have a conflict: +```c +Button("OK"); +Button("OK"); // ID collision! Interacting with either button will trigger the first one. +``` +Fear not! this is easy to solve and there are many ways to solve it! + +- Solving ID conflict in a simple/local context: +When passing a label you can optionally specify extra ID information within string itself. +Use "##" to pass a complement to the ID that won't be visible to the end-user. +This helps solving the simple collision cases when you know e.g. at compilation time which items +are going to be created: +```c +Begin("MyWindow"); +Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play") +Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above +Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above +End(); +``` +- If you want to completely hide the label, but still need an ID: +```c +Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox! +``` +- Occasionally/rarely you might want change a label while preserving a constant ID. This allows +you to animate labels. For example you may want to include varying information in a window title bar, +but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID: +```c +Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID") +Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same as above, even if the label looks different + +sprintf(buf, "My game (%f FPS)###MyGame", fps); +Begin(buf); // Variable title, ID = hash of "MyGame" +``` +- Solving ID conflict in a more general manner: +Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts +within the same window. This is the most convenient way of distinguishing ID when iterating and +creating many UI elements programmatically. +You can push a pointer, a string or an integer value into the ID stack. +Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack. +At each level of the stack we store the seed used for items at this level of the ID stack. +```c +Begin("Window"); +for (int i = 0; i < 100; i++) +{ + PushID(i); // Push i to the id tack + Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click") + PopID(); +} +for (int i = 0; i < 100; i++) +{ + MyObject* obj = Objects[i]; + PushID(obj); + Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click") + PopID(); +} +for (int i = 0; i < 100; i++) +{ + MyObject* obj = Objects[i]; + PushID(obj->Name); + Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click") + PopID(); +} +End(); +``` +- You can stack multiple prefixes into the ID stack: +```c +Button("Click"); // Label = "Click", ID = hash of (..., "Click") +PushID("node"); + Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") + PushID(my_ptr); + Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click") + PopID(); +PopID(); +``` +- Tree nodes implicitly creates a scope for you by calling PushID(). +```c +Button("Click"); // Label = "Click", ID = hash of (..., "Click") +if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag) +{ + Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") + TreePop(); +} +``` +- When working with trees, ID are used to preserve the open/close state of each tree node. +Depending on your use cases you may want to use strings, indices or pointers as ID. +e.g. when following a single pointer that may change over time, using a static string as ID +will preserve your node open/closed state when the targeted object change. +e.g. when displaying a list of objects, using indices or pointers as ID will preserve the +node open/closed state differently. See what makes more sense in your situation! + +--- + +### Q: How can I display an image? What is ImTextureID, how does it work? + +Short explanation: +- Please read Wiki entry for examples: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples +- You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures. +- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value. +- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason). + +**Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.** + +Long explanation: +- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.). +- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API. + We carry the information to identify a "texture" in the ImTextureID type. +ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice. +Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function. +- In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using: +``` +OpenGL: +- ImTextureID = GLuint +- See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp + +DirectX9: +- ImTextureID = LPDIRECT3DTEXTURE9 +- See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp + +DirectX11: +- ImTextureID = ID3D11ShaderResourceView* +- See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp + +DirectX12: +- ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE +- See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp +``` +For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID. +Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure tying together both the texture and information about its format and how to read it. + +- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them. +If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID representation suggested by the example bindings is probably the best choice. +(Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer) + +User code may do: +```cpp +// Cast our texture type to ImTextureID / void* +MyTexture* texture = g_CoffeeTableTexture; +ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height)); +``` +The renderer function called after ImGui::Render() will receive that same value that the user code passed: +```cpp +// Cast ImTextureID / void* stored in the draw command as our texture type +MyTexture* texture = (MyTexture*)pcmd->TextureId; +MyEngineBindTexture2D(texture); +``` +Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. +This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them. +If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using. + +Refer to the Wiki to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples + +C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa. +Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*. +Examples: +```cpp +GLuint my_tex = XXX; +void* my_void_ptr; +my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer) +my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint + +ID3D11ShaderResourceView* my_dx11_srv = XXX; +void* my_void_ptr; +my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void* +my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView* +``` +Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated. + +--- + +### Q: How can I use my own math types instead of ImVec2/ImVec4? + +You can edit [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions. +This way you'll be able to use your own types everywhere, e.g. passing MyVector2 or glm::vec2 to ImGui functions instead of ImVec2. + +--- + +### Q: How can I interact with standard C++ types (such as std::string and std::vector)? +- Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers), and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases. +- To use ImGui::InputText() with a std::string or any resizable string class, see [misc/cpp/imgui_stdlib.h](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.h). +- To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API +lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API. +Prefer using them over the old and awkward Combo()/ListBox() api. +- Generally for most high-level types you should be able to access the underlying data type. +You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code). +- Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass +to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application. +Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances. +Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those +are not configurable and not the same across implementations. +- If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount +of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern +is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead. +One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str +This is a small helper where you can instance strings with configurable local buffers length. Many game engines will +provide similar or better string helpers. + +--- + +### Q: How can I use low-level drawing facilities? (using ImDrawList API) +- You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags. +(The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse) +Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. +- You can call `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` and use those draw list to display +contents behind or over every other imgui windows (one bg/fg drawlist per viewport). +- You can create your own ImDrawList instance. You'll need to initialize them with ImGui::GetDrawListSharedData(), or create your own instancing ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data. + +##### [Return to Index](#index) + + +# Q&A: Fonts, Text + +### Q: How can I load a different font than the default? +Use the font atlas to load the TTF/OTF file you want: + +```c +ImGuiIO& io = ImGui::GetIO(); +io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); +io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() +``` + +Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code. + +(Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.) + +(Read the [misc/fonts/README.txt](https://github.com/ocornut/imgui/blob/master/misc/fonts/README.txt) file for more details about font loading.) + +New programmers: remember that in C/C++ and most programming languages if you want to use a +backslash \ within a string literal, you need to write it double backslash "\\": + +```c +io.Fonts->AddFontFromFileTTF("MyFolder\MyFont.ttf", size); // WRONG (you are escape the M here!) +io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size; // CORRECT +io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT +``` + +--- + +### Q: How can I easily use icons in my application? +The most convenient and practical way is to merge an icon font such as FontAwesome inside you +main font. Then you can refer to icons within your strings. +You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment. +(Read the [misc/fonts/README.txt](https://github.com/ocornut/imgui/blob/master/misc/fonts/README.txt) file for more details about icons font loading.) +With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas, +and copying your own graphics data into it. See misc/fonts/README.txt about using the AddCustomRectFontGlyph API. + +--- + +### Q: How can I load multiple fonts? +Use the font atlas to pack them into a single texture: +(Read the [misc/fonts/README.txt](https://github.com/ocornut/imgui/blob/master/misc/fonts/README.txt) file and the code in ImFontAtlas for more details.) + +```cpp +ImGuiIO& io = ImGui::GetIO(); +ImFont* font0 = io.Fonts->AddFontDefault(); +ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); +ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels); +io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() +// the first loaded font gets used by default +// use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime + +// Options +ImFontConfig config; +config.OversampleH = 2; +config.OversampleV = 1; +config.GlyphOffset.y -= 1.0f; // Move everything by 1 pixels up +config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters +io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config); + +// Combine multiple fonts into one (e.g. for icon fonts) +static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 }; +ImFontConfig config; +config.MergeMode = true; +io.Fonts->AddFontDefault(); +io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font +io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs +``` + +--- + +### Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? +When loading a font, pass custom Unicode ranges to specify the glyphs to load. + +```cpp +// Add default Japanese ranges +io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); + +// Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need) +ImVector ranges; +ImFontGlyphRangesBuilder builder; +builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters) +builder.AddChar(0x7262); // Add a specific character +builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges +builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) +io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 16.0f, NULL, ranges.Data); +``` + +All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 +by using the u8"hello" syntax. Specifying literal in your source code using a local code page +(such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! +Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. + +Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter(). +The applications in examples/ are doing that. +Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). +You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state. +Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for +the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly. + +##### [Return to Index](#index) + +# Q&A: Community + +### Q: How can I help? +- If you are experienced with Dear ImGui and C++, look at the [GitHub Issues](https://github.com/ocornut/imgui/issues), look at the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help! +- Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for Dear ImGui. With increased funding we will be able to hire more people working on this project. +- Individuals: you can also become a [Patron](http://www.patreon.com/imgui) or donate on PayPal! See README. +- Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. +You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/2847). Visuals are ideal as they inspire other programmers. +But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. +- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete pR. + +##### [Return to Index](#index) diff --git a/imgui.cpp b/imgui.cpp index fc15533393c2b..597e681c578e3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -28,7 +28,7 @@ DOCUMENTATION - MISSION STATEMENT - END-USER GUIDE -- PROGRAMMER GUIDE (read me!) +- PROGRAMMER GUIDE - Read first. - How to update to a newer version of Dear ImGui. - Getting started with integrating Dear ImGui in your code/engine. @@ -37,26 +37,7 @@ DOCUMENTATION - Using gamepad/keyboard navigation controls. - API BREAKING CHANGES (read me when you update!) - FREQUENTLY ASKED QUESTIONS (FAQ) - - All answers in https://github.com/ocornut/imgui/wiki/FAQ - - Where is the documentation? - - Which version should I get? - - Who uses Dear ImGui? - - Why the odd dual naming, "Dear ImGui" vs "ImGui"? - - How can I tell whether to dispatch mouse/keyboard to imgui or to my application? - - How can I display an image? What is ImTextureID, how does it works? - - Why are multiple widgets reacting when I interact with a single one? How can I have - multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack... - - How can I use my own math types instead of ImVec2/ImVec4? - - How can I load a different font than the default? - - How can I easily use icons in my application? - - How can I load multiple fonts? - - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - - How can I interact with standard C++ types (such as std::string and std::vector)? - - How can I use the drawing facilities without a Dear ImGui window? (using ImDrawList API) - - How can I use Dear ImGui on a platform that doesn't have a mouse or a keyboard? (input share, remoting, gamepad) - - I integrated Dear ImGui in my engine and the text or lines are blurry.. - - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - - How can I help? + - Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer) CODE (search for "[SECTION]" in the code to find them) @@ -138,7 +119,7 @@ CODE READ FIRST: - - Read the FAQ below this section! + - Remember to read the FAQ (https://www.dearimgui.org/faq) - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs. - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. @@ -235,7 +216,7 @@ CODE // At this point you've got the texture data and you need to upload that your your graphic system: // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'. - // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID. + // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ for details about ImTextureID. MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32) io.Fonts->TexID = (void*)texture; @@ -321,8 +302,8 @@ CODE - The examples/ folders contains many actual implementation of the pseudo-codes above. - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated. They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the - rest of your application. In every cases you need to pass on the inputs to Dear ImGui. Refer to the FAQ for more information. - - Please read the FAQ below!. Amusingly, it is called a FAQ because people frequently run into the same issues! + rest of your application. In every cases you need to pass on the inputs to Dear ImGui. + - Refer to the FAQ for more information. Amusingly, it is called a FAQ because people frequently run into the same issues! USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS @@ -574,12 +555,11 @@ CODE - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - ====================================== + FREQUENTLY ASKED QUESTIONS (FAQ) + ================================ - All answers in: https://github.com/ocornut/imgui/wiki/FAQ - Some answers are copied down here to facilitate searching in code or because they are most likely to - be varying depending on your version of the code. + Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer) + Some answers are copied down here to facilitate searching in code. Q&A: Basics =========== @@ -597,7 +577,7 @@ CODE Q: Which version should I get? Q: Why the names "Dear ImGui" vs "ImGui"? - A: See https://github.com/ocornut/imgui/wiki/FAQ + >> See https://www.dearimgui.org/faq Q&A: Concerns ============= @@ -606,7 +586,7 @@ CODE Q: Can you create elaborate/serious tools with Dear ImGui? Q: Can you reskin the look of Dear ImGui? Q: Why using C++ (as opposed to C)? - A: See https://github.com/ocornut/imgui/wiki/FAQ + >> See https://www.dearimgui.org/faq Q&A: Integration ================ @@ -629,7 +609,7 @@ CODE Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: See https://github.com/ocornut/imgui/wiki/FAQ + >> See https://www.dearimgui.org/faq Q&A: Usage ---------- @@ -751,12 +731,12 @@ CODE node open/closed state differently. See what makes more sense in your situation! Q: How can I display an image? What is ImTextureID, how does it works? - A: See https://github.com/ocornut/imgui/wiki/FAQ and https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples + >> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples Q: How can I use my own math types instead of ImVec2/ImVec4? Q: How can I interact with standard C++ types (such as std::string and std::vector)? Q: How can I use low-level drawing facilities? (using ImDrawList API) - A: See https://github.com/ocornut/imgui/wiki/FAQ + >> See https://www.dearimgui.org/faq Q&A: Fonts, Text ================ @@ -765,7 +745,7 @@ CODE Q: How can I easily use icons in my application? Q: How can I load multiple fonts? Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - A: See https://github.com/ocornut/imgui/wiki/FAQ and misc/fonts/README.txt + >> See https://www.dearimgui.org/faq and misc/fonts/README.txt Q&A: Community ============== From 3bbc27ebd98771edad15f5be200510c2ef8445c2 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 16 Oct 2019 11:23:15 +0200 Subject: [PATCH 164/200] Fixed more FAQ links. (#2848) --- docs/FAQ.md | 36 ++++++++++++++++--------------- docs/README.md | 2 +- docs/issue_template.md | 12 +++++------ examples/imgui_impl_allegro5.cpp | 2 +- examples/imgui_impl_allegro5.h | 2 +- examples/imgui_impl_dx10.cpp | 2 +- examples/imgui_impl_dx10.h | 2 +- examples/imgui_impl_dx11.cpp | 2 +- examples/imgui_impl_dx11.h | 2 +- examples/imgui_impl_dx12.cpp | 2 +- examples/imgui_impl_dx12.h | 2 +- examples/imgui_impl_dx9.cpp | 2 +- examples/imgui_impl_dx9.h | 2 +- examples/imgui_impl_marmalade.cpp | 2 +- examples/imgui_impl_marmalade.h | 2 +- examples/imgui_impl_metal.h | 2 +- examples/imgui_impl_metal.mm | 2 +- examples/imgui_impl_opengl2.cpp | 2 +- examples/imgui_impl_opengl2.h | 2 +- examples/imgui_impl_opengl3.cpp | 2 +- examples/imgui_impl_opengl3.h | 2 +- misc/fonts/README.txt | 2 +- 22 files changed, 45 insertions(+), 43 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 9fc3623488e1b..6dfdb436be701 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,8 +1,10 @@ # FAQ (Frequenty Asked Questions) -You may browse this document at: +You may link to this document using short form: + https://www.dearimgui.org/faq +or its real address: https://github.com/ocornut/imgui/blob/master/docs/FAQ.md -or use any Markdown viewer. +or view this file with any Markdown viewer. ## Index @@ -24,13 +26,13 @@ or use any Markdown viewer. | [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) | | **Q&A: Usage** | | [Why are multiple widgets reacting when I interact with a single one?
How can I have multiple widgets with the same label or with an empty label?](#q-why-are-multiple-widgets-reacting-when-i-interact-with-a-single-one-q-how-can-i-have-multiple-widgets-with-the-same-label-or-with-an-empty-label) | -| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| +| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| | [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) | | [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) | | [How can I use low-level drawing facilities? (using ImDrawList API)](#q-how-can-i-use-low-level-drawing-facilities-using-imdrawlist-api) | | **Q&A: Fonts, Text** | | [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default) | -| [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) | +| [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) | | [How can I load multiple fonts?](#q-how-can-i-load-multiple-fonts) | | [How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?](#q-how-can-i-display-and-input-non-latin-characters-such-as-chinese-japanese-korean-cyrillic) | | **Q&A: Community** | @@ -52,7 +54,7 @@ or use any Markdown viewer. --- ### Q: Which version should I get? -I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. +I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. You may also peak at the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes: - [Docking/Merging features](https://github.com/ocornut/imgui/issues/2109) @@ -87,11 +89,11 @@ Yes. People have written game editors, data browsers, debuggers, profilers and a Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. -Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm. +Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm. ### Q: Can you reskin the look of Dear ImGui? -Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it. +Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it. A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119)) ![minipars](https://user-images.githubusercontent.com/314805/63589441-d9794f00-c5b1-11e9-8d96-cfc1b93702f7.png) @@ -110,7 +112,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci ### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application? You can read the `io.WantCaptureMouse`, `io.WantCaptureKeyboard` and `io.WantTextInput` flags from the ImGuiIO structure. - + e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }` - When `io.WantCaptureMouse` is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application. @@ -150,9 +152,9 @@ Also make sure your orthographic projection matrix and io.DisplaySize matches yo ### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. You are probably mishandling the clipping rectangles in your render function. -Rectangles provided by ImGui are defined as -`(x1=left,y1=top,x2=right,y2=bottom)` -and **NOT** as +Rectangles provided by ImGui are defined as +`(x1=left,y1=top,x2=right,y2=bottom)` +and **NOT** as `(x1,y1,width,height)` ##### [Return to Index](#index) @@ -282,7 +284,7 @@ node open/closed state differently. See what makes more sense in your situation! Short explanation: - Please read Wiki entry for examples: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples -- You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures. +- You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures. - Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value. - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason). @@ -294,21 +296,21 @@ Long explanation: We carry the information to identify a "texture" in the ImTextureID type. ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice. Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function. -- In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using: +- In the [examples/](https://github.com/ocornut/imgui/tree/master/examples) bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using: ``` OpenGL: - ImTextureID = GLuint - See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp -DirectX9: +DirectX9: - ImTextureID = LPDIRECT3DTEXTURE9 - See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp -DirectX11: +DirectX11: - ImTextureID = ID3D11ShaderResourceView* - See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp -DirectX12: +DirectX12: - ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE - See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp ``` @@ -331,7 +333,7 @@ The renderer function called after ImGui::Render() will receive that same value MyTexture* texture = (MyTexture*)pcmd->TextureId; MyEngineBindTexture2D(texture); ``` -Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. +Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them. If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using. diff --git a/docs/README.md b/docs/README.md index 1991b9547e356..50a50c9d8d663 100644 --- a/docs/README.md +++ b/docs/README.md @@ -157,7 +157,7 @@ Custom engine ### Support, Frequently Asked Questions (FAQ) -Most common questions will be answered by the [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/wiki/FAQ) page, e.g.: +Most common questions will be answered by the [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) page, e.g.: **Basics** - "Where is the documentation?" diff --git a/docs/issue_template.md b/docs/issue_template.md index 21f0c1a92db92..bd05f0a58c580 100644 --- a/docs/issue_template.md +++ b/docs/issue_template.md @@ -1,16 +1,16 @@ (Click "Preview" to turn any http URL into a clickable link) -1. PLEASE CAREFULLY READ: -https://github.com/ocornut/imgui/issues/2261 +1. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) -2. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/LOADING FONTS, please post on the "Getting Started" Discourse forum: -https://discourse.dearimgui.org +2. PLEASE CAREFULLY READ: https://github.com/ocornut/imgui/issues/2261 -3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1). +2. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use the [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forum](https://discourse.dearimgui.org/c/getting-started). + +3. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1) (2). 4. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. -5. Delete points 1-5 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. +5. Delete points 1-6 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. Thank you! diff --git a/examples/imgui_impl_allegro5.cpp b/examples/imgui_impl_allegro5.cpp index 525ad5c976e13..8cee95f0311a6 100644 --- a/examples/imgui_impl_allegro5.cpp +++ b/examples/imgui_impl_allegro5.cpp @@ -2,7 +2,7 @@ // (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.) // Implemented features: -// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Platform: Clipboard support (from Allegro 5.1.12) // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Issues: diff --git a/examples/imgui_impl_allegro5.h b/examples/imgui_impl_allegro5.h index bc995a5ace221..8b9a47d14dad8 100644 --- a/examples/imgui_impl_allegro5.h +++ b/examples/imgui_impl_allegro5.h @@ -2,7 +2,7 @@ // (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.) // Implemented features: -// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Platform: Clipboard support (from Allegro 5.1.12) // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Issues: diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index 6dec6147b4a9e..362756dbbecfb 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_dx10.h b/examples/imgui_impl_dx10.h index db156e17a2cf5..94e6db8070765 100644 --- a/examples/imgui_impl_dx10.h +++ b/examples/imgui_impl_dx10.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 197bbe02345e2..2b80f76641b93 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_dx11.h b/examples/imgui_impl_dx11.h index 1741a5d35c2df..5eee80d545f21 100644 --- a/examples/imgui_impl_dx11.h +++ b/examples/imgui_impl_dx11.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 3161d1837370a..6d6161a17e58d 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // Issues: // [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301 diff --git a/examples/imgui_impl_dx12.h b/examples/imgui_impl_dx12.h index 8ae75e532b83e..274c1c92b6edb 100644 --- a/examples/imgui_impl_dx12.h +++ b/examples/imgui_impl_dx12.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // Issues: // [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301 diff --git a/examples/imgui_impl_dx9.cpp b/examples/imgui_impl_dx9.cpp index 2ee76ca6fe4c8..82b96475144da 100644 --- a/examples/imgui_impl_dx9.cpp +++ b/examples/imgui_impl_dx9.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_dx9.h b/examples/imgui_impl_dx9.h index 1eaea87d33fbb..a0413e002048d 100644 --- a/examples/imgui_impl_dx9.h +++ b/examples/imgui_impl_dx9.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_marmalade.cpp b/examples/imgui_impl_marmalade.cpp index 497a5705e2f48..0675c6b4f0389 100644 --- a/examples/imgui_impl_marmalade.cpp +++ b/examples/imgui_impl_marmalade.cpp @@ -2,7 +2,7 @@ // Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui) // Implemented features: -// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID! // Missing features: // [ ] Renderer: Clipping rectangles are not honored. diff --git a/examples/imgui_impl_marmalade.h b/examples/imgui_impl_marmalade.h index 8a767f9da2109..01fbd0d284962 100644 --- a/examples/imgui_impl_marmalade.h +++ b/examples/imgui_impl_marmalade.h @@ -2,7 +2,7 @@ // Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui) // Implemented features: -// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID! // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. diff --git a/examples/imgui_impl_metal.h b/examples/imgui_impl_metal.h index 869c3e5235f6f..7fa558fa084cb 100644 --- a/examples/imgui_impl_metal.h +++ b/examples/imgui_impl_metal.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. OSX) // Implemented features: -// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_metal.mm b/examples/imgui_impl_metal.mm index f3f1b126ce2f2..9d1045f14a4cb 100644 --- a/examples/imgui_impl_metal.mm +++ b/examples/imgui_impl_metal.mm @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. OSX) // Implemented features: -// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_opengl2.cpp b/examples/imgui_impl_opengl2.cpp index fbe278c7f0697..a3496225bf766 100644 --- a/examples/imgui_impl_opengl2.cpp +++ b/examples/imgui_impl_opengl2.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. diff --git a/examples/imgui_impl_opengl2.h b/examples/imgui_impl_opengl2.h index 2e3271dcf55ba..009052d70998c 100644 --- a/examples/imgui_impl_opengl2.h +++ b/examples/imgui_impl_opengl2.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index d7b108ef36281..3824647aebb9b 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -4,7 +4,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/imgui_impl_opengl3.h b/examples/imgui_impl_opengl3.h index 75f8f8c8f6474..2d10ea30263b3 100644 --- a/examples/imgui_impl_opengl3.h +++ b/examples/imgui_impl_opengl3.h @@ -4,7 +4,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 39e0dd48dd3a8..4ddafe62afcb2 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -13,7 +13,7 @@ You may also load external .TTF/.OTF files. The files in this folder are suggested fonts, provided as a convenience. Fonts are rasterized in a single texture at the time of calling either of io.Fonts->GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). -Also read dear imgui FAQ in imgui.cpp! +Also read the FAQ: https://www.dearimgui.org/faq If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum: https://discourse.dearimgui.org/c/getting-started From 9994f5bcbed2649907ecc52be0010f8f3c9a697e Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 16 Oct 2019 11:28:45 +0200 Subject: [PATCH 165/200] Fixed more FAQ links, oops.. (#2848) --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 50a50c9d8d663..aaca0316462f3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -118,7 +118,7 @@ The demo applications are not DPI aware so expect some blurriness on a 4K screen On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/examples) files without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom binding using your custom engine functions if you wish so. -Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://github.com/ocornut/imgui/wiki/FAQ), comments, and one of the examples/ application!** +Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!** Officially maintained bindings (in repository): - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. @@ -134,7 +134,7 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. ### Upcoming Changes -Some of the goals for 2019 are: +Some of the goals for 2019+ are: - Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) From 53278be61f9ff67e43024032e1a3e155179b8c6a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 18 Oct 2019 12:54:30 +0200 Subject: [PATCH 166/200] FAQ, Readme. Use = {} instead of = { 0 }, wasn't problematic because they were all static variables or one stack array not read. But hey. --- docs/FAQ.md | 42 ++++++++++++++++++++++++++++-------- docs/README.md | 4 ++-- docs/TODO.txt | 1 + examples/imgui_impl_glfw.cpp | 2 +- examples/imgui_impl_osx.mm | 2 +- examples/imgui_impl_sdl.cpp | 2 +- imgui.cpp | 4 ++-- imgui_demo.cpp | 6 +++--- 8 files changed, 44 insertions(+), 19 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 6dfdb436be701..6430f67876c23 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -13,7 +13,7 @@ or view this file with any Markdown viewer. :---------------------------------------------------------- | | [Where is the documentation?](#q-where-is-the-documentation) | | [Which version should I get?](#q-which-version-should-i-get) | -| [Why the names "Dear ImGui" vs "ImGui"?](#q-why-names-dear-imgui-vs-imgui) | +| [Why the names "Dear ImGui" vs "ImGui"?](#q-why-the-names-dear-imgui-vs-imgui) | | **Q&A: Concerns** | | [Who uses Dear ImGui?](#q-who-uses-dear-imgui) | | [Can you create elaborate/serious tools with Dear ImGui?](#q-can-you-create-elaborateserious-tools-with-dear-imgui) | @@ -29,7 +29,7 @@ or view this file with any Markdown viewer. | [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| | [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) | | [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) | -| [How can I use low-level drawing facilities? (using ImDrawList API)](#q-how-can-i-use-low-level-drawing-facilities-using-imdrawlist-api) | +| [How can I display custom shapes? (using low-level ImDrawList API)](#q-how-can-i-display-custom-shapes-using-low-level-imdrawlist-api) | | **Q&A: Fonts, Text** | | [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default) | | [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) | @@ -386,13 +386,37 @@ provide similar or better string helpers. --- -### Q: How can I use low-level drawing facilities? (using ImDrawList API) -- You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags. -(The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse) -Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. -- You can call `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` and use those draw list to display -contents behind or over every other imgui windows (one bg/fg drawlist per viewport). -- You can create your own ImDrawList instance. You'll need to initialize them with ImGui::GetDrawListSharedData(), or create your own instancing ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data. +### Q: How can I display custom shapes? (using low-level ImDrawList API) + +- You can use the low-level `ImDrawList` api to render shapes within a window. + +``` +ImGui::Begin("My shapes"); + +ImDrawList* draw_list = ImGui::GetWindowDrawList(); + +// Get the current ImGui cursor position +ImVec2 p = ImGui::GetCursorScreenPos(); + +// Draw a red circle +draw_list->AddCircleFilled(ImVec2(p.x + 50, p.y + 50), 30.0f, IM_COL32(255, 0, 0, 255), 16); + +// Draw a 3 pixel thick yellow line +draw_list->AddLine(ImVec2(p.x, p.y), ImVec2(p.x + 100.0f, p.y + 100.0f), IM_COL32(255, 255, 0, 255), 3.0f); + +// Advance the ImGui cursor to claim space in the window (otherwise the window will appears small and needs to be resized) +ImGui::Dummy(ImVec2(200, 200)); + +ImGui::End(); +``` +![ImDrawList usage](https://raw.githubusercontent.com/wiki/ocornut/imgui/tutorials/CustomRendering01.png) + +- Refer to "Demo > Examples > Custom Rendering" in the demo window and read the code of `ShowExampleAppCustomRendering()` in `imgui_demo.cpp` from more examples. +- To generate colors: you can use the macro `IM_COL32(255,255,255,255)` to generate them at compile time, or use `ImGui::GetColorU32(IM_COL32(255,255,255,255))` or `ImGui::GetColorU32(ImVec4(1.0f,1.0f,1.0f,1.0f))` to generate a color that is multiplied by the current value of `style.Alpha`. +- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui_internal.h"` to use the internally defined math operators, but instead prefer using your own math library and set it up in `imconfig.h`. +- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other dear imgui windows (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated to a dear imgui window. +- You can also create your own dummy window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. +- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing ImDrawListSharedData, and then call your renderer function with your own ImDrawList or ImDrawData data. ##### [Return to Index](#index) diff --git a/docs/README.md b/docs/README.md index aaca0316462f3..a99ffe672e805 100644 --- a/docs/README.md +++ b/docs/README.md @@ -184,7 +184,7 @@ Most common questions will be answered by the [Frequently Asked Questions (FAQ)] - "How can I display an image? What is ImTextureID, how does it work?" - "How can I use my own math types instead of ImVec2/ImVec4?" - "How can I interact with standard C++ types (such as std::string and std::vector)?" -- "How can I use low-level drawing facilities? (using ImDrawList API)" +- "How can I display custom shapes? (using low-level ImDrawList API)" **Fonts, Text** - "How can I load a different font than the default?" @@ -247,7 +247,7 @@ Ongoing Dear ImGui development is financially supported by users and private spo - Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn. *Salty caramel supporters* -- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders. +- Remedy Entertainment, Next Level Games, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders. *Caramel supporters* - Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis, Matt Reyer. diff --git a/docs/TODO.txt b/docs/TODO.txt index 7ca24ca87cc93..b9fcecee781c1 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -363,6 +363,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - demo: add vertical separator demo - demo: add virtual scrolling example? - demo: demonstrate Plot offset + - demo: window size constraint: square demo is broken when resizing from edges (#1975), would need to rework the callback system to solve this - examples: window minimize, maximize (#583) - examples: provide a zero frame-rate/idle example. - examples: apple: example_apple should be using modern GL3. diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index a9e72c6cbb323..dbf1188d2eeae 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -61,7 +61,7 @@ static GLFWwindow* g_Window = NULL; // Main window static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; static double g_Time = 0.0; static bool g_MouseJustPressed[5] = { false, false, false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL; diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm index a491616a587c5..4f4e97534ebad 100644 --- a/examples/imgui_impl_osx.mm +++ b/examples/imgui_impl_osx.mm @@ -24,7 +24,7 @@ // Data static CFAbsoluteTime g_Time = 0.0; -static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; +static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static bool g_MouseCursorHidden = false; // Undocumented methods for creating cursors. diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 4267758101701..06d27b21fa61e 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -57,7 +57,7 @@ static SDL_Window* g_Window = NULL; static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; -static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static char* g_ClipboardTextData = NULL; static const char* ImGui_ImplSDL2_GetClipboardText(void*) diff --git a/imgui.cpp b/imgui.cpp index 597e681c578e3..700138f4706a4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -735,7 +735,7 @@ CODE Q: How can I use my own math types instead of ImVec2/ImVec4? Q: How can I interact with standard C++ types (such as std::string and std::vector)? - Q: How can I use low-level drawing facilities? (using ImDrawList API) + Q: How can I display custom shapes? (using low-level ImDrawList API) >> See https://www.dearimgui.org/faq Q&A: Fonts, Text @@ -5522,7 +5522,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Handle manual resize: Resize Grips, Borders, Gamepad int border_held = -1; - ImU32 resize_grip_col[4] = { 0 }; + ImU32 resize_grip_col[4] = {}; const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4 const float resize_grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); if (!window->Collapsed) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0eeec9801fbf8..8e76586300f9b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -923,7 +923,7 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("In columns")) { ImGui::Columns(3, NULL, false); - static bool selected[16] = { 0 }; + static bool selected[16] = {}; for (int i = 0; i < 16; i++) { char label[32]; sprintf(label, "Item %d", i); @@ -1075,7 +1075,7 @@ static void ShowDemoWindowWidgets() // Create a dummy array of contiguous float values to plot // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter. - static float values[90] = { 0 }; + static float values[90] = {}; static int values_offset = 0; static double refresh_time = 0.0; if (!animate || refresh_time == 0.0) @@ -1176,7 +1176,7 @@ static void ShowDemoWindowWidgets() // Generate a dummy default palette. The palette will persist and can be edited. static bool saved_palette_init = true; - static ImVec4 saved_palette[32] = { }; + static ImVec4 saved_palette[32] = {}; if (saved_palette_init) { for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) From 714fe29d1a93a9d5b62dce1859aa195ef1fb096c Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Thu, 17 Oct 2019 12:36:26 +0300 Subject: [PATCH 167/200] Replace manual flooring with IM_FLOOR() macro. (#2850) Macro is used to ensure that flooring operation is always inlined even in debug builds. __forceinline does not force inlining in /Od builds with MSVC. (cherry picked from commit bc165df6fd7969605bbc07b8a6d3d28f9109e8f3) --- imgui.cpp | 36 +++++++------- imgui_draw.cpp | 14 +++--- imgui_internal.h | 3 +- imgui_widgets.cpp | 80 ++++++++++++++++---------------- misc/freetype/imgui_freetype.cpp | 4 +- 5 files changed, 69 insertions(+), 68 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 700138f4706a4..50dd96478e5ae 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -302,7 +302,7 @@ CODE - The examples/ folders contains many actual implementation of the pseudo-codes above. - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated. They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the - rest of your application. In every cases you need to pass on the inputs to Dear ImGui. + rest of your application. In every cases you need to pass on the inputs to Dear ImGui. - Refer to the FAQ for more information. Amusingly, it is called a FAQ because people frequently run into the same issues! USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS @@ -605,7 +605,7 @@ CODE Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) - + Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. @@ -2781,8 +2781,8 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line - window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line + window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line + window->DC.CursorPos.y = IM_FLOOR(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] @@ -4121,7 +4121,7 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); // Round - text_size.x = (float)(int)(text_size.x + 0.95f); + text_size.x = IM_FLOOR(text_size.x + 0.95f); return text_size; } @@ -4763,8 +4763,8 @@ static ImVec2 CalcWindowContentSize(ImGuiWindow* window) return window->ContentSize; ImVec2 sz; - sz.x = (float)(int)((window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); - sz.y = (float)(int)((window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); + sz.x = IM_FLOOR((window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); + sz.y = IM_FLOOR((window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); return sz; } @@ -4875,8 +4875,8 @@ static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au bool ret_auto_fit = false; const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0; - const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); - const float grip_hover_inner_size = (float)(int)(grip_draw_size * 0.75f); + const float grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); + const float grip_hover_inner_size = IM_FLOOR(grip_draw_size * 0.75f); const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f; ImVec2 pos_target(FLT_MAX, FLT_MAX); @@ -5184,7 +5184,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl if (flags & ImGuiWindowFlags_UnsavedDocument) { ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f); - ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f)); + ImVec2 off = ImVec2(0.0f, IM_FLOOR(-g.FontSize * 0.25f)); RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r); } } @@ -5524,7 +5524,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) int border_held = -1; ImU32 resize_grip_col[4] = {}; const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4 - const float resize_grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); + const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (!window->Collapsed) if (UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0])) use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true; @@ -5592,9 +5592,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Default item width. Make it proportional to window size if window manually resizes if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) - window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f); + window->ItemWidthDefault = ImFloor(window->Size.x * 0.65f); else - window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); + window->ItemWidthDefault = ImFloor(g.FontSize * 16.0f); // SCROLLING @@ -5988,8 +5988,8 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImGuiStyle& style = g.Style; - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); window->DC.ItemWidthStack.push_back(w_item_last); for (int i = 0; i < components-1; i++) window->DC.ItemWidthStack.push_back(w_item_one); @@ -6020,7 +6020,7 @@ float ImGui::CalcItemWidth() float region_max_x = GetContentRegionMaxAbs().x; w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); } - w = (float)(int)w; + w = IM_FLOOR(w); return w; } @@ -7125,7 +7125,7 @@ void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x { // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); - window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); + window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); window->ScrollTargetCenterRatio.x = center_x_ratio; } @@ -7135,7 +7135,7 @@ void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); local_y -= decoration_up_height; - window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); + window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); window->ScrollTargetCenterRatio.y = center_y_ratio; } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4a6dce6d1cbca..e2b5ee865fecd 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2069,7 +2069,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); + const float font_off_y = cfg.GlyphOffset.y + ImFloor(dst_font->Ascent + 0.5f); for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) { @@ -2080,7 +2080,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) const float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX); float char_off_x = font_off_x; if (char_advance_x_org != char_advance_x_mod) - char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; + char_off_x += cfg.PixelSnapH ? ImFloor((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; // Register glyph stbtt_aligned_quad q; @@ -2591,7 +2591,7 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x; // Bake spacing into AdvanceX if (ConfigData->PixelSnapH) - glyph.AdvanceX = (float)(int)(glyph.AdvanceX + 0.5f); + glyph.AdvanceX = IM_FLOOR(glyph.AdvanceX + 0.5f); // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) DirtyLookupTables = true; @@ -2833,8 +2833,8 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col if (const ImFontGlyph* glyph = FindGlyph(c)) { float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; - pos.x = (float)(int)pos.x + DisplayOffset.x; - pos.y = (float)(int)pos.y + DisplayOffset.y; + pos.x = IM_FLOOR(pos.x + DisplayOffset.x); + pos.y = IM_FLOOR(pos.y + DisplayOffset.y); draw_list->PrimReserve(6, 4); draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } @@ -2846,8 +2846,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. // Align to be pixel perfect - pos.x = (float)(int)pos.x + DisplayOffset.x; - pos.y = (float)(int)pos.y + DisplayOffset.y; + pos.x = IM_FLOOR(pos.x + DisplayOffset.x); + pos.y = IM_FLOOR(pos.y + DisplayOffset.y); float x = pos.x; float y = pos.y; if (y > clip_rect.w) diff --git a/imgui_internal.h b/imgui_internal.h index e7868613f81cb..feee1036e23a1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -144,6 +144,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 +#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds // Debug Logging #ifndef IMGUI_DEBUG_LOG @@ -569,7 +570,7 @@ struct IMGUI_API ImRect void TranslateY(float dy) { Min.y += dy; Max.y += dy; } void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. - void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } + void Floor() { Min.x = IM_FLOOR(Min.x); Min.y = IM_FLOOR(Min.y); Max.x = IM_FLOOR(Max.x); Max.y = IM_FLOOR(Max.y); } bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b2398a00fcb0d..d223f147c49de 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -808,7 +808,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa const bool horizontal = (axis == ImGuiAxis_X); ImRect bb = bb_frame; - bb.Expand(ImVec2(-ImClamp((float)(int)((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); + bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) const float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); @@ -851,7 +851,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa // Apply scroll // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); - *p_scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); + *p_scroll_v = IM_FLOOR(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); // Update values for rendering scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); @@ -1004,12 +1004,12 @@ bool ImGui::Checkbox(const char* label, bool* v) if (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) { // Undocumented tristate/mixed/indeterminate checkbox (#2644) - ImVec2 pad(ImMax(1.0f, (float)(int)(square_sz / 3.6f)), ImMax(1.0f, (float)(int)(square_sz / 3.6f))); + ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); } else if (*v) { - const float pad = ImMax(1.0f, (float)(int)(square_sz / 6.0f)); + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); RenderCheckMark(check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f); } @@ -1057,8 +1057,8 @@ bool ImGui::RadioButton(const char* label, bool active) return false; ImVec2 center = check_bb.GetCenter(); - center.x = (float)(int)center.x + 0.5f; - center.y = (float)(int)center.y + 0.5f; + center.x = IM_FLOOR(center.x + 0.5f); + center.y = IM_FLOOR(center.y + 0.5f); const float radius = (square_sz - 1.0f) * 0.5f; bool hovered, held; @@ -1070,7 +1070,7 @@ bool ImGui::RadioButton(const char* label, bool active) window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); if (active) { - const float pad = ImMax(1.0f, (float)(int)(square_sz / 6.0f)); + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16); } @@ -4022,9 +4022,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { const float scroll_increment_x = inner_size.x * 0.25f; if (cursor_offset.x < state->ScrollX) - state->ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x); + state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x)); else if (cursor_offset.x - inner_size.x >= state->ScrollX) - state->ScrollX = (float)(int)(cursor_offset.x - inner_size.x + scroll_increment_x); + state->ScrollX = IM_FLOOR(cursor_offset.x - inner_size.x + scroll_increment_x); } else { @@ -4072,7 +4072,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ else { ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); - if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines + if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); rect.ClipWith(clip_rect); if (rect.Overlaps(clip_rect)) @@ -4239,8 +4239,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) { // RGB/HSV 0..255 Sliders - const float w_item_one = ImMax(1.0f, (float)(int)((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; @@ -4515,7 +4515,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; - float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f); + float bars_triangles_half_sz = IM_FLOOR(bars_width * 0.20f); float backup_initial_col[4]; memcpy(backup_initial_col, col, components * sizeof(float)); @@ -4795,13 +4795,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); - sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much - sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); + sv_cursor_pos.x = ImClamp(IM_FLOOR(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much + sv_cursor_pos.y = ImClamp(IM_FLOOR(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); // Render Hue Bar for (int i = 0; i < 6; ++i) draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]); - float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f); + float bar0_line_y = IM_FLOOR(picker_pos.y + H * sv_picker_size + 0.5f); RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } @@ -4819,7 +4819,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); - float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); + float bar1_line_y = IM_FLOOR(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } @@ -4876,7 +4876,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl bb_inner.Expand(off); if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) { - float mid_x = (float)(int)((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f); + float mid_x = IM_FLOOR((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f); RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight); window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft); } @@ -5228,8 +5228,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { // Framed header expand a little outside the default padding, to the edge of InnerClipRect // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) - frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f); - frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f); + frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f); + frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f); } const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing @@ -5242,7 +5242,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l ImRect interact_bb = frame_bb; if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0) interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f; - + // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. @@ -5521,8 +5521,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // Selectables are tightly packed together so we extend the box to cover spacing between selectable. const float spacing_x = style.ItemSpacing.x; const float spacing_y = style.ItemSpacing.y; - const float spacing_L = (float)(int)(spacing_x * 0.50f); - const float spacing_U = (float)(int)(spacing_y * 0.50f); + const float spacing_L = IM_FLOOR(spacing_x * 0.50f); + const float spacing_U = IM_FLOOR(spacing_y * 0.50f); bb.Min.x -= spacing_L; bb.Min.y -= spacing_U; bb.Max.x += (spacing_x - spacing_L); @@ -5972,7 +5972,7 @@ void ImGuiMenuColumns::Update(int count, float spacing, bool clear) { if (i > 0 && NextWidths[i] > 0.0f) Width += Spacing; - Pos[i] = (float)(int)Width; + Pos[i] = IM_FLOOR(Width); Width += NextWidths[i]; NextWidths[i] = 0.0f; } @@ -6129,19 +6129,19 @@ bool ImGui::BeginMenu(const char* label, bool enabled) // Menu inside an horizontal menu bar // Selectable extend their highlight by half ItemSpacing in each direction. // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() - popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); + popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); + window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x; pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); PopStyleVar(); - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). + window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else { // Menu inside a menu popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); - float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame + float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); @@ -6280,16 +6280,16 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful // Note that in this situation we render neither the shortcut neither the selected tick mark float w = label_size.x; - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); + window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); PopStyleVar(); - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). + window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else { ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); - float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame + float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f)); if (shortcut_size.x > 0.0f) @@ -6583,7 +6583,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) // If we don't have enough room, resize down the largest tabs first ShrinkWidths(g.ShrinkWidthBuffer.Data, g.ShrinkWidthBuffer.Size, width_excess); for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) - tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index].Width = (float)(int)g.ShrinkWidthBuffer[tab_n].Width; + tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index].Width = IM_FLOOR(g.ShrinkWidthBuffer[tab_n].Width); } else { @@ -6984,7 +6984,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // Layout size.x = tab->Width; - window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2((float)(int)tab->Offset - tab_bar->ScrollingAnim, 0.0f); + window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f); ImVec2 pos = window->DC.CursorPos; ImRect bb(pos, pos + size); @@ -7042,7 +7042,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->WidthContents) { // Enlarge tab display when hovering - bb.Max.x = bb.Min.x + (float)(int)ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f)); + bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f))); display_draw_list = GetForegroundDrawList(window); TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive)); } @@ -7152,7 +7152,7 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, if (flags & ImGuiTabItemFlags_UnsavedDocument) { text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x; - ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + (float)(int)(-g.FontSize * 0.25f)); + ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + IM_FLOOR(-g.FontSize * 0.25f)); RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL); } ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; @@ -7461,7 +7461,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } @@ -7476,7 +7476,7 @@ void ImGui::NextColumn() if (columns->Count == 1) { - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); IM_ASSERT(columns->Current == 0); return; } @@ -7501,7 +7501,7 @@ void ImGui::NextColumn() columns->Current = 0; columns->LineMinY = columns->LineMaxY; } - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.y = columns->LineMinY; window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineTextBaseOffset = 0.0f; @@ -7568,7 +7568,7 @@ void ImGui::EndColumns() // Draw column const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - const float xi = (float)(int)x; + const float xi = IM_FLOOR(x); window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); } @@ -7588,7 +7588,7 @@ void ImGui::EndColumns() window->WorkRect = columns->HostWorkRect; window->DC.CurrentColumns = NULL; window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); + window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); } // [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index d3f2bf54b2e60..3a89df5969eb1 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -545,7 +545,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns const float descent = src_tmp.Font.Info.Descender; ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); + const float font_off_y = cfg.GlyphOffset.y + IM_FLOOR(dst_font->Ascent + 0.5f); const int padding = atlas->TexGlyphPadding; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) @@ -572,7 +572,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX); float char_off_x = font_off_x; if (char_advance_x_org != char_advance_x_mod) - char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; + char_off_x += cfg.PixelSnapH ? IM_FLOOR((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; // Register glyph float x0 = info.OffsetX + char_off_x; From 4de32cc87ec6e446fb08998ec1933b3913216592 Mon Sep 17 00:00:00 2001 From: malte-v <34393802+malte-v@users.noreply.github.com> Date: Fri, 18 Oct 2019 16:25:18 +0200 Subject: [PATCH 168/200] Backends: GLFW: Restore previously installed user callbacks in ImplGlfw when ImGui shuts down (#2836) --- docs/CHANGELOG.txt | 1 + examples/imgui_impl_glfw.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ee9fcdd2e18a4..bed35ef384f11 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other Changes: - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] +- Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v] ----------------------------------------------------------------------- diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index dbf1188d2eeae..a28634e208799 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown. // 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter(). // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. @@ -62,6 +63,7 @@ static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; static double g_Time = 0.0; static bool g_MouseJustPressed[5] = { false, false, false, false, false }; static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; +static bool g_InstalledCallbacks = false; // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL; @@ -183,6 +185,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw g_PrevUserCallbackChar = NULL; if (install_callbacks) { + g_InstalledCallbacks = true; g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); @@ -205,6 +208,15 @@ bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfw_Shutdown() { + if (g_InstalledCallbacks) + { + glfwSetMouseButtonCallback(g_Window, g_PrevUserCallbackMousebutton); + glfwSetScrollCallback(g_Window, g_PrevUserCallbackScroll); + glfwSetKeyCallback(g_Window, g_PrevUserCallbackKey); + glfwSetCharCallback(g_Window, g_PrevUserCallbackChar); + g_InstalledCallbacks = false; + } + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) { glfwDestroyCursor(g_MouseCursors[cursor_n]); From eedc8f993f9b69db3e3d5540be55c5774b836342 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 18 Oct 2019 18:20:53 +0200 Subject: [PATCH 169/200] Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. --- docs/CHANGELOG.txt | 1 + examples/example_win32_directx12/main.cpp | 29 ++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bed35ef384f11..c941f2cda3b6f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,7 @@ Other Changes: - Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut] - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] +- Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] - Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v] diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index 90631e8525510..e555051cd3899 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -9,7 +9,12 @@ #include #include -#define DX12_ENABLE_DEBUG_LAYER 0 +//#define DX12_ENABLE_DEBUG_LAYER + +#ifdef DX12_ENABLE_DEBUG_LAYER +#include +#pragma comment(lib, "dxguid.lib") +#endif struct FrameContext { @@ -233,15 +238,14 @@ bool CreateDeviceD3D(HWND hWnd) sd.Stereo = FALSE; } - if (DX12_ENABLE_DEBUG_LAYER) +#ifdef DX12_ENABLE_DEBUG_LAYER + ID3D12Debug* pdx12Debug = NULL; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pdx12Debug)))) { - ID3D12Debug* dx12Debug = NULL; - if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&dx12Debug)))) - { - dx12Debug->EnableDebugLayer(); - dx12Debug->Release(); - } + pdx12Debug->EnableDebugLayer(); + pdx12Debug->Release(); } +#endif D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK) @@ -329,6 +333,15 @@ void CleanupDeviceD3D() if (g_fence) { g_fence->Release(); g_fence = NULL; } if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; } if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } + +#ifdef DX12_ENABLE_DEBUG_LAYER + IDXGIDebug1* pDebug = NULL; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug)))) + { + pDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY); + pDebug->Release(); + } +#endif } void CreateRenderTarget() From 6ffee0e75e8f677c5fd8280dfe544c3fcb325f45 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 18 Oct 2019 18:32:48 +0200 Subject: [PATCH 170/200] Backends: DX12: Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function. The value is unused in master branch but will be used by the multi-viewport features (docking branch). (#2851) + Using SafeRelease() in master. --- docs/CHANGELOG.txt | 2 ++ examples/example_win32_directx12/main.cpp | 2 +- examples/imgui_impl_dx12.cpp | 36 +++++++++++++++-------- examples/imgui_impl_dx12.h | 3 +- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c941f2cda3b6f..d41923bab0b47 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,8 @@ Breaking Changes: Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). Fixed the code and altered default io.KeyRepeatRate,Delay from 0.250,0.050 to 0.300,0.050 to compensate. If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. +- Backends: DX12: Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function. + The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate] Other Changes: - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index e555051cd3899..968ef7d9cf5b7 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -85,7 +85,7 @@ int main(int, char**) // Setup Platform/Renderer bindings ImGui_ImplWin32_Init(hwnd); ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT, - DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap, g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 6d6161a17e58d..83d6852732258 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-10-18: DirectX12: *BREAKING CHANGE* Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function. // 2019-05-29: DirectX12: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: DirectX12: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: Misc: Various minor tidying up. @@ -56,6 +57,14 @@ static FrameResources* g_pFrameResources = NULL; static UINT g_numFramesInFlight = 0; static UINT g_frameIndex = UINT_MAX; +template +static void SafeRelease(T*& res) +{ + if (res) + res->Release(); + res = NULL; +} + struct VERTEX_CONSTANT_BUFFER { float mvp[4][4]; @@ -132,7 +141,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL // Create and grow vertex/index buffers if needed if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) { - if (fr->VertexBuffer != NULL) { fr->VertexBuffer->Release(); fr->VertexBuffer = NULL; } + SafeRelease(fr->VertexBuffer); fr->VertexBufferSize = draw_data->TotalVtxCount + 5000; D3D12_HEAP_PROPERTIES props; memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); @@ -155,7 +164,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL } if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount) { - if (fr->IndexBuffer != NULL) { fr->IndexBuffer->Release(); fr->IndexBuffer = NULL; } + SafeRelease(fr->IndexBuffer); fr->IndexBufferSize = draw_data->TotalIdxCount + 10000; D3D12_HEAP_PROPERTIES props; memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); @@ -375,8 +384,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, g_hFontSrvCpuDescHandle); - if (g_pFontTextureResource != NULL) - g_pFontTextureResource->Release(); + SafeRelease(g_pFontTextureResource); g_pFontTextureResource = pTexture; } @@ -588,21 +596,24 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() if (!g_pd3dDevice) return; + SafeRelease(g_pVertexShaderBlob); + SafeRelease(g_pPixelShaderBlob); + SafeRelease(g_pRootSignature); + SafeRelease(g_pPipelineState); + SafeRelease(g_pFontTextureResource); + ImGuiIO& io = ImGui::GetIO(); - if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } - if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } - if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; } - if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; } - if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; io.Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. + io.Fonts->TexID = NULL; // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. + for (UINT i = 0; i < g_numFramesInFlight; i++) { FrameResources* fr = &g_pFrameResources[i]; - if (fr->IndexBuffer) { fr->IndexBuffer->Release(); fr->IndexBuffer = NULL; } - if (fr->VertexBuffer) { fr->VertexBuffer->Release(); fr->VertexBuffer = NULL; } + SafeRelease(fr->IndexBuffer); + SafeRelease(fr->VertexBuffer); } } -bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, +bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) { // Setup back-end capabilities flags @@ -617,6 +628,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO g_pFrameResources = new FrameResources[num_frames_in_flight]; g_numFramesInFlight = num_frames_in_flight; g_frameIndex = UINT_MAX; + IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports) // Create buffers with a default size (they will later be grown as needed) for (int i = 0; i < num_frames_in_flight; i++) diff --git a/examples/imgui_impl_dx12.h b/examples/imgui_impl_dx12.h index 274c1c92b6edb..6c05805b5a1a9 100644 --- a/examples/imgui_impl_dx12.h +++ b/examples/imgui_impl_dx12.h @@ -15,6 +15,7 @@ enum DXGI_FORMAT; struct ID3D12Device; +struct ID3D12DescriptorHeap; struct ID3D12GraphicsCommandList; struct D3D12_CPU_DESCRIPTOR_HANDLE; struct D3D12_GPU_DESCRIPTOR_HANDLE; @@ -23,7 +24,7 @@ struct D3D12_GPU_DESCRIPTOR_HANDLE; // Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate // render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. // font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture. -IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, +IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame(); From 7dbae8a1988b5175389c0064d208b3f7ef96106f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 21 Oct 2019 13:26:47 +0200 Subject: [PATCH 171/200] Doc: Simplified Readme, removed FAQ index --- docs/README.md | 57 +++++++------------------------------------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/docs/README.md b/docs/README.md index a99ffe672e805..e91db64cfaa19 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,23 +29,15 @@ Dear ImGui is particularly suited to integration in games engine (for tooling), ### Usage -Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: -- imgui.cpp -- imgui.h -- imgui_demo.cpp -- imgui_draw.cpp -- imgui_widgets.cpp -- imgui_internal.h -- imconfig.h (empty by default, user-editable) -- imstb_rectpack.h -- imstb_textedit.h -- imstb_truetype.h +**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily copy and compile into your application/engine. They are all the files in the root folder of the repository (imgui.cpp, imgui.h, imgui_demo.cpp, imgui_draw.cpp etc.). -No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. +**No specific build process is required**. You can add the .cpp files to your existing project. -Backends for a variety of graphics api and rendering platforms along with example applications are provided in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. +You will need a backend to integrate Dear ImGui in your app. The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices. -The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices. After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop: +**Backends for a variety of graphics api and rendering platforms** are provided in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder, along with example applications. See the [Integration](#integration) section of this document for details. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui. + +After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop: Code: ```cp @@ -153,44 +145,11 @@ Custom engine [![screenshot tool](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) [Tracy Profiler](https://bitbucket.org/wolfpld/tracy) -![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/tracy_profiler.png) +![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v173/tracy_profiler.jpg) ### Support, Frequently Asked Questions (FAQ) -Most common questions will be answered by the [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) page, e.g.: - -**Basics** -- "Where is the documentation?" -- "Which version should I get?" -- "Why the names "Dear ImGui" vs "ImGui"?" - -**Community** -- "How can I help?" - -**Concerns** -- "Who uses Dear ImGui?" -- "Can you create elaborate/serious tools with Dear ImGui?" -- "Can you reskin the look of Dear ImGui?" -- "Why using C++ (as opposed to C)?" - -**Integration** -- "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?" -- "How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)" -- "I integrated Dear ImGui in my engine and the text or lines are blurry.." -- "I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.." - -**Usage** -- "Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label?" -- "How can I display an image? What is ImTextureID, how does it work?" -- "How can I use my own math types instead of ImVec2/ImVec4?" -- "How can I interact with standard C++ types (such as std::string and std::vector)?" -- "How can I display custom shapes? (using low-level ImDrawList API)" - -**Fonts, Text** -- "How can I load a different font than the default?" -- "How can I easily use icons in my application?" -- "How can I load multiple fonts?" -- "How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?" +Most common questions will be answered by the [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) page. See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles. From 048b73dfaa0e9cbaea250305c5a4810d67722c8f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 21 Oct 2019 16:12:46 +0200 Subject: [PATCH 172/200] Various comments + Doc: Examples readme. Moved main menu bar code below menu bar code. --- examples/README.txt | 32 +++++++++++++++----- imgui.h | 61 +++++++++++++++++++++----------------- imgui_demo.cpp | 4 +-- imgui_widgets.cpp | 72 ++++++++++++++++++++++----------------------- 4 files changed, 96 insertions(+), 73 deletions(-) diff --git a/examples/README.txt b/examples/README.txt index 23c6bdb96f7ba..2c73c89d09f3c 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -62,10 +62,10 @@ You can find binaries of some of those example applications at: Most the example bindings are split in 2 parts: - The "Platform" bindings, in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, windowing. - Examples: Windows (imgui_impl_win32.cpp), GLFW (imgui_impl_glfw.cpp), SDL2 (imgui_impl_sdl.cpp) + Examples: Windows (imgui_impl_win32.cpp), GLFW (imgui_impl_glfw.cpp), SDL2 (imgui_impl_sdl.cpp), etc. - The "Renderer" bindings, in charge of: creating the main font texture, rendering imgui draw data. - Examples: DirectX11 (imgui_impl_dx11.cpp), GL3 (imgui_impl_opengl3.cpp), Vulkan (imgui_impl_vulkan.cpp) + Examples: DirectX11 (imgui_impl_dx11.cpp), GL3 (imgui_impl_opengl3.cpp), Vulkan (imgui_impl_vulkan.cpp), etc. - The example _applications_ usually combine 1 platform + 1 renderer binding to create a working program. Examples: the example_win32_directx11/ application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. @@ -122,16 +122,32 @@ List of high-level Frameworks Bindings in this repository: (combine Platform + R imgui_impl_allegro5.cpp imgui_impl_marmalade.cpp -Note that Dear ImGui works with Emscripten. -The examples_emscripten/ app uses sdl.cpp + opengl3.cpp but other combinations are possible. +Note that Dear ImGui works with Emscripten. The examples_emscripten/ app uses imgui_impl_sdl.cpp and +imgui_impl_opengl3.cpp, but other combinations are possible. + Third-party framework, graphics API and languages bindings are listed at: https://github.com/ocornut/imgui/wiki/Bindings - Languages: C, C#, ChaiScript, D, Go, Haxe, Java, Lua, Odin, Pascal, PureBasic, Python, Rust, Swift... - Frameworks: Cinder, Cocoa (OSX), Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, Ogre, OpenSceneGraph, - openFrameworks, LOVE, NanoRT, Nim Game Lib, Qt3d, SFML, Unreal Engine 4... - Miscellaneous: Software Renderer, RemoteImgui, etc. + Languages: + C, C#, ChaiScript, CovScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Nim, + Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... + + Frameworks: + Amethyst, bsf, Cinder, Cocoa2d-x, Diligent Engine, Flexium, GML/GameMaker Studio, + GTK3 + OpenGL, Irrlicht, Ogre, OpenSceneGraph/OSG, openFrameworks, Orx, LÖVE+LUA, + Magnum, NanoRT, Nim Game Lib, px_render, Qt, Qt3d, SFML, Sokol, Unreal Engine 4, vtk... + + Miscellaneous: Software Renderer, RemoteImgui, imgui-ws, etc. + +Not sure which to use? +Recommended platform/frameworks: + + GLFW https://github.com/glfw/glfw Use imgui_impl_glfw.cpp + SDL2 https://www.libsdl.org Use imgui_impl_sdl.cp + Sokol https://github.com/floooh/sokol Use util/sokol_imgui.h in Sokol repository. + +Those will allow you to create portable applications and will solve and abstract away many issues. --------------------------------------- diff --git a/imgui.h b/imgui.h index 1675fc6c65f6f..ba7d637015ee6 100644 --- a/imgui.h +++ b/imgui.h @@ -27,7 +27,7 @@ Index of this file: #pragma once -// Configuration file with compile-time options (edit imconfig.h or define IMGUI_USER_CONFIG to your own filename) +// Configuration file with compile-time options (edit imconfig.h or #define IMGUI_USER_CONFIG to your own filename) #ifdef IMGUI_USER_CONFIG #include IMGUI_USER_CONFIG #endif @@ -39,8 +39,9 @@ Index of this file: // Header mess //----------------------------------------------------------------------------- -#include // FLT_MAX -#include // va_list +// Includes +#include // FLT_MIN, FLT_MAX +#include // va_list, va_start, va_end #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp @@ -66,13 +67,13 @@ Index of this file: #define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h #endif #if defined(__clang__) || defined(__GNUC__) -#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to user functions. +#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // To apply printf-style warnings to our functions. #define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else #define IM_FMTARGS(FMT) #define IM_FMTLIST(FMT) #endif -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers! +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers! #define IM_UNUSED(_VAR) ((void)_VAR) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. #if (__cplusplus >= 201100) #define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11 @@ -123,7 +124,7 @@ struct ImGuiTextBuffer; // Helper to hold and append into a text buf struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbb][,ccccc]") // Typedefs and Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) -// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. +// Use your programming IDE "Go to definition" facility on the names in the central column below to find the actual flags/enum lists. #ifndef ImTextureID typedef void* ImTextureID; // User data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) #endif @@ -157,7 +158,7 @@ typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data); typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Scalar data types -typedef signed char ImS8; // 8-bit signed integer == char +typedef signed char ImS8; // 8-bit signed integer typedef unsigned char ImU8; // 8-bit unsigned integer typedef signed short ImS16; // 16-bit signed integer typedef unsigned short ImU16; // 16-bit unsigned integer @@ -201,14 +202,14 @@ struct ImVec4 //----------------------------------------------------------------------------- // ImGui: Dear ImGui end-user API -// (Inside a namespace so you can add extra functions in your own separate file. Please don't modify imgui.cpp/.h!) +// (Inside a namespace so you can add extra functions in your own separate file. Please don't modify imgui source files!) //----------------------------------------------------------------------------- namespace ImGui { // Context creation and access // Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between imgui contexts. - // All those functions are not reliant on the current context. + // None of those functions is reliant on the current context. IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context IMGUI_API ImGuiContext* GetCurrentContext(); @@ -245,8 +246,9 @@ namespace ImGui // which clicking will set the boolean to false when clicked. // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value! - // [this is due to legacy reason and is inconsistent with most other functions such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. - // where the EndXXX call should only be called if the corresponding BeginXXX function returned true.] + // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, + // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function + // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] // - Note that the bottom of window stack always contains a window called "Debug". IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); IMGUI_API void End(); @@ -255,13 +257,13 @@ namespace ImGui // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. // - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400). // - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window. - // Always call a matching EndChild() for each BeginChild() call, regardless of its return value [this is due to legacy reason and is inconsistent with most other functions such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function returned true.] + // Always call a matching EndChild() for each BeginChild() call, regardless of its return value [as with Begin: this is due to legacy reason and inconsistent with most BeginXXX functions apart from the regular Begin() which behaves like BeginChild().] IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); IMGUI_API void EndChild(); // Windows Utilities - // - "current window" = the window we are appending into while inside a Begin()/End() block. "next window" = next window we will Begin() into. + // - 'current window' = the window we are appending into while inside a Begin()/End() block. 'next window' = next window we will Begin() into. IMGUI_API bool IsWindowAppearing(); IMGUI_API bool IsWindowCollapsed(); IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options. @@ -342,6 +344,7 @@ namespace ImGui // Cursor / Layout // - By "cursor" we mean the current output position. // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down. + // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceeding widget. IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. IMGUI_API void SameLine(float offset_from_start_x=0.0f, float spacing=-1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates. IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in an horizontal-layout context. @@ -383,8 +386,8 @@ namespace ImGui IMGUI_API ImGuiID GetID(const void* ptr_id); // Widgets: Text - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. - IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // simple formatted text + IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. + IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); @@ -399,6 +402,7 @@ namespace ImGui // Widgets: Main // - Most widgets return true when the value has been changed or when pressed/selected + // - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state. IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) @@ -413,7 +417,7 @@ namespace ImGui IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses // Widgets: Combo Box - // - The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. + // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! @@ -509,7 +513,7 @@ namespace ImGui // Widgets: Selectables // - A selectable highlights when hovered, and can display another color when selected. - // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. + // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous. IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. @@ -535,16 +539,19 @@ namespace ImGui IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); // Widgets: Menus - IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. - IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! + // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar. + // - Use BeginMainMenuBar() to create a menu bar at the top of the screen. IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! + IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. + IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL // Tooltips + // - Tooltip are windows following the mouse which do not take focus away. IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items). IMGUI_API void EndTooltip(); IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip(). @@ -556,7 +563,7 @@ namespace ImGui // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls. // User can manipulate the visibility state by calling OpenPopup(). - // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup. + // (*) You can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup. // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time. IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true! @@ -572,6 +579,7 @@ namespace ImGui // Columns // - You can also use SameLine(pos_x) to mimic simplified columns. // - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!) + // - By end of the 2019 we will expose a new 'Table' api which will replace columns. IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index @@ -582,7 +590,6 @@ namespace ImGui IMGUI_API int GetColumnsCount(); // Tab Bars, Tabs - // [BETA API] API may evolve! IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true! IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0);// create a Tab. Returns true if the Tab is selected. @@ -950,12 +957,12 @@ enum ImGuiKey_ ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_KeyPadEnter, - ImGuiKey_A, // for text edit CTRL+A: select all - ImGuiKey_C, // for text edit CTRL+C: copy - ImGuiKey_V, // for text edit CTRL+V: paste - ImGuiKey_X, // for text edit CTRL+X: cut - ImGuiKey_Y, // for text edit CTRL+Y: redo - ImGuiKey_Z, // for text edit CTRL+Z: undo + ImGuiKey_A, // for text edit CTRL+A: select all + ImGuiKey_C, // for text edit CTRL+C: copy + ImGuiKey_V, // for text edit CTRL+V: paste + ImGuiKey_X, // for text edit CTRL+X: cut + ImGuiKey_Y, // for text edit CTRL+Y: redo + ImGuiKey_Z, // for text edit CTRL+Z: undo ImGuiKey_COUNT }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8e76586300f9b..c9ee0f43371fc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3263,7 +3263,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (ImGui::Button("Revert Ref")) style = *ref; ImGui::SameLine(); - HelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere."); + HelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export\" below to save them somewhere."); ImGui::Separator(); @@ -3311,7 +3311,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { static int output_dest = 0; static bool output_only_modified = true; - if (ImGui::Button("Export Unsaved")) + if (ImGui::Button("Export")) { if (output_dest == 0) ImGui::LogToClipboard(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d223f147c49de..f9415b3a2a1a3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5943,10 +5943,10 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) // [SECTION] MenuItem, BeginMenu, EndMenu, etc. //------------------------------------------------------------------------- // - ImGuiMenuColumns [Internal] -// - BeginMainMenuBar() -// - EndMainMenuBar() // - BeginMenuBar() // - EndMenuBar() +// - BeginMainMenuBar() +// - EndMainMenuBar() // - BeginMenu() // - EndMenu() // - MenuItem() @@ -5994,40 +5994,6 @@ float ImGuiMenuColumns::CalcExtraSpace(float avail_w) return ImMax(0.0f, avail_w - Width); } -// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set. -bool ImGui::BeginMainMenuBar() -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); - SetNextWindowPos(ImVec2(0.0f, 0.0f)); - SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y)); - PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); - ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; - bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar(); - PopStyleVar(2); - g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); - if (!is_open) - { - End(); - return false; - } - return true; //-V1020 -} - -void ImGui::EndMainMenuBar() -{ - EndMenuBar(); - - // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window - // FIXME: With this strategy we won't be able to restore a NULL focus. - ImGuiContext& g = *GImGui; - if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0 && !g.NavAnyRequest) - FocusTopMostWindowUnderOne(g.NavWindow, NULL); - - End(); -} - // FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere.. // Currently the main responsibility of this function being to setup clip-rect + horizontal layout + menu navigation layer. // Ideally we also want this to be responsible for claiming space out of the main window scrolling rectangle, in which case ImGuiWindowFlags_MenuBar will become unnecessary. @@ -6101,6 +6067,40 @@ void ImGui::EndMenuBar() window->DC.MenuBarAppending = false; } +// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set. +bool ImGui::BeginMainMenuBar() +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); + SetNextWindowPos(ImVec2(0.0f, 0.0f)); + SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y)); + PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); + ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; + bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar(); + PopStyleVar(2); + g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); + if (!is_open) + { + End(); + return false; + } + return true; //-V1020 +} + +void ImGui::EndMainMenuBar() +{ + EndMenuBar(); + + // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window + // FIXME: With this strategy we won't be able to restore a NULL focus. + ImGuiContext& g = *GImGui; + if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0 && !g.NavAnyRequest) + FocusTopMostWindowUnderOne(g.NavWindow, NULL); + + End(); +} + bool ImGui::BeginMenu(const char* label, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); From 23c1ff490744ca76c8e8581ea1605b786fb2720d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Oct 2019 14:43:04 +0200 Subject: [PATCH 173/200] Removed redirecting functions/enums names that were marked obsolete in 1.52 (October 2017). - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding(); - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f) - ImFont::Glyph -> use ImFontGlyph If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out the new names or equivalent features, or see how they were implemented until 1.73. --- docs/CHANGELOG.txt | 10 +++++++++- imgui.cpp | 19 ++----------------- imgui.h | 13 ++----------- imstb_textedit.h | 2 +- imstb_truetype.h | 2 +- 5 files changed, 15 insertions(+), 31 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d41923bab0b47..762a788a98e17 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,6 +34,14 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Breaking Changes: +- Removed redirecting functions/enums names that were marked obsolete in 1.52 (October 2017): + - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed + - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) + - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding() + - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f) + - ImFont::Glyph -> use ImFontGlyph + If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out + the new names or equivalent features, or see how they were implemented until 1.73. - Inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. If you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can @@ -42,7 +50,7 @@ Breaking Changes: Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). Fixed the code and altered default io.KeyRepeatRate,Delay from 0.250,0.050 to 0.300,0.050 to compensate. If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. -- Backends: DX12: Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function. +- Backends: DX12: Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function. The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate] Other Changes: diff --git a/imgui.cpp b/imgui.cpp index 50dd96478e5ae..6ee838355b2ba 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -351,13 +351,14 @@ CODE When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017): Begin() (5 arguments signature), IsRootWindowOrAnyChildHovered(), AlignFirstTextHeightToWidgets(), SetNextWindowPosCenter(), ImFont::Glyph. Grep this log for details and new names, or see how they were implemented until 1.73. - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix. The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names. + - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names, or see how they were implemented until 1.71. - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering. This optimization is disabled if the parent window has no visual output, because it appears to be the most common situation leading to the creation of overlapping child windows. @@ -5814,22 +5815,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) return !skip_items; } -// Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()/SetNextWindowBgAlpha() + Begin() instead. -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, float bg_alpha_override, ImGuiWindowFlags flags) -{ - // Old API feature: we could pass the initial window size as a parameter. This was misleading because it only had an effect if the window didn't have data in the .ini file. - if (size_first_use.x != 0.0f || size_first_use.y != 0.0f) - SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver); - - // Old API feature: override the window background alpha with a parameter. - if (bg_alpha_override >= 0.0f) - SetNextWindowBgAlpha(bg_alpha_override); - - return Begin(name, p_open, flags); -} -#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS - void ImGui::End() { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index ba7d637015ee6..9662670a50d34 100644 --- a/imgui.h +++ b/imgui.h @@ -246,8 +246,8 @@ namespace ImGui // which clicking will set the boolean to false when clicked. // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value! - // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, - // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function + // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, + // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] // - Note that the bottom of window stack always contains a window called "Debug". IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); @@ -1578,11 +1578,6 @@ namespace ImGui static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } - // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) - IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. - static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } - static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } - static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } } typedef ImGuiInputTextCallback ImGuiTextEditCallback; // OBSOLETED in 1.63 (from Aug 2018): made the names consistent typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData; @@ -2230,10 +2225,6 @@ struct ImFont IMGUI_API void AddGlyph(ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. IMGUI_API void SetFallbackChar(ImWchar c); - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - typedef ImFontGlyph Glyph; // OBSOLETED in 1.52+ -#endif }; #if defined(__clang__) diff --git a/imstb_textedit.h b/imstb_textedit.h index d7fcbd624980c..2077d02aed5fa 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -1,4 +1,4 @@ -// [DEAR IMGUI] +// [DEAR IMGUI] // This is a slightly modified version of stb_textedit.h 1.13. // Those changes would need to be pushed into nothings/stb: // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) diff --git a/imstb_truetype.h b/imstb_truetype.h index c1cdb1806a5df..193338afb2606 100644 --- a/imstb_truetype.h +++ b/imstb_truetype.h @@ -1,4 +1,4 @@ -// [DEAR IMGUI] +// [DEAR IMGUI] // This is a slightly modified version of stb_truetype.h 1.20. // Mostly fixing for compiler and static analyzer warnings. // Grep for [DEAR IMGUI] to find the changes. From be9f1e8f007be79e9c1b38ada231c9be2a416e6e Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 23 Oct 2019 00:45:59 +0300 Subject: [PATCH 174/200] ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j] --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 762a788a98e17..7b2a16a031b3f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Breaking Changes: The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate] Other Changes: +- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j] - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) - InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f9415b3a2a1a3..0f984debb8adf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4784,7 +4784,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl draw_list->PrimVtx(trb, uv_white, hue_color32); draw_list->PrimVtx(trc, uv_white, col_white); draw_list->PrimVtx(tra, uv_white, 0); - draw_list->PrimVtx(trb, uv_white, col_white); + draw_list->PrimVtx(trb, uv_white, col_black); draw_list->PrimVtx(trc, uv_white, 0); draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); From 75d540d33699fc04d1ea31deb5f8adb726aaf915 Mon Sep 17 00:00:00 2001 From: Funto Date: Wed, 23 Oct 2019 16:55:26 +0200 Subject: [PATCH 175/200] Example: Emscripten: Fix for compilation (filesystem module is required) (#2734) --- examples/example_emscripten/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/example_emscripten/Makefile b/examples/example_emscripten/Makefile index 9edfafd0ed890..c9f2c054e2d5d 100644 --- a/examples/example_emscripten/Makefile +++ b/examples/example_emscripten/Makefile @@ -24,7 +24,8 @@ UNAME_S := $(shell uname -s) EMS = -s USE_SDL=2 -s WASM=1 EMS += -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN_TRAP_MODE=clamp EMS += -s DISABLE_EXCEPTION_CATCHING=1 -s NO_EXIT_RUNTIME=0 -EMS += -s ASSERTIONS=1 -s NO_FILESYSTEM=1 +EMS += -s ASSERTIONS=1 +#EMS += -s NO_FILESYSTEM=1 ## Getting "error: undefined symbol: $FS" if filesystem is removed #EMS += -s SAFE_HEAP=1 ## Adds overhead CPPFLAGS = -I../ -I../../ From ec0e953ccac876a6c850fde2cbbe9bc138b99a55 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 6 Oct 2019 23:17:36 +0200 Subject: [PATCH 176/200] Fixed a couple of subtle bounding box vertical positioning issues relating to text baseline alignment. The issue would generally manifest when laying out multiple items on a same line, with varying heights and text baseline offsets. (#2833) Some specific examples, e.g. a button with regular frame padding followed by another item with a multi-line label and no frame padding, such as: multi-line text, small button, tree node item, etc. The second item was correctly offset to match text baseline, and would interact/display correctly,but it wouldn't push the contents area boundary low enough. Note: previously the second parameter to ItemSize() was 0.0f was default, now -1.0f to signify "no text baseline offset request". If you have code using ItemSize() with an hardcoded zero you may need to change it. (+1 squashed commits) --- docs/CHANGELOG.txt | 10 +++++++++- imgui.cpp | 9 +++++++-- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 27 ++++++++++++++------------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7b2a16a031b3f..46948ecca9f31 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,9 +54,16 @@ Breaking Changes: The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate] Other Changes: -- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j] - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) - InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) +- Layout: Fixed a couple of subtle bounding box vertical positioning issues relating to the handling of text + baseline alignment. The issue would generally manifest when laying out multiple items on a same line, + with varying heights and text baseline offsets. + Some specific examples, e.g. a button with regular frame padding followed by another item with a + multi-line label and no frame padding, such as: multi-line text, small button, tree node item, etc. + The second item was correctly offset to match text baseline, and would interact/display correctly, + but it wouldn't push the contents area boundary low enough. +- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j] - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data @@ -65,6 +72,7 @@ Other Changes: - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. +- Examples: Emscripten: Removed NO_FILESYSTEM from Makefile, seems to fail on some setup. (#2734) [@Funto] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] - Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v] diff --git a/imgui.cpp b/imgui.cpp index 6ee838355b2ba..cb4ff91313e5f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2777,8 +2777,13 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) if (window->SkipItems) return; + // We increase the height in this function to accommodate for baseline offset. + // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, + // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. + const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; + const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y); + // Always align ourselves on pixel boundaries - const float line_height = ImMax(window->DC.CurrLineSize.y, size.y); //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; @@ -6913,7 +6918,7 @@ void ImGui::EndGroup() } window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. - ItemSize(group_bb.GetSize(), 0.0f); + ItemSize(group_bb.GetSize()); ItemAdd(group_bb, 0); // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. diff --git a/imgui_internal.h b/imgui_internal.h index feee1036e23a1..f669b18ea3da6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1543,8 +1543,8 @@ namespace ImGui IMGUI_API void PushOverrideID(ImGuiID id); // Basic Helpers for widget code - IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = 0.0f); - IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = 0.0f); + IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); + IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0f984debb8adf..ca98f3ce213bd 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -213,7 +213,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) text_size.y = (pos - text_pos).y; ImRect bb(text_pos, text_pos + text_size); - ItemSize(text_size); + ItemSize(text_size, 0.0f); ItemAdd(bb, 0); } else @@ -222,7 +222,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); ImRect bb(text_pos, text_pos + text_size); - ItemSize(text_size); + ItemSize(text_size, 0.0f); if (!ItemAdd(bb, 0)) return; @@ -359,17 +359,18 @@ void ImGui::BulletTextV(const char* fmt, va_list args) const char* text_begin = g.TempBuffer; const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); - const float text_base_offset_y = ImMax(0.0f, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it - const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding - ItemSize(bb); + const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding + ImVec2 pos = window->DC.CursorPos; + pos.y += window->DC.CurrLineTextBaseOffset; + ItemSize(total_size, 0.0f); + const ImRect bb(pos, pos + total_size); if (!ItemAdd(bb, 0)) return; // Render ImU32 text_col = GetColorU32(ImGuiCol_Text); - RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), text_col); - RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false); + RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, g.FontSize*0.5f), text_col); + RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false); } //------------------------------------------------------------------------- @@ -691,7 +692,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu const ImGuiID id = window->GetID(str_id); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); const float default_size = GetFrameHeight(); - ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); + ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f); if (!ItemAdd(bb, id)) return false; @@ -5211,7 +5212,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; - const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); + const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y)); if (!label_end) label_end = FindRenderedTextEnd(label); @@ -5236,7 +5237,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); - ItemSize(ImVec2(text_width, frame_height), text_offset_y); + ItemSize(ImVec2(text_width, frame_height), padding.y); // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing ImRect interact_bb = frame_bb; @@ -5507,7 +5508,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrLineTextBaseOffset; ImRect bb_inner(pos, pos + size); - ItemSize(size); + ItemSize(size, 0.0f); // Fill horizontal space. ImVec2 window_padding = window->WindowPadding; @@ -6438,7 +6439,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG tab_bar->FramePadding = g.Style.FramePadding; // Layout - ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight())); + ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y); window->DC.CursorPos.x = tab_bar->BarRect.Min.x; // Draw separator From 24e9a6e92cca227c471ab5b81eb24299f9f84b35 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 23 Oct 2019 15:39:14 +0300 Subject: [PATCH 177/200] Remove .travis.yml due to switching to github actions. --- .travis.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7a554baf6709a..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -language: cpp -sudo: required -dist: trusty - -os: - - linux - - osx - -compiler: - - gcc - - clang - -before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then - sudo apt-get update -qq; - sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; - wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip; - unzip glfw-3.2.1.zip && cd glfw-3.2.1; - cmake -DBUILD_SHARED_LIBS=true -DGLFW_BUILD_EXAMPLES=false -DGLFW_BUILD_TESTS=false -DGLFW_BUILD_DOCS=false .; - sudo make -j $CPU_NUM install && cd ..; - fi - - if [ $TRAVIS_OS_NAME == osx ]; then - brew update; - brew install glfw3; - brew install sdl2; - fi - -script: - - make -C examples/example_glfw_opengl2 - - make -C examples/example_glfw_opengl3 - - make -C examples/example_sdl_opengl3 - - if [ $TRAVIS_OS_NAME == osx ]; then - xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos; - fi From d5b5a81946c5ecf40f1b083eee96ebf8ef472f79 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 23 Oct 2019 18:10:47 +0300 Subject: [PATCH 178/200] GitHub Actions CI script for Windows/Linux/MacOS/iOS/Emscripten builds. --- .github/workflows/build.yml | 108 ++++++++++++++++++++++++++++++++++++ docs/CHANGELOG.txt | 2 + docs/README.md | 4 +- 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000000..54d267aeb4efd --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,108 @@ +name: build + +on: [push, pull_request] + +jobs: + Windows: + runs-on: windows-2019 + env: + MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\ + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Fix Projects + shell: powershell + run: | + # Replace v110 toolset with v142. Only v141 and v142 toolsets are available on CI workers. + # Replace 8.1 platform sdk with 10.0.18362.0. Workers do not contain legacy SDKs. + # WARNING: This will need updating if toolset/sdk change in project files! + gci -recurse -filter "*.vcxproj" | ForEach-Object { + (Get-Content $_.FullName) -Replace "v110","v142" -Replace "8.1","10.0.18362.0" | Set-Content -Path $_.FullName + } + + - name: Build x86 + shell: cmd + run: | + "%MSBUILD_PATH%\MSBuild.exe" /p:Platform=Win32 /p:Configuration=Release examples/imgui_examples.sln + + - name: Build x64 + shell: cmd + run: | + "%MSBUILD_PATH%\MSBuild.exe" /p:Platform=x64 /p:Configuration=Release examples/imgui_examples.sln + + Linux: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y libglfw3-dev libsdl2-dev + + - name: Build + run: | + make -C examples/example_null + make -C examples/example_glfw_opengl2 + make -C examples/example_glfw_opengl3 + make -C examples/example_sdl_opengl2 + make -C examples/example_sdl_opengl3 + + MacOS: + runs-on: macOS-10.14 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Install Dependencies + run: | + brew install glfw3 + brew install sdl2 + + - name: Build + run: | + make -C examples/example_null + make -C examples/example_glfw_opengl2 + make -C examples/example_glfw_opengl3 + make -C examples/example_glfw_metal + make -C examples/example_sdl_opengl2 + make -C examples/example_sdl_opengl3 + xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos + xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2 + + iOS: + runs-on: macOS-10.14 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Build + run: | + # Code signing is required, but we disable it because it is irrelevant for CI builds. + xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO + + Emscripten: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Install Dependencies + run: | + wget -q https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz + tar -xvf emsdk-portable.tar.gz + emsdk-portable/emsdk update + emsdk-portable/emsdk install latest + emsdk-portable/emsdk activate latest + + - name: Build + run: | + source emsdk-portable/emsdk_env.sh + make -C examples/example_emscripten diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 46948ecca9f31..d52561d69feaf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,8 @@ Other Changes: - Examples: Emscripten: Removed NO_FILESYSTEM from Makefile, seems to fail on some setup. (#2734) [@Funto] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] - Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v] +- CI: Set up a bunch of continuous-integration tests using GitHub Actions. We now compile many of the example + applications on Windows, Linux, MacOS, iOS, Emscripten. Removed Travis integration. (#2865) [@rokups] ----------------------------------------------------------------------- diff --git a/docs/README.md b/docs/README.md index e91db64cfaa19..ac2e03a263fab 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ dear imgui ===== -[![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui) +[![Build Status](https://github.com/ocornut/imgui/workflows/build/badge.svg)](https://github.com/ocornut/imgui/actions?workflow=build) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) (This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.) @@ -33,7 +33,7 @@ Dear ImGui is particularly suited to integration in games engine (for tooling), **No specific build process is required**. You can add the .cpp files to your existing project. -You will need a backend to integrate Dear ImGui in your app. The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices. +You will need a backend to integrate Dear ImGui in your app. The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices. **Backends for a variety of graphics api and rendering platforms** are provided in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder, along with example applications. See the [Integration](#integration) section of this document for details. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui. From 3c238ecae30b264aa8cf0509f1e24a6c8e1d6d21 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 24 Oct 2019 11:26:45 +0200 Subject: [PATCH 179/200] Move issue_template and pull_request_template to .github folder. --- {docs => .github}/issue_template.md | 0 {docs => .github}/pull_request_template.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {docs => .github}/issue_template.md (100%) rename {docs => .github}/pull_request_template.md (100%) diff --git a/docs/issue_template.md b/.github/issue_template.md similarity index 100% rename from docs/issue_template.md rename to .github/issue_template.md diff --git a/docs/pull_request_template.md b/.github/pull_request_template.md similarity index 100% rename from docs/pull_request_template.md rename to .github/pull_request_template.md From 9b323a7ebfab1c0ce5840f1c2ed64f30c892d44e Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Oct 2019 11:05:14 +0200 Subject: [PATCH 180/200] SplitterBehavior: not using FrameRounding in render (was in first commit of the function, not sure why). (#319) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ca98f3ce213bd..958a6904f5d94 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1348,7 +1348,7 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float // Render const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding); + window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, 0.0f); return held; } From 4d0c88e9e6f0c77c9fbf71f6843daac9fec78371 Mon Sep 17 00:00:00 2001 From: dawid Date: Fri, 25 Oct 2019 11:40:50 +0200 Subject: [PATCH 181/200] Backends: GL3: Fix compile for < 3.2 bindings where glDrawElementsBaseVertex is not available. (#2866, #2852) --- examples/imgui_impl_opengl3.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 3824647aebb9b..7f2c588e30cf2 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -120,14 +120,15 @@ #endif // Desktop GL has glDrawElementsBaseVertex() which GL ES and WebGL don't have. -#if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) -#define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 0 +#if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) || !defined(GL_VERSION_3_2) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX 0 #else -#define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 1 +#define IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX 1 #endif // OpenGL Data static char g_GlslVersionString[32] = ""; +static GLuint g_GlVersion = 0; static GLuint g_FontTexture = 0; static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location @@ -137,11 +138,22 @@ static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { + // query for GL version +#if !defined(IMGUI_IMPL_OPENGL_ES2) + GLint major, minor; + glGetIntegerv (GL_MAJOR_VERSION, &major); + glGetIntegerv (GL_MINOR_VERSION, &minor); + g_GlVersion = major * 1000 + minor; +#else + g_GlVersion = 2000; // GLES 2 +#endif + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); io.BackendRendererName = "imgui_impl_opengl3"; -#if IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX - io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. +#if IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX + if (g_GlVersion >= 3200) + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. #endif // Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. @@ -344,8 +356,11 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // Bind texture, Draw glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); -#if IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX - glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); +#if IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX + if (g_GlVersion >= 3200) + glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); + else + glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); #else glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); #endif From f002a1189888faa0f98cfde963deeb78f02f4b43 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Oct 2019 11:56:36 +0200 Subject: [PATCH 182/200] Backends: OpenGL3: Fix building with pre-3.2 GL bindings which do not expose glDrawElementsBaseVertex(), using runtime GL version to decide if we set ImGuiBackendFlags_RendererHasVtxOffset. (#2866, #2852) [@dpilawa] --- docs/CHANGELOG.txt | 2 ++ examples/imgui_impl_opengl3.cpp | 34 ++++++++++++++++----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d52561d69feaf..72c7c18a7ea8f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -73,6 +73,8 @@ Other Changes: - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Examples: Emscripten: Removed NO_FILESYSTEM from Makefile, seems to fail on some setup. (#2734) [@Funto] +- Backends: OpenGL3: Fix building with pre-3.2 GL loaders which do not expose glDrawElementsBaseVertex(), + using runtime GL version to decide if we set ImGuiBackendFlags_RendererHasVtxOffset. (#2866, #2852) [@dpilawa] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] - Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v] - CI: Set up a bunch of continuous-integration tests using GitHub Actions. We now compile many of the example diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 7f2c588e30cf2..c1d44da6b0060 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders. // 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility. // 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. @@ -77,7 +78,7 @@ #include "TargetConditionals.h" #endif -// Auto-detect GL version +// Auto-enable GLES on matching platforms #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" @@ -99,9 +100,9 @@ #include #elif defined(IMGUI_IMPL_OPENGL_ES3) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) -#include // Use GL ES 3 +#include // Use GL ES 3 #else -#include // Use GL ES 3 +#include // Use GL ES 3 #endif #else // About Desktop OpenGL function loaders: @@ -119,16 +120,16 @@ #endif #endif -// Desktop GL has glDrawElementsBaseVertex() which GL ES and WebGL don't have. +// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. #if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) || !defined(GL_VERSION_3_2) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX 0 +#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 0 #else -#define IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX 1 +#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 1 #endif // OpenGL Data -static char g_GlslVersionString[32] = ""; -static GLuint g_GlVersion = 0; +static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries. +static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings. static GLuint g_FontTexture = 0; static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location @@ -138,11 +139,11 @@ static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { - // query for GL version + // Query for GL version #if !defined(IMGUI_IMPL_OPENGL_ES2) GLint major, minor; - glGetIntegerv (GL_MAJOR_VERSION, &major); - glGetIntegerv (GL_MINOR_VERSION, &minor); + glGetIntegerv(GL_MAJOR_VERSION, &major); + glGetIntegerv(GL_MINOR_VERSION, &minor); g_GlVersion = major * 1000 + minor; #else g_GlVersion = 2000; // GLES 2 @@ -151,12 +152,13 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); io.BackendRendererName = "imgui_impl_opengl3"; -#if IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX +#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET if (g_GlVersion >= 3200) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. #endif - // Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. + // Store GLSL version string so we can refer to it later in case we recreate shaders. + // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. #if defined(IMGUI_IMPL_OPENGL_ES2) if (glsl_version == NULL) glsl_version = "#version 100"; @@ -356,14 +358,12 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // Bind texture, Draw glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); -#if IMGUI_IMPL_OPENGL_MAY_HAVE_DRAW_WITH_BASE_VERTEX +#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET if (g_GlVersion >= 3200) glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); else - glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); -#else - glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); #endif + glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); } } } From 4e56de757c76c9d713d4f05a0f6adf82d1aac068 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Oct 2019 15:33:10 +0200 Subject: [PATCH 183/200] Doc: Promote Discord over Discourse. Obsoleting Discourse server. --- .github/issue_template.md | 2 +- docs/README.md | 4 ++-- imgui.cpp | 2 +- misc/fonts/README.txt | 7 ++----- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index bd05f0a58c580..e2c30e0754377 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -4,7 +4,7 @@ 2. PLEASE CAREFULLY READ: https://github.com/ocornut/imgui/issues/2261 -2. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use the [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forum](https://discourse.dearimgui.org/c/getting-started). +2. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use the [Discord server](http://discord.dearimgui.org). 3. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1) (2). diff --git a/docs/README.md b/docs/README.md index ac2e03a263fab..c5d757be5235a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -155,7 +155,7 @@ See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, a See: [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#Articles-about-the-IMGUI-paradigm) to read/learn about the Immediate Mode GUI paradigm. -If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org). +If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](http://discord.dearimgui.org). Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. @@ -176,7 +176,7 @@ How to help **How can I help?** -- You may participate in the [Discord server](https://discord.gg/NgJ4SEP), [Discourse forums](https://discourse.dearimgui.org), GitHub [issues tracker](https://github.com/ocornut/imgui/issues). +- You may participate in the [Discord server](http://discord.dearimgui.org), [GitHub forum/issues](https://github.com/ocornut/imgui/issues). - You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it. - See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas. - Have your company financially support this project. diff --git a/imgui.cpp b/imgui.cpp index cb4ff91313e5f..facc64d4ea5c4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5,7 +5,7 @@ // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui // Releases change-log at https://github.com/ocornut/imgui/releases -// Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started +// Technical Support for Getting Started https://github.com/ocornut/imgui/wiki // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2847 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 4ddafe62afcb2..0f335c7d96907 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -13,10 +13,8 @@ You may also load external .TTF/.OTF files. The files in this folder are suggested fonts, provided as a convenience. Fonts are rasterized in a single texture at the time of calling either of io.Fonts->GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). -Also read the FAQ: https://www.dearimgui.org/faq - -If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum: - https://discourse.dearimgui.org/c/getting-started +Please read the FAQ: https://www.dearimgui.org/faq +Please use the Discord server: http://discord.dearimgui.org and not the Github issue tracker for basic font loading questions. --------------------------------------- @@ -45,7 +43,6 @@ If you have other loading/merging/adding fonts, you can post on the Dear ImGui " u8"hello" u8"こんにちは" // this will be encoded as UTF-8 - If you want to include a backslash \ character in your string literal, you need to double them e.g. "folder\\filename". -- Please use the Discourse forum (https://discourse.dearimgui.org) and not the Github issue tracker for basic font loading questions. --------------------------------------- From 0b2d35f63fb0e6dd4f541e40430dbf762a2466ed Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Mon, 28 Oct 2019 12:46:45 +0100 Subject: [PATCH 184/200] Fix snprintf and vsnprintf definition inconsistencies. --- imgui_demo.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c9ee0f43371fc..3eedda458b11d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -100,12 +100,17 @@ Index of this file: // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n. #ifdef _WIN32 #define IM_NEWLINE "\r\n" -#define snprintf _snprintf -#define vsnprintf _vsnprintf #else #define IM_NEWLINE "\n" #endif +#if defined(_MSC_VER) && !defined(snprintf) +#define snprintf _snprintf +#endif +#if defined(_MSC_VER) && !defined(vsnprintf) +#define vsnprintf _vsnprintf +#endif + //----------------------------------------------------------------------------- // [SECTION] Forward Declarations, Helpers //----------------------------------------------------------------------------- From c863c1f6a1eb2aba0c017168e105025fe1fda422 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 29 Oct 2019 17:04:13 +0100 Subject: [PATCH 185/200] Clean up number rounding. Now it is more obvious what code is doing. (#2862) Add IM_ROUND() macro Replace IM_FLOOR(n + 0.5f) and ImFloor(n + 0.5f) with IM_ROUND(n) --- imgui.cpp | 10 +++++----- imgui_draw.cpp | 4 ++-- imgui_internal.h | 5 +++-- imgui_widgets.cpp | 26 +++++++++++++------------- misc/freetype/imgui_freetype.cpp | 2 +- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index facc64d4ea5c4..56ac3357785fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4747,8 +4747,8 @@ static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size g.NextWindowData.SizeCallback(&data); new_size = data.DesiredSize; } - new_size.x = ImFloor(new_size.x); - new_size.y = ImFloor(new_size.y); + new_size.x = IM_FLOOR(new_size.x); + new_size.y = IM_FLOOR(new_size.y); } // Minimum size @@ -6453,7 +6453,7 @@ void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond con if (size.x > 0.0f) { window->AutoFitFramesX = 0; - window->SizeFull.x = ImFloor(size.x); + window->SizeFull.x = IM_FLOOR(size.x); } else { @@ -6463,7 +6463,7 @@ void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond con if (size.y > 0.0f) { window->AutoFitFramesY = 0; - window->SizeFull.y = ImFloor(size.y); + window->SizeFull.y = IM_FLOOR(size.y); } else { @@ -8267,7 +8267,7 @@ static void ImGui::NavUpdate() { // *Fallback* manual-scroll with Nav directional keys when window has no navigable item ImGuiWindow* window = g.NavWindow; - const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * g.IO.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) { if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e2b5ee865fecd..544e9f3bdc20e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2069,7 +2069,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + ImFloor(dst_font->Ascent + 0.5f); + const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) { @@ -2591,7 +2591,7 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x; // Bake spacing into AdvanceX if (ConfigData->PixelSnapH) - glyph.AdvanceX = IM_FLOOR(glyph.AdvanceX + 0.5f); + glyph.AdvanceX = IM_ROUND(glyph.AdvanceX); // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) DirtyLookupTables = true; diff --git a/imgui_internal.h b/imgui_internal.h index f669b18ea3da6..26660ba3b4360 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -145,6 +145,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds +#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // // Debug Logging #ifndef IMGUI_DEBUG_LOG @@ -262,8 +263,8 @@ static inline float ImSaturate(float f) static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; } -static inline float ImFloor(float f) { return (float)(int)f; } -static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } +static inline float ImFloor(float f) { return (float)(int)(f); } +static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } static inline int ImModPositive(int a, int b) { return (a + b) % b; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 958a6904f5d94..f31b0138939fe 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -852,7 +852,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa // Apply scroll // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); - *p_scroll_v = IM_FLOOR(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); + *p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); // Update values for rendering scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); @@ -1058,8 +1058,8 @@ bool ImGui::RadioButton(const char* label, bool active) return false; ImVec2 center = check_bb.GetCenter(); - center.x = IM_FLOOR(center.x + 0.5f); - center.y = IM_FLOOR(center.y + 0.5f); + center.x = IM_ROUND(center.x); + center.y = IM_ROUND(center.y); const float radius = (square_sz - 1.0f) * 0.5f; bool hovered, held; @@ -4796,13 +4796,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); - sv_cursor_pos.x = ImClamp(IM_FLOOR(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much - sv_cursor_pos.y = ImClamp(IM_FLOOR(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); + sv_cursor_pos.x = ImClamp(IM_ROUND(picker_pos.x + ImSaturate(S) * sv_picker_size), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much + sv_cursor_pos.y = ImClamp(IM_ROUND(picker_pos.y + ImSaturate(1 - V) * sv_picker_size), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); // Render Hue Bar for (int i = 0; i < 6; ++i) draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]); - float bar0_line_y = IM_FLOOR(picker_pos.y + H * sv_picker_size + 0.5f); + float bar0_line_y = IM_ROUND(picker_pos.y + H * sv_picker_size); RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } @@ -4820,7 +4820,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); - float bar1_line_y = IM_FLOOR(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); + float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } @@ -4877,7 +4877,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl bb_inner.Expand(off); if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) { - float mid_x = IM_FLOOR((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f); + float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f); RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight); window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft); } @@ -6014,7 +6014,7 @@ bool ImGui::BeginMenuBar() // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. ImRect bar_rect = window->MenuBarRect(); - ImRect clip_rect(ImFloor(bar_rect.Min.x + 0.5f), ImFloor(bar_rect.Min.y + window->WindowBorderSize + 0.5f), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding) + 0.5f), ImFloor(bar_rect.Max.y + 0.5f)); + ImRect clip_rect(IM_ROUND(bar_rect.Min.x), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding)), IM_ROUND(bar_rect.Max.y)); clip_rect.ClipWith(window->OuterRectClipped); PushClipRect(clip_rect.Min, clip_rect.Max, false); @@ -6446,8 +6446,8 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive); const float y = tab_bar->BarRect.Max.y - 1.0f; { - const float separator_min_x = tab_bar->BarRect.Min.x - ImFloor(window->WindowPadding.x * 0.5f); - const float separator_max_x = tab_bar->BarRect.Max.x + ImFloor(window->WindowPadding.x * 0.5f); + const float separator_min_x = tab_bar->BarRect.Min.x - IM_FLOOR(window->WindowPadding.x * 0.5f); + const float separator_max_x = tab_bar->BarRect.Max.x + IM_FLOOR(window->WindowPadding.x * 0.5f); window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f); } return true; @@ -7443,8 +7443,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag { // Compute clipping rectangle ImGuiColumnData* column = &columns->Columns[n]; - float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n)); - float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); + float clip_x1 = IM_ROUND(window->Pos.x + GetColumnOffset(n)); + float clip_x2 = IM_ROUND(window->Pos.x + GetColumnOffset(n + 1) - 1.0f); column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); column->ClipRect.ClipWith(window->ClipRect); } diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 3a89df5969eb1..6695fb651fc8e 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -545,7 +545,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns const float descent = src_tmp.Font.Info.Descender; ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_FLOOR(dst_font->Ascent + 0.5f); + const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); const int padding = atlas->TexGlyphPadding; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) From 6bf5aed3254c7ec126b1fc10eb8ce38ac3bb5a9e Mon Sep 17 00:00:00 2001 From: stfx Date: Mon, 28 Oct 2019 13:02:59 +0100 Subject: [PATCH 186/200] Declaration and assignment can be joined, Member function may be 'const'. (#2875) --- imgui.h | 8 ++++---- imgui_draw.cpp | 9 ++++----- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/imgui.h b/imgui.h index 9662670a50d34..841506f973e45 100644 --- a/imgui.h +++ b/imgui.h @@ -1630,11 +1630,11 @@ struct ImGuiTextBuffer IMGUI_API static char EmptyString[1]; ImGuiTextBuffer() { } - inline char operator[](int i) { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } + inline char operator[](int i) const { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; } const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator int size() const { return Buf.Size ? Buf.Size - 1 : 0; } - bool empty() { return Buf.Size <= 1; } + bool empty() const { return Buf.Size <= 1; } void clear() { Buf.clear(); } void reserve(int capacity) { Buf.reserve(capacity); } const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } @@ -2111,7 +2111,7 @@ struct ImFontAtlas IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel - bool IsBuilt() { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); } + bool IsBuilt() const { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); } void SetTexID(ImTextureID id) { TexID = id; } //------------------------------------------- @@ -2144,7 +2144,7 @@ struct ImFontAtlas const ImFontAtlasCustomRect*GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; } // [Internal] - IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); + IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const; IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); //------------------------------------------- diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 544e9f3bdc20e..f73e0e311b026 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1752,7 +1752,7 @@ int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int return CustomRects.Size - 1; // Return index } -void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) +void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const { IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed @@ -3201,9 +3201,9 @@ static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, uns { const unsigned long ADLER_MOD = 65521; unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; - unsigned long blocklen, i; + unsigned long blocklen = buflen % 5552; - blocklen = buflen % 5552; + unsigned long i; while (buflen) { for (i=0; i + 7 < blocklen; i += 8) { s1 += buffer[0], s2 += s1; @@ -3230,10 +3230,9 @@ static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, uns static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/) { - unsigned int olen; if (stb__in4(0) != 0x57bC0000) return 0; if (stb__in4(4) != 0) return 0; // error! stream is > 4GB - olen = stb_decompress_length(i); + const unsigned int olen = stb_decompress_length(i); stb__barrier_in_b = i; stb__barrier_out_e = output + olen; stb__barrier_out_b = output; diff --git a/imgui_internal.h b/imgui_internal.h index 26660ba3b4360..3786b6fb6ee66 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -624,7 +624,7 @@ struct IMGUI_API ImGuiMenuColumns ImGuiMenuColumns(); void Update(int count, float spacing, bool clear); float DeclColumns(float w0, float w1, float w2); - float CalcExtraSpace(float avail_w); + float CalcExtraSpace(float avail_w) const; }; // Internal state of the currently focused/edited text input box diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f31b0138939fe..1a82f291e1915 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5990,7 +5990,7 @@ float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using v return ImMax(Width, NextWidth); } -float ImGuiMenuColumns::CalcExtraSpace(float avail_w) +float ImGuiMenuColumns::CalcExtraSpace(float avail_w) const { return ImMax(0.0f, avail_w - Width); } From d62a413476cea8245bddb0f18f8f57b8009cfe17 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Oct 2019 21:47:43 +0100 Subject: [PATCH 187/200] Misc: Windows: Do not use _wfopen() if IMGUI_DISABLE_WIN32_FUNCTIONS is defined. (#2815) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 72c7c18a7ea8f..719e598fdc283 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,7 @@ Other Changes: incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data to clarify how they are used, and more comments redirecting to the demo code. (#2844) +- Misc: Windows: Do not use _wfopen() if IMGUI_DISABLE_WIN32_FUNCTIONS is defined. (#2815) - Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut] - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] diff --git a/imgui.cpp b/imgui.cpp index 56ac3357785fd..2fdfb94826483 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1363,7 +1363,7 @@ ImU32 ImHashStr(const char* data_p, size_t data_size, ImU32 seed) FILE* ImFileOpen(const char* filename, const char* mode) { -#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__) +#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can) const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; From 9f979c33f4c33a6afeec8357324638c97b93499a Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 30 Oct 2019 09:49:57 +0200 Subject: [PATCH 188/200] CI: Fix builds failing because of missing v140 toolset and SDK on dx12 sample. (cherry picked from commit 8d91a77e9b42eac7a6d7d28c8563ccc468842e8b) --- .github/workflows/build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54d267aeb4efd..932c6be2565b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,11 +15,14 @@ jobs: - name: Fix Projects shell: powershell run: | - # Replace v110 toolset with v142. Only v141 and v142 toolsets are available on CI workers. - # Replace 8.1 platform sdk with 10.0.18362.0. Workers do not contain legacy SDKs. # WARNING: This will need updating if toolset/sdk change in project files! gci -recurse -filter "*.vcxproj" | ForEach-Object { - (Get-Content $_.FullName) -Replace "v110","v142" -Replace "8.1","10.0.18362.0" | Set-Content -Path $_.FullName + # Fix SDK and toolset for most samples. + (Get-Content $_.FullName) -Replace "v110","v142" | Set-Content -Path $_.FullName + (Get-Content $_.FullName) -Replace "8.1","10.0.18362.0" | Set-Content -Path $_.FullName + # Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12. + (Get-Content $_.FullName) -Replace "v140","v142" | Set-Content -Path $_.FullName + (Get-Content $_.FullName) -Replace "10.0.14393.0","10.0.18362.0" | Set-Content -Path $_.FullName } - name: Build x86 From a4420be1a20ecf18416f306902c78b87e4ff6c0a Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 30 Oct 2019 10:45:27 +0200 Subject: [PATCH 189/200] CI: Split builds of examples into separate jobs. (cherry picked from commit ee73b1b5a47f176ab123239aa3cbcc2cdf284383) --- .github/workflows/build.yml | 106 +++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 932c6be2565b3..cbe8291ea9f58 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,15 +25,51 @@ jobs: (Get-Content $_.FullName) -Replace "10.0.14393.0","10.0.18362.0" | Set-Content -Path $_.FullName } - - name: Build x86 + # Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long. + + - name: Build Win32 example_glfw_opengl2 shell: cmd - run: | - "%MSBUILD_PATH%\MSBuild.exe" /p:Platform=Win32 /p:Configuration=Release examples/imgui_examples.sln + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release' - - name: Build x64 + - name: Build Win32 example_glfw_opengl3 shell: cmd - run: | - "%MSBUILD_PATH%\MSBuild.exe" /p:Platform=x64 /p:Configuration=Release examples/imgui_examples.sln + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_win32_directx9 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_win32_directx10 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_win32_directx11 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build x64 example_glfw_opengl2 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_glfw_opengl3 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_win32_directx9 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_win32_directx10 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_win32_directx11 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_win32_directx12 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release' Linux: runs-on: ubuntu-18.04 @@ -47,13 +83,20 @@ jobs: sudo apt-get update sudo apt-get install -y libglfw3-dev libsdl2-dev - - name: Build - run: | - make -C examples/example_null - make -C examples/example_glfw_opengl2 - make -C examples/example_glfw_opengl3 - make -C examples/example_sdl_opengl2 - make -C examples/example_sdl_opengl3 + - name: Build example_null + run: make -C examples/example_null + + - name: Build example_glfw_opengl2 + run: make -C examples/example_glfw_opengl2 + + - name: Build example_glfw_opengl3 + run: make -C examples/example_glfw_opengl3 + + - name: Build example_sdl_opengl2 + run: make -C examples/example_sdl_opengl2 + + - name: Build example_sdl_opengl3 + run: make -C examples/example_sdl_opengl3 MacOS: runs-on: macOS-10.14 @@ -67,16 +110,29 @@ jobs: brew install glfw3 brew install sdl2 - - name: Build - run: | - make -C examples/example_null - make -C examples/example_glfw_opengl2 - make -C examples/example_glfw_opengl3 - make -C examples/example_glfw_metal - make -C examples/example_sdl_opengl2 - make -C examples/example_sdl_opengl3 - xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos - xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2 + - name: Build example_null + run: make -C examples/example_null + + - name: Build example_glfw_opengl2 + run: make -C examples/example_glfw_opengl2 + + - name: Build example_glfw_opengl3 + run: make -C examples/example_glfw_opengl3 + + - name: Build example_glfw_metal + run: make -C examples/example_glfw_metal + + - name: Build example_sdl_opengl2 + run: make -C examples/example_sdl_opengl2 + + - name: Build example_sdl_opengl3 + run: make -C examples/example_sdl_opengl3 + + - name: Build example_apple_metal + run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos + + - name: Build example_apple_opengl2 + run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2 iOS: runs-on: macOS-10.14 @@ -85,7 +141,7 @@ jobs: with: fetch-depth: 1 - - name: Build + - name: Build example_apple_metal run: | # Code signing is required, but we disable it because it is irrelevant for CI builds. xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO @@ -105,7 +161,7 @@ jobs: emsdk-portable/emsdk install latest emsdk-portable/emsdk activate latest - - name: Build + - name: Build example_emscripten run: | source emsdk-portable/emsdk_env.sh make -C examples/example_emscripten From 5ebd4e4c6e882cc197f3016c64d35f3e5821e270 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 30 Oct 2019 11:30:46 +0200 Subject: [PATCH 190/200] CI: Install SDL SDK in windows workers and add SDL examples to the build. CI: Add Vulkan GLFW and SDL builds to windows build job. --- .github/workflows/build.yml | 52 ++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbe8291ea9f58..1ee3e0d880cb6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,11 +7,22 @@ jobs: runs-on: windows-2019 env: MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\ + # Until gh-actions allow us to use env variables inside other env variables (because we need %GITHUB_WORKSPACE%) we have to use relative path to imgui/examples/example_name directory. + SDL2_DIR: ..\..\SDL2-devel-2.0.10-VC\SDL2-2.0.10\ + VULKAN_SDK: ..\..\vulkan-sdk-1.1.121.2\ steps: - uses: actions/checkout@v1 with: fetch-depth: 1 + - name: Install Dependencies + shell: powershell + run: | + Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip" -OutFile "SDL2-devel-2.0.10-VC.zip" + Expand-Archive -Path SDL2-devel-2.0.10-VC.zip + Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip + Expand-Archive -Path vulkan-sdk-1.1.121.2.zip + - name: Fix Projects shell: powershell run: | @@ -26,7 +37,6 @@ jobs: } # Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long. - - name: Build Win32 example_glfw_opengl2 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release' @@ -35,6 +45,26 @@ jobs: shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release' + - name: Build Win32 example_glfw_vulkan + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_sdl_vulkan + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_sdl_opengl2 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_sdl_opengl3 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release' + + - name: Build Win32 example_sdl_directx11 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release' + - name: Build Win32 example_win32_directx9 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=Win32 /p:Configuration=Release' @@ -55,6 +85,26 @@ jobs: shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release' + - name: Build x64 example_glfw_vulkan + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_sdl_vulkan + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_sdl_opengl2 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_sdl_opengl3 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release' + + - name: Build x64 example_sdl_directx11 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release' + - name: Build x64 example_win32_directx9 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release' From 5006639526494fb28f804dbc768eedcdf92e9ed4 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 30 Oct 2019 16:10:43 +0200 Subject: [PATCH 191/200] CI: Add scheduled builds and limit some examples to build only on schedule in order to decrease time of builds performed on each push. (cherry picked from commit 6c0e1baca29b853586dadf75eb32ef75e2725f10) --- .github/workflows/build.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ee3e0d880cb6..0c7020c60d1c6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,10 @@ name: build -on: [push, pull_request] +on: + push: {} + pull_request: {} + schedule: + - cron: '0 9 * * *' jobs: Windows: @@ -44,18 +48,22 @@ jobs: - name: Build Win32 example_glfw_opengl3 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build Win32 example_glfw_vulkan shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build Win32 example_sdl_vulkan shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build Win32 example_sdl_opengl2 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build Win32 example_sdl_opengl3 shell: cmd @@ -64,6 +72,7 @@ jobs: - name: Build Win32 example_sdl_directx11 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build Win32 example_win32_directx9 shell: cmd @@ -76,10 +85,12 @@ jobs: - name: Build Win32 example_win32_directx11 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_glfw_opengl2 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_glfw_opengl3 shell: cmd @@ -92,14 +103,17 @@ jobs: - name: Build x64 example_sdl_vulkan shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_sdl_opengl2 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_sdl_opengl3 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_sdl_directx11 shell: cmd @@ -108,14 +122,17 @@ jobs: - name: Build x64 example_win32_directx9 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_win32_directx10 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_win32_directx11 shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'schedule' - name: Build x64 example_win32_directx12 shell: cmd @@ -141,9 +158,11 @@ jobs: - name: Build example_glfw_opengl3 run: make -C examples/example_glfw_opengl3 + if: github.event_name == 'schedule' - name: Build example_sdl_opengl2 run: make -C examples/example_sdl_opengl2 + if: github.event_name == 'schedule' - name: Build example_sdl_opengl3 run: make -C examples/example_sdl_opengl3 @@ -168,12 +187,14 @@ jobs: - name: Build example_glfw_opengl3 run: make -C examples/example_glfw_opengl3 + if: github.event_name == 'schedule' - name: Build example_glfw_metal run: make -C examples/example_glfw_metal - name: Build example_sdl_opengl2 run: make -C examples/example_sdl_opengl2 + if: github.event_name == 'schedule' - name: Build example_sdl_opengl3 run: make -C examples/example_sdl_opengl3 From 8fee5a434904fce02ef542b6f3f684e09afde29c Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 31 Oct 2019 11:15:40 +0100 Subject: [PATCH 192/200] Internals: Renaming for consistency. --- imgui.cpp | 30 +++++++++++++++--------------- imgui_internal.h | 10 +++++----- imgui_widgets.cpp | 16 ++++++++-------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2fdfb94826483..53b19fad7c020 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5689,14 +5689,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x; window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y; - // [LEGACY] Contents Region - // FIXME-OBSOLETE: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. + // [LEGACY] Content Region + // FIXME-OBSOLETE: window->ContentRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. // Used by: // - Mouse wheel scrolling + many other things - window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x; - window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + decoration_up_height; - window->ContentsRegionRect.Max.x = window->ContentsRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x)); - window->ContentsRegionRect.Max.y = window->ContentsRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y)); + window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x; + window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + decoration_up_height; + window->ContentRegionRect.Max.x = window->ContentRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x)); + window->ContentRegionRect.Max.y = window->ContentRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y)); // Setup drawing context // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.) @@ -6599,7 +6599,7 @@ ImVec2 ImGui::GetContentRegionMax() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = window->ContentsRegionRect.Max - window->Pos; + ImVec2 mx = window->ContentRegionRect.Max - window->Pos; if (window->DC.CurrentColumns) mx.x = window->WorkRect.Max.x - window->Pos.x; return mx; @@ -6610,7 +6610,7 @@ ImVec2 ImGui::GetContentRegionMaxAbs() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = window->ContentsRegionRect.Max; + ImVec2 mx = window->ContentRegionRect.Max; if (window->DC.CurrentColumns) mx.x = window->WorkRect.Max.x; return mx; @@ -6626,19 +6626,19 @@ ImVec2 ImGui::GetContentRegionAvail() ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentsRegionRect.Min - window->Pos; + return window->ContentRegionRect.Min - window->Pos; } ImVec2 ImGui::GetWindowContentRegionMax() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentsRegionRect.Max - window->Pos; + return window->ContentRegionRect.Max - window->Pos; } float ImGui::GetWindowContentRegionWidth() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentsRegionRect.GetWidth(); + return window->ContentRegionRect.GetWidth(); } float ImGui::GetTextLineHeight() @@ -9594,8 +9594,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) } // State - enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Contents, WRT_ContentsRegionRect, WRT_Count }; // Windows Rect Type - const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" }; + enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type + const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" }; static bool show_windows_rects = false; static int show_windows_rect_type = WRT_WorkRect; static bool show_windows_begin_order = false; @@ -9626,8 +9626,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) else if (rect_type == WRT_InnerRect) { return window->InnerRect; } else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; } else if (rect_type == WRT_WorkRect) { return window->WorkRect; } - else if (rect_type == WRT_Contents) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } - else if (rect_type == WRT_ContentsRegionRect) { return window->ContentsRegionRect; } + else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } + else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; } IM_ASSERT(0); return ImRect(); } diff --git a/imgui_internal.h b/imgui_internal.h index 3786b6fb6ee66..c1dda24e55b82 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1338,9 +1338,9 @@ struct IMGUI_API ImGuiWindow ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window. ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar) ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect. - ImRect WorkRect; // Cover the whole scrolling region, shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentsRegionRect over time (from 1.71+ onward). + ImRect WorkRect; // Cover the whole scrolling region, shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentRegionRect over time (from 1.71+ onward). ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back(). - ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. + ImRect ContentRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. int LastFrameActive; // Last frame number the window was Active. float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there) @@ -1415,7 +1415,7 @@ enum ImGuiTabBarFlagsPrivate_ // Extend ImGuiTabItemFlags_ enum ImGuiTabItemFlagsPrivate_ { - ImGuiTabItemFlags_NoCloseButton = 1 << 20 // Store whether p_open is set or not, which we need to recompute WidthContents during layout. + ImGuiTabItemFlags_NoCloseButton = 1 << 20 // Store whether p_open is set or not, which we need to recompute ContentWidth during layout. }; // Storage for one active tab item (sizeof() 26~32 bytes) @@ -1428,9 +1428,9 @@ struct ImGuiTabItem int NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames float Offset; // Position relative to beginning of tab float Width; // Width currently displayed - float WidthContents; // Width of actual contents, stored during BeginTabItem() call + float ContentWidth; // Width of actual contents, stored during BeginTabItem() call - ImGuiTabItem() { ID = Flags = 0; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = WidthContents = 0.0f; } + ImGuiTabItem() { ID = Flags = 0; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; } }; // Storage for a tab bar (sizeof() 92~96 bytes) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1a82f291e1915..bf2f6617b4cd4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6566,13 +6566,13 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window. const char* tab_name = tab_bar->GetTabName(tab); const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true; - tab->WidthContents = TabItemCalcSize(tab_name, has_close_button).x; + tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x; - width_total_contents += (tab_n > 0 ? g.Style.ItemInnerSpacing.x : 0.0f) + tab->WidthContents; + width_total_contents += (tab_n > 0 ? g.Style.ItemInnerSpacing.x : 0.0f) + tab->ContentWidth; // Store data so we can build an array sorted by width if we need to shrink tabs down g.ShrinkWidthBuffer[tab_n].Index = tab_n; - g.ShrinkWidthBuffer[tab_n].Width = tab->WidthContents; + g.ShrinkWidthBuffer[tab_n].Width = tab->ContentWidth; } // Compute width @@ -6592,7 +6592,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; - tab->Width = ImMin(tab->WidthContents, tab_max_width); + tab->Width = ImMin(tab->ContentWidth, tab_max_width); IM_ASSERT(tab->Width > 0.0f); } } @@ -6608,7 +6608,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID) scroll_track_selected_tab_id = tab->ID; offset_x += tab->Width + g.Style.ItemInnerSpacing.x; - offset_x_ideal += tab->WidthContents + g.Style.ItemInnerSpacing.x; + offset_x_ideal += tab->ContentWidth + g.Style.ItemInnerSpacing.x; } tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f); tab_bar->OffsetMaxIdeal = ImMax(offset_x_ideal - g.Style.ItemInnerSpacing.x, 0.0f); @@ -6929,7 +6929,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, tab_is_new = true; } tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab); - tab->WidthContents = size.x; + tab->ContentWidth = size.x; if (p_open == NULL) flags |= ImGuiTabItemFlags_NoCloseButton; @@ -7040,10 +7040,10 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, } #if 0 - if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->WidthContents) + if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->ContentWidth) { // Enlarge tab display when hovering - bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f))); + bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->ContentWidth, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f))); display_draw_list = GetForegroundDrawList(window); TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive)); } From 792a8631aafd3df8d45563e3af60e39feb20b31d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 31 Oct 2019 14:01:35 +0100 Subject: [PATCH 193/200] Metrics: Expose basic details of each window key/value state storage. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 719e598fdc283..a5f6b1ee09b81 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,7 @@ Other Changes: - Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut] - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] +- Metrics: Expose basic details of each window key/value state storage. - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Examples: Emscripten: Removed NO_FILESYSTEM from Makefile, seems to fail on some setup. (#2734) [@Funto] - Backends: OpenGL3: Fix building with pre-3.2 GL loaders which do not expose glDrawElementsBaseVertex(), diff --git a/imgui.cpp b/imgui.cpp index 53b19fad7c020..22f5395e5e5e5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9762,7 +9762,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) NodeColumns(&window->ColumnsStorage[n]); ImGui::TreePop(); } - ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.size_in_bytes()); + NodeStorage(&window->StateStorage, "Storage"); ImGui::TreePop(); } @@ -9787,6 +9787,18 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } } + + static void NodeStorage(ImGuiStorage* storage, const char* label) + { + if (!ImGui::TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) + return; + for (int n = 0; n < storage->Data.Size; n++) + { + const ImGuiStorage::ImGuiStoragePair& p = storage->Data[n]; + ImGui::BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. + } + ImGui::TreePop(); + } }; Funcs::NodeWindows(g.Windows, "Windows"); From bcd752cfccb029ed60d93357e6eaa144a6df58da Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Mon, 4 Nov 2019 09:50:50 +0200 Subject: [PATCH 194/200] CI: Fix emscripten builds after portable SDK archive became unavailable. (cherry picked from commit 14b18697e653de80f75af18113033b2086846194) --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c7020c60d1c6..babd548a8b06e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -226,13 +226,13 @@ jobs: - name: Install Dependencies run: | - wget -q https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz - tar -xvf emsdk-portable.tar.gz - emsdk-portable/emsdk update - emsdk-portable/emsdk install latest - emsdk-portable/emsdk activate latest + wget -q https://github.com/emscripten-core/emsdk/archive/master.tar.gz + tar -xvf master.tar.gz + emsdk-master/emsdk update + emsdk-master/emsdk install latest-fastcomp + emsdk-master/emsdk activate latest-fastcomp - name: Build example_emscripten run: | - source emsdk-portable/emsdk_env.sh + source emsdk-master/emsdk_env.sh make -C examples/example_emscripten From c9ffa62e1f867c40df277df343d600af92220dc6 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 30 Oct 2019 17:50:02 +0200 Subject: [PATCH 195/200] Add .gitattributes with rules for line endings of files. (cherry picked from commit f2a2be72b341f55c44a035b1257177d83489ea5c) --- .gitattributes | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000..d48470eeff115 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,30 @@ +* text=auto + +*.c text +*.cpp text +*.h text +*.m text +*.mm text +*.md text +*.txt text +*.html text +*.bat text +*.frag text +*.vert text +*.mkb text +*.icf text + +*.sln text eol=crlf +*.vcxproj text eol=crlf +*.vcxproj.filters text eol=crlf +*.natvis text eol=crlf + +Makefile text eol=lf +*.sh text eol=lf +*.pbxproj text eol=lf +*.storyboard text eol=lf +*.plist text eol=lf + +*.png binary +*.ttf binary +*.lib binary From c9182424a83d949c663e3c80b0b7eda9c036f999 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 30 Oct 2019 17:50:11 +0200 Subject: [PATCH 196/200] Normalize all the line endings. (cherry picked from commit f1772d44be09fd78bf5f1ebda44b39b96180d319) --- .../example_sdl_directx11.vcxproj | 360 ++--- .../example_sdl_directx11.vcxproj.filters | 112 +- examples/libs/usynergy/uSynergy.c | 1272 ++++++++--------- 3 files changed, 872 insertions(+), 872 deletions(-) diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj index e28a5d2519180..7af2c9c063745 100644 --- a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj +++ b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj @@ -1,181 +1,181 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9E1987E3-1F19-45CA-B9C9-D31E791836D8} - example_sdl_directx11 - 8.1 - example_sdl_directx11 - - - - Application - true - MultiByte - v110 - - - Application - true - MultiByte - v110 - - - Application - false - true - MultiByte - v110 - - - Application - false - true - MultiByte - v110 - - - - - - - - - - - - - - - - - - - $(ProjectDir)$(Configuration)\ - $(ProjectDir)$(Configuration)\ - $(IncludePath) - - - $(ProjectDir)$(Configuration)\ - $(ProjectDir)$(Configuration)\ - $(IncludePath) - - - $(ProjectDir)$(Configuration)\ - $(ProjectDir)$(Configuration)\ - $(IncludePath) - - - $(ProjectDir)$(Configuration)\ - $(ProjectDir)$(Configuration)\ - $(IncludePath) - - - - Level4 - Disabled - ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) - - - true - %SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) - Console - msvcrt.lib - - - - - Level4 - Disabled - ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) - - - true - %SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) - SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) - Console - msvcrt.lib - - - - - Level4 - MaxSpeed - true - true - ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) - false - - - true - true - true - %SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) - Console - - - - - - - Level4 - MaxSpeed - true - true - ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) - false - - - true - true - true - %SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) - SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) - Console - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {9E1987E3-1F19-45CA-B9C9-D31E791836D8} + example_sdl_directx11 + 8.1 + example_sdl_directx11 + + + + Application + true + MultiByte + v110 + + + Application + true + MultiByte + v110 + + + Application + false + true + MultiByte + v110 + + + Application + false + true + MultiByte + v110 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + + + true + %SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + + + true + %SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + ..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters index b2345067d6b8f..879f0dbe623ae 100644 --- a/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters +++ b/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters @@ -1,57 +1,57 @@ - - - - - {0587d7a3-f2ce-4d56-b84f-a0005d3bfce6} - - - {08e36723-ce4f-4cff-9662-c40801cf1acf} - - - - - imgui - - - imgui - - - imgui - - - sources - - - sources - - - - - imgui - - - sources - - - imgui - - - imgui - - - sources - - - imgui - - - sources - - - - - - sources - - + + + + + {0587d7a3-f2ce-4d56-b84f-a0005d3bfce6} + + + {08e36723-ce4f-4cff-9662-c40801cf1acf} + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + sources + + + imgui + + + imgui + + + sources + + + imgui + + + sources + + + + + + sources + + \ No newline at end of file diff --git a/examples/libs/usynergy/uSynergy.c b/examples/libs/usynergy/uSynergy.c index a8d01da415e57..8dce47b8ab87c 100644 --- a/examples/libs/usynergy/uSynergy.c +++ b/examples/libs/usynergy/uSynergy.c @@ -1,636 +1,636 @@ -/* -uSynergy client -- Implementation for the embedded Synergy client library - version 1.0.0, July 7th, 2012 - -Copyright (c) 2012 Alex Evans - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ -#include "uSynergy.h" -#include -#include - - - -//--------------------------------------------------------------------------------------------------------------------- -// Internal helpers -//--------------------------------------------------------------------------------------------------------------------- - - - -/** -@brief Read 16 bit integer in network byte order and convert to native byte order -**/ -static int16_t sNetToNative16(const unsigned char *value) -{ -#ifdef USYNERGY_LITTLE_ENDIAN - return value[1] | (value[0] << 8); -#else - return value[0] | (value[1] << 8); -#endif -} - - - -/** -@brief Read 32 bit integer in network byte order and convert to native byte order -**/ -static int32_t sNetToNative32(const unsigned char *value) -{ -#ifdef USYNERGY_LITTLE_ENDIAN - return value[3] | (value[2] << 8) | (value[1] << 16) | (value[0] << 24); -#else - return value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); -#endif -} - - - -/** -@brief Trace text to client -**/ -static void sTrace(uSynergyContext *context, const char* text) -{ - // Don't trace if we don't have a trace function - if (context->m_traceFunc != 0L) - context->m_traceFunc(context->m_cookie, text); -} - - - -/** -@brief Add string to reply packet -**/ -static void sAddString(uSynergyContext *context, const char *string) -{ - size_t len = strlen(string); - memcpy(context->m_replyCur, string, len); - context->m_replyCur += len; -} - - - -/** -@brief Add uint8 to reply packet -**/ -static void sAddUInt8(uSynergyContext *context, uint8_t value) -{ - *context->m_replyCur++ = value; -} - - - -/** -@brief Add uint16 to reply packet -**/ -static void sAddUInt16(uSynergyContext *context, uint16_t value) -{ - uint8_t *reply = context->m_replyCur; - *reply++ = (uint8_t)(value >> 8); - *reply++ = (uint8_t)value; - context->m_replyCur = reply; -} - - - -/** -@brief Add uint32 to reply packet -**/ -static void sAddUInt32(uSynergyContext *context, uint32_t value) -{ - uint8_t *reply = context->m_replyCur; - *reply++ = (uint8_t)(value >> 24); - *reply++ = (uint8_t)(value >> 16); - *reply++ = (uint8_t)(value >> 8); - *reply++ = (uint8_t)value; - context->m_replyCur = reply; -} - - - -/** -@brief Send reply packet -**/ -static uSynergyBool sSendReply(uSynergyContext *context) -{ - // Set header size - uint8_t *reply_buf = context->m_replyBuffer; - uint32_t reply_len = (uint32_t)(context->m_replyCur - reply_buf); /* Total size of reply */ - uint32_t body_len = reply_len - 4; /* Size of body */ - uSynergyBool ret; - reply_buf[0] = (uint8_t)(body_len >> 24); - reply_buf[1] = (uint8_t)(body_len >> 16); - reply_buf[2] = (uint8_t)(body_len >> 8); - reply_buf[3] = (uint8_t)body_len; - - // Send reply - ret = context->m_sendFunc(context->m_cookie, context->m_replyBuffer, reply_len); - - // Reset reply buffer write pointer - context->m_replyCur = context->m_replyBuffer+4; - return ret; -} - - - -/** -@brief Call mouse callback after a mouse event -**/ -static void sSendMouseCallback(uSynergyContext *context) -{ - // Skip if no callback is installed - if (context->m_mouseCallback == 0L) - return; - - // Send callback - context->m_mouseCallback(context->m_cookie, context->m_mouseX, context->m_mouseY, context->m_mouseWheelX, - context->m_mouseWheelY, context->m_mouseButtonLeft, context->m_mouseButtonRight, context->m_mouseButtonMiddle); -} - - - -/** -@brief Send keyboard callback when a key has been pressed or released -**/ -static void sSendKeyboardCallback(uSynergyContext *context, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - // Skip if no callback is installed - if (context->m_keyboardCallback == 0L) - return; - - // Send callback - context->m_keyboardCallback(context->m_cookie, key, modifiers, down, repeat); -} - - - -/** -@brief Send joystick callback -**/ -static void sSendJoystickCallback(uSynergyContext *context, uint8_t joyNum) -{ - int8_t *sticks; - - // Skip if no callback is installed - if (context->m_joystickCallback == 0L) - return; - - // Send callback - sticks = context->m_joystickSticks[joyNum]; - context->m_joystickCallback(context->m_cookie, joyNum, context->m_joystickButtons[joyNum], sticks[0], sticks[1], sticks[2], sticks[3]); -} - - - -/** -@brief Parse a single client message, update state, send callbacks and send replies -**/ -#define USYNERGY_IS_PACKET(pkt_id) memcmp(message+4, pkt_id, 4)==0 -static void sProcessMessage(uSynergyContext *context, const uint8_t *message) -{ - // We have a packet! - if (memcmp(message+4, "Synergy", 7)==0) - { - // Welcome message - // kMsgHello = "Synergy%2i%2i" - // kMsgHelloBack = "Synergy%2i%2i%s" - sAddString(context, "Synergy"); - sAddUInt16(context, USYNERGY_PROTOCOL_MAJOR); - sAddUInt16(context, USYNERGY_PROTOCOL_MINOR); - sAddUInt32(context, (uint32_t)strlen(context->m_clientName)); - sAddString(context, context->m_clientName); - if (!sSendReply(context)) - { - // Send reply failed, let's try to reconnect - sTrace(context, "SendReply failed, trying to reconnect in a second"); - context->m_connected = USYNERGY_FALSE; - context->m_sleepFunc(context->m_cookie, 1000); - } - else - { - // Let's assume we're connected - char buffer[256+1]; - sprintf(buffer, "Connected as client \"%s\"", context->m_clientName); - sTrace(context, buffer); - context->m_hasReceivedHello = USYNERGY_TRUE; - } - return; - } - else if (USYNERGY_IS_PACKET("QINF")) - { - // Screen info. Reply with DINF - // kMsgQInfo = "QINF" - // kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i" - uint16_t x = 0, y = 0, warp = 0; - sAddString(context, "DINF"); - sAddUInt16(context, x); - sAddUInt16(context, y); - sAddUInt16(context, context->m_clientWidth); - sAddUInt16(context, context->m_clientHeight); - sAddUInt16(context, warp); - sAddUInt16(context, 0); // mx? - sAddUInt16(context, 0); // my? - sSendReply(context); - return; - } - else if (USYNERGY_IS_PACKET("CIAK")) - { - // Do nothing? - // kMsgCInfoAck = "CIAK" - return; - } - else if (USYNERGY_IS_PACKET("CROP")) - { - // Do nothing? - // kMsgCResetOptions = "CROP" - return; - } - else if (USYNERGY_IS_PACKET("CINN")) - { - // Screen enter. Reply with CNOP - // kMsgCEnter = "CINN%2i%2i%4i%2i" - - // Obtain the Synergy sequence number - context->m_sequenceNumber = sNetToNative32(message + 12); - context->m_isCaptured = USYNERGY_TRUE; - - // Call callback - if (context->m_screenActiveCallback != 0L) - context->m_screenActiveCallback(context->m_cookie, USYNERGY_TRUE); - } - else if (USYNERGY_IS_PACKET("COUT")) - { - // Screen leave - // kMsgCLeave = "COUT" - context->m_isCaptured = USYNERGY_FALSE; - - // Call callback - if (context->m_screenActiveCallback != 0L) - context->m_screenActiveCallback(context->m_cookie, USYNERGY_FALSE); - } - else if (USYNERGY_IS_PACKET("DMDN")) - { - // Mouse down - // kMsgDMouseDown = "DMDN%1i" - char btn = message[8]-1; - if (btn==2) - context->m_mouseButtonRight = USYNERGY_TRUE; - else if (btn==1) - context->m_mouseButtonMiddle = USYNERGY_TRUE; - else - context->m_mouseButtonLeft = USYNERGY_TRUE; - sSendMouseCallback(context); - } - else if (USYNERGY_IS_PACKET("DMUP")) - { - // Mouse up - // kMsgDMouseUp = "DMUP%1i" - char btn = message[8]-1; - if (btn==2) - context->m_mouseButtonRight = USYNERGY_FALSE; - else if (btn==1) - context->m_mouseButtonMiddle = USYNERGY_FALSE; - else - context->m_mouseButtonLeft = USYNERGY_FALSE; - sSendMouseCallback(context); - } - else if (USYNERGY_IS_PACKET("DMMV")) - { - // Mouse move. Reply with CNOP - // kMsgDMouseMove = "DMMV%2i%2i" - context->m_mouseX = sNetToNative16(message+8); - context->m_mouseY = sNetToNative16(message+10); - sSendMouseCallback(context); - } - else if (USYNERGY_IS_PACKET("DMWM")) - { - // Mouse wheel - // kMsgDMouseWheel = "DMWM%2i%2i" - // kMsgDMouseWheel1_0 = "DMWM%2i" - context->m_mouseWheelX += sNetToNative16(message+8); - context->m_mouseWheelY += sNetToNative16(message+10); - sSendMouseCallback(context); - } - else if (USYNERGY_IS_PACKET("DKDN")) - { - // Key down - // kMsgDKeyDown = "DKDN%2i%2i%2i" - // kMsgDKeyDown1_0 = "DKDN%2i%2i" - //uint16_t id = sNetToNative16(message+8); - uint16_t mod = sNetToNative16(message+10); - uint16_t key = sNetToNative16(message+12); - sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_FALSE); - } - else if (USYNERGY_IS_PACKET("DKRP")) - { - // Key repeat - // kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i" - // kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i" - uint16_t mod = sNetToNative16(message+10); -// uint16_t count = sNetToNative16(message+12); - uint16_t key = sNetToNative16(message+14); - sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_TRUE); - } - else if (USYNERGY_IS_PACKET("DKUP")) - { - // Key up - // kMsgDKeyUp = "DKUP%2i%2i%2i" - // kMsgDKeyUp1_0 = "DKUP%2i%2i" - //uint16 id=Endian::sNetToNative(sbuf[4]); - uint16_t mod = sNetToNative16(message+10); - uint16_t key = sNetToNative16(message+12); - sSendKeyboardCallback(context, key, mod, USYNERGY_FALSE, USYNERGY_FALSE); - } - else if (USYNERGY_IS_PACKET("DGBT")) - { - // Joystick buttons - // kMsgDGameButtons = "DGBT%1i%2i"; - uint8_t joy_num = message[8]; - if (joy_numm_joystickButtons[joy_num] = (message[9] << 8) | message[10]; - sSendJoystickCallback(context, joy_num); - } - } - else if (USYNERGY_IS_PACKET("DGST")) - { - // Joystick sticks - // kMsgDGameSticks = "DGST%1i%1i%1i%1i%1i"; - uint8_t joy_num = message[8]; - if (joy_numm_joystickSticks[joy_num], message+9, 4); - sSendJoystickCallback(context, joy_num); - } - } - else if (USYNERGY_IS_PACKET("DSOP")) - { - // Set options - // kMsgDSetOptions = "DSOP%4I" - } - else if (USYNERGY_IS_PACKET("CALV")) - { - // Keepalive, reply with CALV and then CNOP - // kMsgCKeepAlive = "CALV" - sAddString(context, "CALV"); - sSendReply(context); - // now reply with CNOP - } - else if (USYNERGY_IS_PACKET("DCLP")) - { - // Clipboard message - // kMsgDClipboard = "DCLP%1i%4i%s" - // - // The clipboard message contains: - // 1 uint32: The size of the message - // 4 chars: The identifier ("DCLP") - // 1 uint8: The clipboard index - // 1 uint32: The sequence number. It's zero, because this message is always coming from the server? - // 1 uint32: The total size of the remaining 'string' (as per the Synergy %s string format (which is 1 uint32 for size followed by a char buffer (not necessarily null terminated)). - // 1 uint32: The number of formats present in the message - // And then 'number of formats' times the following: - // 1 uint32: The format of the clipboard data - // 1 uint32: The size n of the clipboard data - // n uint8: The clipboard data - const uint8_t * parse_msg = message+17; - uint32_t num_formats = sNetToNative32(parse_msg); - parse_msg += 4; - for (; num_formats; num_formats--) - { - // Parse clipboard format header - uint32_t format = sNetToNative32(parse_msg); - uint32_t size = sNetToNative32(parse_msg+4); - parse_msg += 8; - - // Call callback - if (context->m_clipboardCallback) - context->m_clipboardCallback(context->m_cookie, format, parse_msg, size); - - parse_msg += size; - } - } - else - { - // Unknown packet, could be any of these - // kMsgCNoop = "CNOP" - // kMsgCClose = "CBYE" - // kMsgCClipboard = "CCLP%1i%4i" - // kMsgCScreenSaver = "CSEC%1i" - // kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i" - // kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i" - // kMsgDMouseRelMove = "DMRM%2i%2i" - // kMsgEIncompatible = "EICV%2i%2i" - // kMsgEBusy = "EBSY" - // kMsgEUnknown = "EUNK" - // kMsgEBad = "EBAD" - char buffer[64]; - sprintf(buffer, "Unknown packet '%c%c%c%c'", message[4], message[5], message[6], message[7]); - sTrace(context, buffer); - return; - } - - // Reply with CNOP maybe? - sAddString(context, "CNOP"); - sSendReply(context); -} -#undef USYNERGY_IS_PACKET - - - -/** -@brief Mark context as being disconnected -**/ -static void sSetDisconnected(uSynergyContext *context) -{ - context->m_connected = USYNERGY_FALSE; - context->m_hasReceivedHello = USYNERGY_FALSE; - context->m_isCaptured = USYNERGY_FALSE; - context->m_replyCur = context->m_replyBuffer + 4; - context->m_sequenceNumber = 0; -} - - - -/** -@brief Update a connected context -**/ -static void sUpdateContext(uSynergyContext *context) -{ - /* Receive data (blocking) */ - int receive_size = USYNERGY_RECEIVE_BUFFER_SIZE - context->m_receiveOfs; - int num_received = 0; - int packlen = 0; - if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer + context->m_receiveOfs, receive_size, &num_received) == USYNERGY_FALSE) - { - /* Receive failed, let's try to reconnect */ - char buffer[128]; - sprintf(buffer, "Receive failed (%d bytes asked, %d bytes received), trying to reconnect in a second", receive_size, num_received); - sTrace(context, buffer); - sSetDisconnected(context); - context->m_sleepFunc(context->m_cookie, 1000); - return; - } - context->m_receiveOfs += num_received; - - /* If we didn't receive any data then we're probably still polling to get connected and - therefore not getting any data back. To avoid overloading the system with a Synergy - thread that would hammer on polling, we let it rest for a bit if there's no data. */ - if (num_received == 0) - context->m_sleepFunc(context->m_cookie, 500); - - /* Check for timeouts */ - if (context->m_hasReceivedHello) - { - uint32_t cur_time = context->m_getTimeFunc(); - if (num_received == 0) - { - /* Timeout after 2 secs of inactivity (we received no CALV) */ - if ((cur_time - context->m_lastMessageTime) > USYNERGY_IDLE_TIMEOUT) - sSetDisconnected(context); - } - else - context->m_lastMessageTime = cur_time; - } - - /* Eat packets */ - for (;;) - { - /* Grab packet length and bail out if the packet goes beyond the end of the buffer */ - packlen = sNetToNative32(context->m_receiveBuffer); - if (packlen+4 > context->m_receiveOfs) - break; - - /* Process message */ - sProcessMessage(context, context->m_receiveBuffer); - - /* Move packet to front of buffer */ - memmove(context->m_receiveBuffer, context->m_receiveBuffer+packlen+4, context->m_receiveOfs-packlen-4); - context->m_receiveOfs -= packlen+4; - } - - /* Throw away over-sized packets */ - if (packlen > USYNERGY_RECEIVE_BUFFER_SIZE) - { - /* Oversized packet, ditch tail end */ - char buffer[128]; - sprintf(buffer, "Oversized packet: '%c%c%c%c' (length %d)", context->m_receiveBuffer[4], context->m_receiveBuffer[5], context->m_receiveBuffer[6], context->m_receiveBuffer[7], packlen); - sTrace(context, buffer); - num_received = context->m_receiveOfs-4; // 4 bytes for the size field - while (num_received != packlen) - { - int buffer_left = packlen - num_received; - int to_receive = buffer_left < USYNERGY_RECEIVE_BUFFER_SIZE ? buffer_left : USYNERGY_RECEIVE_BUFFER_SIZE; - int ditch_received = 0; - if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer, to_receive, &ditch_received) == USYNERGY_FALSE) - { - /* Receive failed, let's try to reconnect */ - sTrace(context, "Receive failed, trying to reconnect in a second"); - sSetDisconnected(context); - context->m_sleepFunc(context->m_cookie, 1000); - break; - } - else - { - num_received += ditch_received; - } - } - context->m_receiveOfs = 0; - } -} - - -//--------------------------------------------------------------------------------------------------------------------- -// Public interface -//--------------------------------------------------------------------------------------------------------------------- - - - -/** -@brief Initialize uSynergy context -**/ -void uSynergyInit(uSynergyContext *context) -{ - /* Zero memory */ - memset(context, 0, sizeof(uSynergyContext)); - - /* Initialize to default state */ - sSetDisconnected(context); -} - - -/** -@brief Update uSynergy -**/ -void uSynergyUpdate(uSynergyContext *context) -{ - if (context->m_connected) - { - /* Update context, receive data, call callbacks */ - sUpdateContext(context); - } - else - { - /* Try to connect */ - if (context->m_connectFunc(context->m_cookie)) - context->m_connected = USYNERGY_TRUE; - } -} - - - -/** -@brief Send clipboard data -**/ -void uSynergySendClipboard(uSynergyContext *context, const char *text) -{ - // Calculate maximum size that will fit in a reply packet - uint32_t overhead_size = 4 + /* Message size */ - 4 + /* Message ID */ - 1 + /* Clipboard index */ - 4 + /* Sequence number */ - 4 + /* Rest of message size (because it's a Synergy string from here on) */ - 4 + /* Number of clipboard formats */ - 4 + /* Clipboard format */ - 4; /* Clipboard data length */ - uint32_t max_length = USYNERGY_REPLY_BUFFER_SIZE - overhead_size; - - // Clip text to max length - uint32_t text_length = (uint32_t)strlen(text); - if (text_length > max_length) - { - char buffer[128]; - sprintf(buffer, "Clipboard buffer too small, clipboard truncated at %d characters", max_length); - sTrace(context, buffer); - text_length = max_length; - } - - // Assemble packet - sAddString(context, "DCLP"); - sAddUInt8(context, 0); /* Clipboard index */ - sAddUInt32(context, context->m_sequenceNumber); - sAddUInt32(context, 4+4+4+text_length); /* Rest of message size: numFormats, format, length, data */ - sAddUInt32(context, 1); /* Number of formats (only text for now) */ - sAddUInt32(context, USYNERGY_CLIPBOARD_FORMAT_TEXT); - sAddUInt32(context, text_length); - sAddString(context, text); - sSendReply(context); -} +/* +uSynergy client -- Implementation for the embedded Synergy client library + version 1.0.0, July 7th, 2012 + +Copyright (c) 2012 Alex Evans + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ +#include "uSynergy.h" +#include +#include + + + +//--------------------------------------------------------------------------------------------------------------------- +// Internal helpers +//--------------------------------------------------------------------------------------------------------------------- + + + +/** +@brief Read 16 bit integer in network byte order and convert to native byte order +**/ +static int16_t sNetToNative16(const unsigned char *value) +{ +#ifdef USYNERGY_LITTLE_ENDIAN + return value[1] | (value[0] << 8); +#else + return value[0] | (value[1] << 8); +#endif +} + + + +/** +@brief Read 32 bit integer in network byte order and convert to native byte order +**/ +static int32_t sNetToNative32(const unsigned char *value) +{ +#ifdef USYNERGY_LITTLE_ENDIAN + return value[3] | (value[2] << 8) | (value[1] << 16) | (value[0] << 24); +#else + return value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); +#endif +} + + + +/** +@brief Trace text to client +**/ +static void sTrace(uSynergyContext *context, const char* text) +{ + // Don't trace if we don't have a trace function + if (context->m_traceFunc != 0L) + context->m_traceFunc(context->m_cookie, text); +} + + + +/** +@brief Add string to reply packet +**/ +static void sAddString(uSynergyContext *context, const char *string) +{ + size_t len = strlen(string); + memcpy(context->m_replyCur, string, len); + context->m_replyCur += len; +} + + + +/** +@brief Add uint8 to reply packet +**/ +static void sAddUInt8(uSynergyContext *context, uint8_t value) +{ + *context->m_replyCur++ = value; +} + + + +/** +@brief Add uint16 to reply packet +**/ +static void sAddUInt16(uSynergyContext *context, uint16_t value) +{ + uint8_t *reply = context->m_replyCur; + *reply++ = (uint8_t)(value >> 8); + *reply++ = (uint8_t)value; + context->m_replyCur = reply; +} + + + +/** +@brief Add uint32 to reply packet +**/ +static void sAddUInt32(uSynergyContext *context, uint32_t value) +{ + uint8_t *reply = context->m_replyCur; + *reply++ = (uint8_t)(value >> 24); + *reply++ = (uint8_t)(value >> 16); + *reply++ = (uint8_t)(value >> 8); + *reply++ = (uint8_t)value; + context->m_replyCur = reply; +} + + + +/** +@brief Send reply packet +**/ +static uSynergyBool sSendReply(uSynergyContext *context) +{ + // Set header size + uint8_t *reply_buf = context->m_replyBuffer; + uint32_t reply_len = (uint32_t)(context->m_replyCur - reply_buf); /* Total size of reply */ + uint32_t body_len = reply_len - 4; /* Size of body */ + uSynergyBool ret; + reply_buf[0] = (uint8_t)(body_len >> 24); + reply_buf[1] = (uint8_t)(body_len >> 16); + reply_buf[2] = (uint8_t)(body_len >> 8); + reply_buf[3] = (uint8_t)body_len; + + // Send reply + ret = context->m_sendFunc(context->m_cookie, context->m_replyBuffer, reply_len); + + // Reset reply buffer write pointer + context->m_replyCur = context->m_replyBuffer+4; + return ret; +} + + + +/** +@brief Call mouse callback after a mouse event +**/ +static void sSendMouseCallback(uSynergyContext *context) +{ + // Skip if no callback is installed + if (context->m_mouseCallback == 0L) + return; + + // Send callback + context->m_mouseCallback(context->m_cookie, context->m_mouseX, context->m_mouseY, context->m_mouseWheelX, + context->m_mouseWheelY, context->m_mouseButtonLeft, context->m_mouseButtonRight, context->m_mouseButtonMiddle); +} + + + +/** +@brief Send keyboard callback when a key has been pressed or released +**/ +static void sSendKeyboardCallback(uSynergyContext *context, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + // Skip if no callback is installed + if (context->m_keyboardCallback == 0L) + return; + + // Send callback + context->m_keyboardCallback(context->m_cookie, key, modifiers, down, repeat); +} + + + +/** +@brief Send joystick callback +**/ +static void sSendJoystickCallback(uSynergyContext *context, uint8_t joyNum) +{ + int8_t *sticks; + + // Skip if no callback is installed + if (context->m_joystickCallback == 0L) + return; + + // Send callback + sticks = context->m_joystickSticks[joyNum]; + context->m_joystickCallback(context->m_cookie, joyNum, context->m_joystickButtons[joyNum], sticks[0], sticks[1], sticks[2], sticks[3]); +} + + + +/** +@brief Parse a single client message, update state, send callbacks and send replies +**/ +#define USYNERGY_IS_PACKET(pkt_id) memcmp(message+4, pkt_id, 4)==0 +static void sProcessMessage(uSynergyContext *context, const uint8_t *message) +{ + // We have a packet! + if (memcmp(message+4, "Synergy", 7)==0) + { + // Welcome message + // kMsgHello = "Synergy%2i%2i" + // kMsgHelloBack = "Synergy%2i%2i%s" + sAddString(context, "Synergy"); + sAddUInt16(context, USYNERGY_PROTOCOL_MAJOR); + sAddUInt16(context, USYNERGY_PROTOCOL_MINOR); + sAddUInt32(context, (uint32_t)strlen(context->m_clientName)); + sAddString(context, context->m_clientName); + if (!sSendReply(context)) + { + // Send reply failed, let's try to reconnect + sTrace(context, "SendReply failed, trying to reconnect in a second"); + context->m_connected = USYNERGY_FALSE; + context->m_sleepFunc(context->m_cookie, 1000); + } + else + { + // Let's assume we're connected + char buffer[256+1]; + sprintf(buffer, "Connected as client \"%s\"", context->m_clientName); + sTrace(context, buffer); + context->m_hasReceivedHello = USYNERGY_TRUE; + } + return; + } + else if (USYNERGY_IS_PACKET("QINF")) + { + // Screen info. Reply with DINF + // kMsgQInfo = "QINF" + // kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i" + uint16_t x = 0, y = 0, warp = 0; + sAddString(context, "DINF"); + sAddUInt16(context, x); + sAddUInt16(context, y); + sAddUInt16(context, context->m_clientWidth); + sAddUInt16(context, context->m_clientHeight); + sAddUInt16(context, warp); + sAddUInt16(context, 0); // mx? + sAddUInt16(context, 0); // my? + sSendReply(context); + return; + } + else if (USYNERGY_IS_PACKET("CIAK")) + { + // Do nothing? + // kMsgCInfoAck = "CIAK" + return; + } + else if (USYNERGY_IS_PACKET("CROP")) + { + // Do nothing? + // kMsgCResetOptions = "CROP" + return; + } + else if (USYNERGY_IS_PACKET("CINN")) + { + // Screen enter. Reply with CNOP + // kMsgCEnter = "CINN%2i%2i%4i%2i" + + // Obtain the Synergy sequence number + context->m_sequenceNumber = sNetToNative32(message + 12); + context->m_isCaptured = USYNERGY_TRUE; + + // Call callback + if (context->m_screenActiveCallback != 0L) + context->m_screenActiveCallback(context->m_cookie, USYNERGY_TRUE); + } + else if (USYNERGY_IS_PACKET("COUT")) + { + // Screen leave + // kMsgCLeave = "COUT" + context->m_isCaptured = USYNERGY_FALSE; + + // Call callback + if (context->m_screenActiveCallback != 0L) + context->m_screenActiveCallback(context->m_cookie, USYNERGY_FALSE); + } + else if (USYNERGY_IS_PACKET("DMDN")) + { + // Mouse down + // kMsgDMouseDown = "DMDN%1i" + char btn = message[8]-1; + if (btn==2) + context->m_mouseButtonRight = USYNERGY_TRUE; + else if (btn==1) + context->m_mouseButtonMiddle = USYNERGY_TRUE; + else + context->m_mouseButtonLeft = USYNERGY_TRUE; + sSendMouseCallback(context); + } + else if (USYNERGY_IS_PACKET("DMUP")) + { + // Mouse up + // kMsgDMouseUp = "DMUP%1i" + char btn = message[8]-1; + if (btn==2) + context->m_mouseButtonRight = USYNERGY_FALSE; + else if (btn==1) + context->m_mouseButtonMiddle = USYNERGY_FALSE; + else + context->m_mouseButtonLeft = USYNERGY_FALSE; + sSendMouseCallback(context); + } + else if (USYNERGY_IS_PACKET("DMMV")) + { + // Mouse move. Reply with CNOP + // kMsgDMouseMove = "DMMV%2i%2i" + context->m_mouseX = sNetToNative16(message+8); + context->m_mouseY = sNetToNative16(message+10); + sSendMouseCallback(context); + } + else if (USYNERGY_IS_PACKET("DMWM")) + { + // Mouse wheel + // kMsgDMouseWheel = "DMWM%2i%2i" + // kMsgDMouseWheel1_0 = "DMWM%2i" + context->m_mouseWheelX += sNetToNative16(message+8); + context->m_mouseWheelY += sNetToNative16(message+10); + sSendMouseCallback(context); + } + else if (USYNERGY_IS_PACKET("DKDN")) + { + // Key down + // kMsgDKeyDown = "DKDN%2i%2i%2i" + // kMsgDKeyDown1_0 = "DKDN%2i%2i" + //uint16_t id = sNetToNative16(message+8); + uint16_t mod = sNetToNative16(message+10); + uint16_t key = sNetToNative16(message+12); + sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_FALSE); + } + else if (USYNERGY_IS_PACKET("DKRP")) + { + // Key repeat + // kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i" + // kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i" + uint16_t mod = sNetToNative16(message+10); +// uint16_t count = sNetToNative16(message+12); + uint16_t key = sNetToNative16(message+14); + sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_TRUE); + } + else if (USYNERGY_IS_PACKET("DKUP")) + { + // Key up + // kMsgDKeyUp = "DKUP%2i%2i%2i" + // kMsgDKeyUp1_0 = "DKUP%2i%2i" + //uint16 id=Endian::sNetToNative(sbuf[4]); + uint16_t mod = sNetToNative16(message+10); + uint16_t key = sNetToNative16(message+12); + sSendKeyboardCallback(context, key, mod, USYNERGY_FALSE, USYNERGY_FALSE); + } + else if (USYNERGY_IS_PACKET("DGBT")) + { + // Joystick buttons + // kMsgDGameButtons = "DGBT%1i%2i"; + uint8_t joy_num = message[8]; + if (joy_numm_joystickButtons[joy_num] = (message[9] << 8) | message[10]; + sSendJoystickCallback(context, joy_num); + } + } + else if (USYNERGY_IS_PACKET("DGST")) + { + // Joystick sticks + // kMsgDGameSticks = "DGST%1i%1i%1i%1i%1i"; + uint8_t joy_num = message[8]; + if (joy_numm_joystickSticks[joy_num], message+9, 4); + sSendJoystickCallback(context, joy_num); + } + } + else if (USYNERGY_IS_PACKET("DSOP")) + { + // Set options + // kMsgDSetOptions = "DSOP%4I" + } + else if (USYNERGY_IS_PACKET("CALV")) + { + // Keepalive, reply with CALV and then CNOP + // kMsgCKeepAlive = "CALV" + sAddString(context, "CALV"); + sSendReply(context); + // now reply with CNOP + } + else if (USYNERGY_IS_PACKET("DCLP")) + { + // Clipboard message + // kMsgDClipboard = "DCLP%1i%4i%s" + // + // The clipboard message contains: + // 1 uint32: The size of the message + // 4 chars: The identifier ("DCLP") + // 1 uint8: The clipboard index + // 1 uint32: The sequence number. It's zero, because this message is always coming from the server? + // 1 uint32: The total size of the remaining 'string' (as per the Synergy %s string format (which is 1 uint32 for size followed by a char buffer (not necessarily null terminated)). + // 1 uint32: The number of formats present in the message + // And then 'number of formats' times the following: + // 1 uint32: The format of the clipboard data + // 1 uint32: The size n of the clipboard data + // n uint8: The clipboard data + const uint8_t * parse_msg = message+17; + uint32_t num_formats = sNetToNative32(parse_msg); + parse_msg += 4; + for (; num_formats; num_formats--) + { + // Parse clipboard format header + uint32_t format = sNetToNative32(parse_msg); + uint32_t size = sNetToNative32(parse_msg+4); + parse_msg += 8; + + // Call callback + if (context->m_clipboardCallback) + context->m_clipboardCallback(context->m_cookie, format, parse_msg, size); + + parse_msg += size; + } + } + else + { + // Unknown packet, could be any of these + // kMsgCNoop = "CNOP" + // kMsgCClose = "CBYE" + // kMsgCClipboard = "CCLP%1i%4i" + // kMsgCScreenSaver = "CSEC%1i" + // kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i" + // kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i" + // kMsgDMouseRelMove = "DMRM%2i%2i" + // kMsgEIncompatible = "EICV%2i%2i" + // kMsgEBusy = "EBSY" + // kMsgEUnknown = "EUNK" + // kMsgEBad = "EBAD" + char buffer[64]; + sprintf(buffer, "Unknown packet '%c%c%c%c'", message[4], message[5], message[6], message[7]); + sTrace(context, buffer); + return; + } + + // Reply with CNOP maybe? + sAddString(context, "CNOP"); + sSendReply(context); +} +#undef USYNERGY_IS_PACKET + + + +/** +@brief Mark context as being disconnected +**/ +static void sSetDisconnected(uSynergyContext *context) +{ + context->m_connected = USYNERGY_FALSE; + context->m_hasReceivedHello = USYNERGY_FALSE; + context->m_isCaptured = USYNERGY_FALSE; + context->m_replyCur = context->m_replyBuffer + 4; + context->m_sequenceNumber = 0; +} + + + +/** +@brief Update a connected context +**/ +static void sUpdateContext(uSynergyContext *context) +{ + /* Receive data (blocking) */ + int receive_size = USYNERGY_RECEIVE_BUFFER_SIZE - context->m_receiveOfs; + int num_received = 0; + int packlen = 0; + if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer + context->m_receiveOfs, receive_size, &num_received) == USYNERGY_FALSE) + { + /* Receive failed, let's try to reconnect */ + char buffer[128]; + sprintf(buffer, "Receive failed (%d bytes asked, %d bytes received), trying to reconnect in a second", receive_size, num_received); + sTrace(context, buffer); + sSetDisconnected(context); + context->m_sleepFunc(context->m_cookie, 1000); + return; + } + context->m_receiveOfs += num_received; + + /* If we didn't receive any data then we're probably still polling to get connected and + therefore not getting any data back. To avoid overloading the system with a Synergy + thread that would hammer on polling, we let it rest for a bit if there's no data. */ + if (num_received == 0) + context->m_sleepFunc(context->m_cookie, 500); + + /* Check for timeouts */ + if (context->m_hasReceivedHello) + { + uint32_t cur_time = context->m_getTimeFunc(); + if (num_received == 0) + { + /* Timeout after 2 secs of inactivity (we received no CALV) */ + if ((cur_time - context->m_lastMessageTime) > USYNERGY_IDLE_TIMEOUT) + sSetDisconnected(context); + } + else + context->m_lastMessageTime = cur_time; + } + + /* Eat packets */ + for (;;) + { + /* Grab packet length and bail out if the packet goes beyond the end of the buffer */ + packlen = sNetToNative32(context->m_receiveBuffer); + if (packlen+4 > context->m_receiveOfs) + break; + + /* Process message */ + sProcessMessage(context, context->m_receiveBuffer); + + /* Move packet to front of buffer */ + memmove(context->m_receiveBuffer, context->m_receiveBuffer+packlen+4, context->m_receiveOfs-packlen-4); + context->m_receiveOfs -= packlen+4; + } + + /* Throw away over-sized packets */ + if (packlen > USYNERGY_RECEIVE_BUFFER_SIZE) + { + /* Oversized packet, ditch tail end */ + char buffer[128]; + sprintf(buffer, "Oversized packet: '%c%c%c%c' (length %d)", context->m_receiveBuffer[4], context->m_receiveBuffer[5], context->m_receiveBuffer[6], context->m_receiveBuffer[7], packlen); + sTrace(context, buffer); + num_received = context->m_receiveOfs-4; // 4 bytes for the size field + while (num_received != packlen) + { + int buffer_left = packlen - num_received; + int to_receive = buffer_left < USYNERGY_RECEIVE_BUFFER_SIZE ? buffer_left : USYNERGY_RECEIVE_BUFFER_SIZE; + int ditch_received = 0; + if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer, to_receive, &ditch_received) == USYNERGY_FALSE) + { + /* Receive failed, let's try to reconnect */ + sTrace(context, "Receive failed, trying to reconnect in a second"); + sSetDisconnected(context); + context->m_sleepFunc(context->m_cookie, 1000); + break; + } + else + { + num_received += ditch_received; + } + } + context->m_receiveOfs = 0; + } +} + + +//--------------------------------------------------------------------------------------------------------------------- +// Public interface +//--------------------------------------------------------------------------------------------------------------------- + + + +/** +@brief Initialize uSynergy context +**/ +void uSynergyInit(uSynergyContext *context) +{ + /* Zero memory */ + memset(context, 0, sizeof(uSynergyContext)); + + /* Initialize to default state */ + sSetDisconnected(context); +} + + +/** +@brief Update uSynergy +**/ +void uSynergyUpdate(uSynergyContext *context) +{ + if (context->m_connected) + { + /* Update context, receive data, call callbacks */ + sUpdateContext(context); + } + else + { + /* Try to connect */ + if (context->m_connectFunc(context->m_cookie)) + context->m_connected = USYNERGY_TRUE; + } +} + + + +/** +@brief Send clipboard data +**/ +void uSynergySendClipboard(uSynergyContext *context, const char *text) +{ + // Calculate maximum size that will fit in a reply packet + uint32_t overhead_size = 4 + /* Message size */ + 4 + /* Message ID */ + 1 + /* Clipboard index */ + 4 + /* Sequence number */ + 4 + /* Rest of message size (because it's a Synergy string from here on) */ + 4 + /* Number of clipboard formats */ + 4 + /* Clipboard format */ + 4; /* Clipboard data length */ + uint32_t max_length = USYNERGY_REPLY_BUFFER_SIZE - overhead_size; + + // Clip text to max length + uint32_t text_length = (uint32_t)strlen(text); + if (text_length > max_length) + { + char buffer[128]; + sprintf(buffer, "Clipboard buffer too small, clipboard truncated at %d characters", max_length); + sTrace(context, buffer); + text_length = max_length; + } + + // Assemble packet + sAddString(context, "DCLP"); + sAddUInt8(context, 0); /* Clipboard index */ + sAddUInt32(context, context->m_sequenceNumber); + sAddUInt32(context, 4+4+4+text_length); /* Rest of message size: numFormats, format, length, data */ + sAddUInt32(context, 1); /* Number of formats (only text for now) */ + sAddUInt32(context, USYNERGY_CLIPBOARD_FORMAT_TEXT); + sAddUInt32(context, text_length); + sAddString(context, text); + sSendReply(context); +} From bff2d5d5e2e2d304a3c17d140a81b0bbce114c0b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Nov 2019 11:41:02 +0100 Subject: [PATCH 197/200] Update README.md --- docs/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/README.md b/docs/README.md index c5d757be5235a..c78cddb984269 100644 --- a/docs/README.md +++ b/docs/README.md @@ -214,6 +214,10 @@ Ongoing Dear ImGui development is financially supported by users and private spo And all other past and present supporters; THANK YOU! (Please contact me if you would like to be added or removed from this list) +Dear ImGui is using software and services kindly provided free of charge for open source projects: +- [PVS-Studio](https://www.viva64.com/en/b/0570/) for static analysis. +- [GitHub actions](https://github.com/features/actions) for continuous integration systems. + Credits ------- From 916487a653346d17d07226e5bb3c6bbc7f4bbf48 Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Thu, 31 Oct 2019 00:56:16 +0300 Subject: [PATCH 198/200] example_emscripten: skip outdated compiler option For more info see: https://github.com/ocornut/imgui/issues/2877 --- examples/example_emscripten/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/example_emscripten/Makefile b/examples/example_emscripten/Makefile index c9f2c054e2d5d..480fabd7d530a 100644 --- a/examples/example_emscripten/Makefile +++ b/examples/example_emscripten/Makefile @@ -22,9 +22,11 @@ OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) EMS = -s USE_SDL=2 -s WASM=1 -EMS += -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN_TRAP_MODE=clamp +EMS += -s ALLOW_MEMORY_GROWTH=1 EMS += -s DISABLE_EXCEPTION_CATCHING=1 -s NO_EXIT_RUNTIME=0 EMS += -s ASSERTIONS=1 +# Uncomment next line to fix possible rendering bugs with emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877) +#EMS += -s BINARYEN_TRAP_MODE=clamp #EMS += -s NO_FILESYSTEM=1 ## Getting "error: undefined symbol: $FS" if filesystem is removed #EMS += -s SAFE_HEAP=1 ## Adds overhead From 3929255b770d511301d8f65923c6f5f0adf8b126 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Nov 2019 12:53:30 +0100 Subject: [PATCH 199/200] Examples: Emscripten: Removed BINARYEN_TRAP_MODE=clamp from Makefile which was removed in Emscripten 1.39.0 but required prior to 1.39.0, making life easier for absolutely no-one. (#2877, #2878) [@podsvirov] --- docs/CHANGELOG.txt | 2 ++ examples/example_emscripten/README.md | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a5f6b1ee09b81..e4ea21dc85190 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,8 @@ Other Changes: - Metrics: Expose basic details of each window key/value state storage. - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Examples: Emscripten: Removed NO_FILESYSTEM from Makefile, seems to fail on some setup. (#2734) [@Funto] +- Examples: Emscripten: Removed BINARYEN_TRAP_MODE=clamp from Makefile which was removed in Emscripten 1.39.0 + but required prior to 1.39.0, making life easier for absolutely no-one. (#2877, #2878) [@podsvirov] - Backends: OpenGL3: Fix building with pre-3.2 GL loaders which do not expose glDrawElementsBaseVertex(), using runtime GL version to decide if we set ImGuiBackendFlags_RendererHasVtxOffset. (#2866, #2852) [@dpilawa] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] diff --git a/examples/example_emscripten/README.md b/examples/example_emscripten/README.md index c607ed73c912c..dcb7c1a72afa6 100644 --- a/examples/example_emscripten/README.md +++ b/examples/example_emscripten/README.md @@ -3,6 +3,10 @@ - You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions -``` -em++ -I.. -I../.. main.cpp ../imgui_impl_sdl.cpp ../imgui_impl_opengl3.cpp ../../imgui*.cpp -s USE_SDL=2 -s USE_WEBGL2=1 -s WASM=1 -s FULL_ES3=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN_TRAP_MODE=clamp --shell-file shell_minimal.html -o example-emscripten.html -``` +- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools. + +- Then build using `make` while in the `example_emscripten/` directory. + +- Note that Emscripten 1.39.0 (October 2019) obsoleted the `BINARYEN_TRAP_MODE=clamp` compilation flag which was required with version older than 1.39.0 to avoid rendering artefacts. See [#2877](https://github.com/ocornut/imgui/issues/2877) for details. If you use an older version, uncomment this line in the Makefile: + +`#EMS += -s BINARYEN_TRAP_MODE=clamp` From 4c13807b7d43ff0946b7ffea0ae3aee9e611d778 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Nov 2019 22:43:53 +0100 Subject: [PATCH 200/200] Misc: Optimized storage of window settings data (reducing allocation count). --- docs/CHANGELOG.txt | 1 + imgui.cpp | 12 +++++++----- imgui_internal.h | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e4ea21dc85190..6aa2940716e08 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,7 @@ Other Changes: incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data to clarify how they are used, and more comments redirecting to the demo code. (#2844) +- Misc: Optimized storage of window settings data (reducing allocation count). - Misc: Windows: Do not use _wfopen() if IMGUI_DISABLE_WIN32_FUNCTIONS is defined. (#2815) - Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut] - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. diff --git a/imgui.cpp b/imgui.cpp index 22f5395e5e5e5..f58737ca5bc6c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3809,8 +3809,7 @@ void ImGui::Shutdown(ImGuiContext* context) g.PrivateClipboard.clear(); g.InputTextState.ClearFreeMemory(); - for (int i = 0; i < g.SettingsWindows.Size; i++) - IM_DELETE(g.SettingsWindows[i].Name); + g.SettingsWindowsNames.clear(); g.SettingsWindows.clear(); g.SettingsHandlers.clear(); @@ -9205,8 +9204,10 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) if (const char* p = strstr(name, "###")) name = p; #endif - settings->Name = ImStrdup(name); - settings->ID = ImHashStr(name); + size_t name_len = strlen(name); + settings->NameOffset = g.SettingsWindowsNames.size(); + g.SettingsWindowsNames.append(name, name + name_len + 1); // Append with zero terminator + settings->ID = ImHashStr(name, name_len); return settings; } @@ -9387,7 +9388,8 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl for (int i = 0; i != g.SettingsWindows.Size; i++) { const ImGuiWindowSettings* settings = &g.SettingsWindows[i]; - buf->appendf("[%s][%s]\n", handler->TypeName, settings->Name); + const char* settings_name = g.SettingsWindowsNames.c_str() + settings->NameOffset; + buf->appendf("[%s][%s]\n", handler->TypeName, settings_name); buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y); buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y); buf->appendf("Collapsed=%d\n", settings->Collapsed); diff --git a/imgui_internal.h b/imgui_internal.h index c1dda24e55b82..c1998107b226f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -662,15 +662,16 @@ struct IMGUI_API ImGuiInputTextState }; // Windows data saved in imgui.ini file +// Because we never destroy or rename ImGuiWindowSettings, we can store the names in a separate buffer easily. struct ImGuiWindowSettings { - char* Name; + int NameOffset; // Offset into SettingsWindowNames[] ImGuiID ID; ImVec2ih Pos; ImVec2ih Size; bool Collapsed; - ImGuiWindowSettings() { Name = NULL; ID = 0; Pos = Size = ImVec2ih(0, 0); Collapsed = false; } + ImGuiWindowSettings() { NameOffset = -1; ID = 0; Pos = Size = ImVec2ih(0, 0); Collapsed = false; } }; struct ImGuiSettingsHandler @@ -1039,6 +1040,7 @@ struct ImGuiContext ImGuiTextBuffer SettingsIniData; // In memory .ini settings ImVector SettingsHandlers; // List of .ini settings handlers ImVector SettingsWindows; // ImGuiWindow .ini settings entries (parsed from the last loaded .ini file and maintained on saving) + ImGuiTextBuffer SettingsWindowsNames; // Names for SettingsWindows // Logging bool LogEnabled;