From ae1e3619f6f81a45a7162d70cba65118fd36c0ec Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Thu, 9 Jan 2020 13:47:42 +0200 Subject: [PATCH 01/11] Disable some PVS studio warnings. V1048: While they are technically correct we want to emphasize assigned values must remain same. --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 549ee75e..f659123e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4197,7 +4197,7 @@ void ImGui::Render() g.FrameCountRendered = g.FrameCount; // Gather ImDrawList to render (for each active window) - g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsRenderWindows = 0; + g.IO.MetricsRenderWindows = 0; g.DrawDataBuilder.Clear(); if (!g.BackgroundDrawList.VtxBuffer.empty()) AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.BackgroundDrawList); @@ -8363,7 +8363,7 @@ static void ImGui::NavUpdate() IM_ASSERT(child_window->ChildId != 0); FocusWindow(parent_window); SetNavID(child_window->ChildId, 0); - g.NavIdIsAlive = false; + g.NavIdIsAlive = false; // -V1048: Reassigning with same value, we're being explicit here. if (g.NavDisableMouseHover) g.NavMousePosDirty = true; } @@ -8453,7 +8453,7 @@ static void ImGui::NavUpdate() { //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.NavInitResultId = 0; // -V1048: Reassigning with same value, we're being explicit here. g.NavDisableHighlight = false; } NavUpdateAnyRequestFlag(); From 97a8dc6514db70112678c4f1972ee65a6ab0281d Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Fri, 10 Jan 2020 17:37:54 +0200 Subject: [PATCH 02/11] CI: Added PVS-Studio static analysis on the continuous-integration server. --- .github/workflows/build.yml | 35 +++++++++++++++++++++++++++++++++++ docs/CHANGELOG.txt | 1 + imgui.cpp | 6 ++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 265c400d..856e29f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -265,3 +265,38 @@ jobs: run: | source emsdk-master/emsdk_env.sh make -C examples/example_emscripten + + Static-Analysis: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Install Dependencies + env: + PVS_STUDIO_LICENSE: ${{ secrets.PVS_STUDIO_LICENSE }} + run: | + if [[ "$PVS_STUDIO_LICENSE" != "" ]]; + then + echo "$PVS_STUDIO_LICENSE" > pvs-studio.lic + wget -q https://files.viva64.com/etc/pubkey.txt + sudo apt-key add pubkey.txt + sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.viva64.com/etc/viva64.list + sudo apt-get update + sudo apt-get install -y pvs-studio + fi + + - name: PVS-Studio static analysis + run: | + if [[ ! -f pvs-studio.lic ]]; + then + echo "PVS Studio license is missing. No analysis will be performed." + echo "If you have a PVS Studio license please create a project secret named PVS_STUDIO_LICENSE with your license." + echo "You may use a free license. More information at https://www.viva64.com/en/b/0457/" + exit 0 + fi + cd examples/example_null + pvs-studio-analyzer trace -- make EXTRA_WARNINGS=1 + pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log + plog-converter -a 'GA:1,2;OP:1' -t errorfile -w pvs-studio.log diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2575da17..36d10732 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -77,6 +77,7 @@ Other Changes: - Backends: GLFW: Added support for the missing mouse cursors newly added in GLFW 3.4+. [@rokups] - Backends: SDL: Wayland: use SDL_GetMouseState (because there is no global mouse state available on Wayland). (#2800, #2802) [@NeroBurner] +- CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups] - Examples: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might automatically use it). (#2919, #2798) diff --git a/imgui.cpp b/imgui.cpp index f659123e..ed6da44d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8363,7 +8363,8 @@ static void ImGui::NavUpdate() IM_ASSERT(child_window->ChildId != 0); FocusWindow(parent_window); SetNavID(child_window->ChildId, 0); - g.NavIdIsAlive = false; // -V1048: Reassigning with same value, we're being explicit here. + // Reassigning with same value, we're being explicit here. + g.NavIdIsAlive = false; // -V1048 if (g.NavDisableMouseHover) g.NavMousePosDirty = true; } @@ -8453,7 +8454,8 @@ static void ImGui::NavUpdate() { //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; // -V1048: Reassigning with same value, we're being explicit here. + // Reassigning with same value, we're being explicit here. + g.NavInitResultId = 0; // -V1048 g.NavDisableHighlight = false; } NavUpdateAnyRequestFlag(); From f03c00bc89c4ba9b45f4e216d943e1d890dfbac0 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Fri, 10 Jan 2020 19:36:26 +0200 Subject: [PATCH 03/11] Added imgui_single_file.h, We use this to validate compiling all *.cpp in same compilation unit. Removed Unity builds stuff from example_null/. CI builds a temporary .cpp file. --- .github/workflows/build.yml | 25 +++++++++++++++++++------ docs/CHANGELOG.txt | 5 ++++- examples/example_null/Makefile | 9 ++------- examples/example_null/unity_build.cpp | 6 ------ misc/single_file/imgui_single_file.h | 17 +++++++++++++++++ 5 files changed, 42 insertions(+), 20 deletions(-) delete mode 100644 examples/example_null/unity_build.cpp create mode 100644 misc/single_file/imgui_single_file.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 856e29f5..04f8f6dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,8 +44,13 @@ jobs: - name: Build example_null (extra warnings) run: mingw32-make -C examples/example_null EXTRA_WARNINGS=1 - - name: Build example_null (unity build) - run: mingw32-make -C examples/example_null UNITY_BUILD=1 + - name: Build example_null (single file build) + shell: bash + run: | + echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp + echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp + echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp + g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp - name: Build Win32 example_glfw_opengl2 shell: cmd @@ -176,8 +181,12 @@ jobs: make -C examples/example_null clean CXXFLAGS="$CXXFLAGS -m64" CXX=clang++ make -C examples/example_null EXTRA_WARNINGS=1 - - name: Build example_null (unity build) - run: make -C examples/example_null UNITY_BUILD=1 + - name: Build example_null (single file build) + run: | + echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp + echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp + echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp + g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp - name: Build example_glfw_opengl2 run: make -C examples/example_glfw_opengl2 @@ -208,8 +217,12 @@ jobs: - name: Build example_null (extra warnings) run: make -C examples/example_null EXTRA_WARNINGS=1 - - name: Build example_null (unity build) - run: make -C examples/example_null UNITY_BUILD=1 + - name: Build example_null (single file build) + run: | + echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp + echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp + echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp + clang++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp - name: Build example_glfw_opengl2 run: make -C examples/example_glfw_opengl2 diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 36d10732..5f6d16d6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,11 +68,14 @@ Other Changes: - ColorEdit: In HSV display of a RGB stored value, attempt to locally preserve Saturation when Value==0.0 (similar to changes done in 1.73 for Hue). Removed Hue editing lock since those improvements in 1.73 makes them unnecessary. (#2722, #2770). [@rokups] -- Misc: Added ImGuiMouseCursor_NotAllowed enum so it can be used by more shared widgets. [@rokups] - ImDrawList: Add AddNgon(), AddNgonFilled() API with a guarantee on the explicit segment count. In the current branch they are essentially the same as AddCircle(), AddCircleFilled() but as we will rework the circle rendering functions to use textures and automatic segment count selection, those new api can fill a gap. [@ShironekoBen] +- Misc: Added ImGuiMouseCursor_NotAllowed enum so it can be used by more shared widgets. [@rokups] +- Misc: Added misc/single_file/imgui_single_file.h, We use this to validate compiling all *.cpp + files in a same compilation unit. Actual users of that technique (also called "Unity builds") + can generally provide this themselves, so we don't really recommend you use this. [@rokups] - Backends: GLFW, SDL, Win32, OSX, Allegro: Added support for ImGuiMouseCursor_NotAllowed. [@rokups] - Backends: GLFW: Added support for the missing mouse cursors newly added in GLFW 3.4+. [@rokups] - Backends: SDL: Wayland: use SDL_GetMouseState (because there is no global mouse state available diff --git a/examples/example_null/Makefile b/examples/example_null/Makefile index 3930eb27..7d39e824 100644 --- a/examples/example_null/Makefile +++ b/examples/example_null/Makefile @@ -5,13 +5,8 @@ EXE = example_null EXTRA_WARNINGS ?= 0 -UNITY_BUILD ?= 0 -ifeq ($(UNITY_BUILD), 1) - SOURCES = unity_build.cpp -else - SOURCES = main.cpp - SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp -endif +SOURCES = main.cpp +SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) diff --git a/examples/example_null/unity_build.cpp b/examples/example_null/unity_build.cpp deleted file mode 100644 index c6040016..00000000 --- a/examples/example_null/unity_build.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// Unity build test - build this example as a single compilation unit. -#include "main.cpp" -#include "../../imgui.cpp" -#include "../../imgui_demo.cpp" -#include "../../imgui_draw.cpp" -#include "../../imgui_widgets.cpp" diff --git a/misc/single_file/imgui_single_file.h b/misc/single_file/imgui_single_file.h new file mode 100644 index 00000000..a556931c --- /dev/null +++ b/misc/single_file/imgui_single_file.h @@ -0,0 +1,17 @@ +// imgui_single_file.h +// We use this to validate compiling all *.cpp files in a same compilation unit. +// Users of that technique (also called "Unity builds") can generally provide this themselves, +// so we don't really recommend you use this in your projects. + +// Do this: +// #define IMGUI_IMPLEMENTATION +// Before you include this file in *one* C++ file to create the implementation. +// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit. +#include "../../imgui.h" + +#ifdef IMGUI_IMPLEMENTATION +#include "../../imgui.cpp" +#include "../../imgui_demo.cpp" +#include "../../imgui_draw.cpp" +#include "../../imgui_widgets.cpp" +#endif From 4b3c5ff5f158de53c67d966b6f65c03bfca2c23f Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 11 Jan 2020 15:35:39 +0100 Subject: [PATCH 04/11] Comments + minor moving --- imgui_demo.cpp | 14 +++++++------- imgui_internal.h | 18 +++++++++--------- misc/README.txt | 6 ++++++ 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1f0a1b19..b0e0d347 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7,11 +7,11 @@ // your game/app! Removing this file from your project is hindering access to documentation for everyone in your team, // likely leading you to poorer usage of the library. // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow(). -// If you want to link core Dear ImGui in your shipped builds but want an easy guarantee that the demo will not be linked, +// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be linked, // you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty. // In other situation, whenever you have Dear ImGui available you probably want this to be available for reference. // Thank you, -// -Your beloved friend, imgui_demo.cpp (that you won't delete) +// -Your beloved friend, imgui_demo.cpp (which you won't delete) // Message to beginner C/C++ programmers about the meaning of the 'static' keyword: // In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is @@ -21,13 +21,13 @@ // 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. -// The Demo code is this file is designed to be easy to copy-and-paste in into your application! +// The Demo code in this file is designed to be easy to copy-and-paste in into your application! // Because of this: // - We never omit the ImGui:: namespace when calling functions, even though most of our code is already in the same namespace. // - We try to declare static variables in the local scope, as close as possible to the code using them. -// - We never use any of the helpers/facilities used internally by dear imgui, unless it has been exposed in the public API (imgui.h). -// - We never use maths operators on ImVec2/ImVec4. For other imgui sources files, they are provided by imgui_internal.h w/ IMGUI_DEFINE_MATH_OPERATORS, -// for your own sources file they are optional and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h. +// - We never use any of the helpers/facilities used internally by Dear ImGui, unless it has been exposed in the public API (imgui.h). +// - We never use maths operators on ImVec2/ImVec4. For other of our sources files, they are provided by imgui_internal.h w/ IMGUI_DEFINE_MATH_OPERATORS. +// For your own sources file they are optional and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h. // Because we don't want to assume anything about your support of maths operators, we don't use them in imgui_demo.cpp. /* @@ -97,7 +97,7 @@ Index of this file: #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. +// Play it nice with Windows users (Update: since 2018-05, Notepad finally appears to support Unix-style carriage returns!) #ifdef _WIN32 #define IM_NEWLINE "\r\n" #else diff --git a/imgui_internal.h b/imgui_internal.h index 29864f82..96ff585f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -920,7 +920,7 @@ struct ImGuiNextWindowData 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; } + inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } // Also cleared by ItemAdd() }; enum ImGuiNextItemDataFlags_ @@ -1035,7 +1035,7 @@ struct ImGuiContext ImVectorOpenPopupStack; // Which popups are open (persistent) ImVectorBeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) - // Navigation data (for gamepad/keyboard) + // Gamepad/keyboard Navigation ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiID NavId; // Focused item for navigation ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem() @@ -1076,7 +1076,7 @@ struct ImGuiContext 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) - // Tabbing system (older than Nav, active even if Nav is disabled. FIXME-NAV: This needs a redesign!) + // Legacy Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) ImGuiWindow* FocusRequestCurrWindow; // ImGuiWindow* FocusRequestNextWindow; // int FocusRequestCurrCounterAll; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch) @@ -1085,6 +1085,10 @@ struct ImGuiContext int FocusRequestNextCounterTab; // " bool FocusTabPressed; // + // Range-Select/Multi-Select + // [This is unused in this branch, but left here to facilitate merging/syncing multiple branches] + ImGuiID MultiSelectScopeId; + // Render ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user ImDrawDataBuilder DrawDataBuilder; @@ -1133,10 +1137,6 @@ struct ImGuiContext int TooltipOverrideCount; ImVector PrivateClipboard; // If no custom clipboard handler is defined - // Range-Select/Multi-Select - // [This is unused in this branch, but left here to facilitate merging/syncing multiple branches] - ImGuiID MultiSelectScopeId; - // Platform support ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor ImVec2 PlatformImeLastPos; @@ -1247,6 +1247,8 @@ struct ImGuiContext FocusRequestNextCounterAll = FocusRequestNextCounterTab = INT_MAX; FocusTabPressed = false; + MultiSelectScopeId = 0; + DimBgRatio = 0.0f; BackgroundDrawList._OwnerName = "##Background"; // Give it a name for debugging ForegroundDrawList._OwnerName = "##Foreground"; // Give it a name for debugging @@ -1276,8 +1278,6 @@ struct ImGuiContext ScrollbarClickDeltaToGrabCenter = 0.0f; TooltipOverrideCount = 0; - MultiSelectScopeId = 0; - PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX); SettingsLoaded = false; diff --git a/misc/README.txt b/misc/README.txt index be3af5ae..86900089 100644 --- a/misc/README.txt +++ b/misc/README.txt @@ -16,3 +16,9 @@ misc/natvis/ Natvis file to describe dear imgui types in the Visual Studio debugger. With this, types like ImVector<> will be displayed nicely in the debugger. You can include this file a Visual Studio project file, or install it in Visual Studio folder. + +misc/single_file/ + Single-file header stub. + We use this to validate compiling all *.cpp files in a same compilation unit. + Users of that technique (also called "Unity builds") can generally provide this themselves, + so we don't really recommend you use this in your projects. From ff5299e0e030b9b769ff3b069a924001c6a84feb Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 12 Jan 2020 21:51:40 +0100 Subject: [PATCH 05/11] Docs: FAQ, Comments. --- docs/CHANGELOG.txt | 32 +++++++++++++ docs/FAQ.md | 107 +++++++++++++++++++++++--------------------- examples/README.txt | 2 + imgui.cpp | 59 ++++++++++++------------ imgui.h | 18 ++++++-- imgui_demo.cpp | 7 +++ 6 files changed, 139 insertions(+), 86 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5f6d16d6..cf9c1327 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,8 @@ Other Changes: VERSION 1.74 (Released 2019-11-25) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.74 + 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 @@ -166,6 +168,8 @@ Other Changes: VERSION 1.73 (Released 2019-09-24) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.73 + Other Changes: - Nav, Scrolling: Added support for Home/End key. (#787) @@ -226,6 +230,8 @@ Other Changes: VERSION 1.72b (Released 2019-07-31) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.72b + Other Changes: - Nav, Scrolling: Fixed programmatic scroll leading to a slightly incorrect scroll offset when @@ -241,6 +247,8 @@ Other Changes: VERSION 1.72 (Released 2019-07-27) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.72 + Breaking Changes: - Removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): - ImGuiCol_Column*, ImGuiSetCond_* enums. @@ -322,6 +330,8 @@ Other Changes: VERSION 1.71 (Released 2019-06-12) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.71 + Breaking Changes: - IO: changed AddInputCharacter(unsigned short c) signature to AddInputCharacter(unsigned int c). - Renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete). @@ -402,6 +412,8 @@ Other Changes: VERSION 1.70 (Released 2019-05-06) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.70 + Breaking Changes: - ImDrawList: Improved algorithm for mitre joints on thick lines, preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, @@ -489,6 +501,8 @@ Other Changes: VERSION 1.69 (Released 2019-03-13) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.69 + Breaking Changes: - Renamed ColorEdit/ColorPicker's ImGuiColorEditFlags_RGB/_HSV/_HEX flags to respectively @@ -565,6 +579,8 @@ Other Changes: VERSION 1.68 (Released 2019-02-19) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.68 + Breaking Changes: - Removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already). @@ -633,6 +649,8 @@ Other Changes: VERSION 1.67 (Released 2019-01-14) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.67 + Breaking Changes: - Made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable @@ -696,6 +714,8 @@ Other Changes: VERSION 1.66b (Released 2018-12-01) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.66b + Other Changes: - Fixed a text rendering/clipping bug introduced in 1.66 (on 2018-10-12, commit ede3a3b9) that affect single ImDrawList::AddText() @@ -713,6 +733,8 @@ Other Changes: VERSION 1.66 (Released 2018-11-22) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.66 + Breaking Changes: - Renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete). @@ -772,6 +794,8 @@ Other Changes: VERSION 1.65 (Released 2018-09-06) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.65 + Breaking Changes: - Renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and @@ -796,6 +820,8 @@ Other Changes: VERSION 1.64 (Released 2018-08-31) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.64 + Changes: - Moved README, CHANGELOG and TODO files to the docs/ folder. @@ -818,6 +844,8 @@ Changes: VERSION 1.63 (Released 2018-08-29) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.63 + Breaking Changes: - Style: Renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. @@ -910,6 +938,8 @@ Other Changes: VERSION 1.62 (Released 2018-06-22) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.62 + Breaking Changes: - TreeNodeEx(): The helper ImGuiTreeNodeFlags_CollapsingHeader flag now include ImGuiTreeNodeFlags_NoTreePushOnOpen. @@ -989,6 +1019,8 @@ Other Changes: VERSION 1.61 (Released 2018-05-14) ----------------------------------------------------------------------- +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.61 + Breaking Changes: - DragInt(): The default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally diff --git a/docs/FAQ.md b/docs/FAQ.md index 68b43f73..3216a524 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -12,21 +12,16 @@ or view this file with any Markdown viewer. | **Q&A: Basics** | :---------------------------------------------------------- | | [Where is the documentation?](#q-where-is-the-documentation) | +| [What is this library called?](#q-what-is-this-library-called) | | [Which version should I get?](#q-which-version-should-i-get) | -| [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) | -| [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 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 enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) | | [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-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) | +| **[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) | @@ -36,6 +31,11 @@ or view this file with any Markdown viewer. | [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: 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: Community** | | [How can I help?](#q-how-can-i-help) | @@ -50,61 +50,31 @@ or view this file with any Markdown viewer. - 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). - The [Wiki](https://github.com/ocornut/imgui/wiki) has many resources and links. - The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful. +- The [Issues](https://github.com/ocornut/imgui/issues) section can be searched for past questions and issues. - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. +- The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts. + +--- + +### Q. What is this library called? + +**This library is called Dear ImGui**. Please refer to it as Dear ImGui (not ImGui, not IMGUI). + +(The library misleadingly started its life in 2014 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 in December 2015 a fully qualified name "Dear ImGui" for this library. --- ### 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) +You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes: +- [Docking 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 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) @@ -365,7 +335,7 @@ 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. +Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understand how the ImDrawList are generated. --- @@ -534,6 +504,41 @@ the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft ##### [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: Community ### Q: How can I help? diff --git a/examples/README.txt b/examples/README.txt index f52c90bc..a2655da6 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -35,6 +35,8 @@ You can find binaries of some of those example applications at: MISC COMMENTS AND SUGGESTIONS --------------------------------------- + - Read FAQ at http://dearimgui.org/faq + - Please read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. Please read the comments and instruction at the top of each file. diff --git a/imgui.cpp b/imgui.cpp index ed6da44d..c9ca32a3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,12 +1,19 @@ // dear imgui, v1.75 WIP // (main code and documentation) -// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. -// 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://github.com/ocornut/imgui/wiki -// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2847 +// Help: +// - Read FAQ at http://dearimgui.org/faq +// - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. +// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. All applications in examples/ are doing that. + +// Resources: +// - FAQ http://dearimgui.org/faq +// - Homepage & latest https://github.com/ocornut/imgui +// - Releases & changelog https://github.com/ocornut/imgui/releases +// - Gallery https://github.com/ocornut/imgui/issues/2847 (please post your screenshots/video there!) +// - Glossary https://github.com/ocornut/imgui/wiki/Glossary +// - Wiki https://github.com/ocornut/imgui/wiki +// - Issues & support https://github.com/ocornut/imgui/issues // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). @@ -155,8 +162,9 @@ CODE GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE --------------------------------------------------------------- - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library. + - In the majority of cases you should be able to use unmodified back-ends files available in the examples/ folder. - Add the Dear ImGui source files to your projects or using your preferred build system. - It is recommended you build and statically link the .cpp files as part of your project and not as shared library (DLL). + It is recommended you build and statically link the .cpp files as part of your project and NOT as shared library (DLL). - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating Dear ImGui types with your own maths types. - 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. @@ -176,7 +184,7 @@ CODE // TODO: Fill optional fields of the io structure later. // TODO: Load TTF/OTF fonts if you don't want to use the default font. - // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32 and imgui_impl_dx11) + // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32.cpp and imgui_impl_dx11.cpp) ImGui_ImplWin32_Init(hwnd); ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); @@ -597,37 +605,17 @@ CODE - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. + Q: What is this library called? Q: Which version should I get? - Q: Why the names "Dear ImGui" vs "ImGui"? >> This library is called "Dear ImGui", please don't call it "ImGui" :) >> See https://www.dearimgui.org/faq - Q&A: Concerns - ============= - - Q: Who uses 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)? - >> See https://www.dearimgui.org/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) { ... } ) - - 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 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 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.) + A: You should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags! + >> See https://www.dearimgui.org/faq for fully detailed answer. You really want to read this. Q. How can I enable keyboard controls? Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) @@ -771,6 +759,15 @@ CODE Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? >> See https://www.dearimgui.org/faq and docs/FONTS.txt + Q&A: Concerns + ============= + + Q: Who uses 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)? + >> See https://www.dearimgui.org/faq + Q&A: Community ============== diff --git a/imgui.h b/imgui.h index 6ed2fb5b..57d0511c 100644 --- a/imgui.h +++ b/imgui.h @@ -1,10 +1,20 @@ // dear imgui, v1.75 WIP // (headers) -// See imgui.cpp file for documentation. -// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. -// Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. -// Get latest version at https://github.com/ocornut/imgui +// Help: +// - Read FAQ at http://dearimgui.org/faq +// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. +// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. All applications in examples/ are doing that. +// Read imgui.cpp for more details, documentation and comments. + +// Resources: +// - FAQ http://dearimgui.org/faq +// - Homepage & latest https://github.com/ocornut/imgui +// - Releases & changelog https://github.com/ocornut/imgui/releases +// - Gallery https://github.com/ocornut/imgui/issues/2847 (please post your screenshots/video there!) +// - Glossary https://github.com/ocornut/imgui/wiki/Glossary +// - Wiki https://github.com/ocornut/imgui/wiki +// - Issues & support https://github.com/ocornut/imgui/issues /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b0e0d347..5ccebef2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,6 +1,13 @@ // dear imgui, v1.75 WIP // (demo code) +// Help: +// - Read FAQ at http://dearimgui.org/faq +// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. +// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. All applications in examples/ are doing that. +// Read imgui.cpp for more details, documentation and comments. +// Get latest version at https://github.com/ocornut/imgui + // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: // Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other coders // will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of From f56962cb9a371d8b124a145cee8e20d74da175f4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 13 Jan 2020 14:09:42 +0100 Subject: [PATCH 06/11] ColorEdit: "Copy As" context-menu tool shows hex values with a '#' prefix instead of '0x' + both with/without alpha when available. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cf9c1327..782f5be2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,8 @@ Other Changes: - ColorEdit: In HSV display of a RGB stored value, attempt to locally preserve Saturation when Value==0.0 (similar to changes done in 1.73 for Hue). Removed Hue editing lock since those improvements in 1.73 makes them unnecessary. (#2722, #2770). [@rokups] +- ColorEdit: "Copy As" context-menu tool shows hex values with a '#' prefix instead of '0x'. +- ColorEdit: "Copy As" content-menu tool shows hex values both with/without alpha when available. - ImDrawList: Add AddNgon(), AddNgonFilled() API with a guarantee on the explicit segment count. In the current branch they are essentially the same as AddCircle(), AddCircleFilled() but as we will rework the circle rendering functions to use textures and automatic segment count diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c7d142cb..4f3c6fa7 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5022,12 +5022,15 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca); if (Selectable(buf)) SetClipboardText(buf); - if (flags & ImGuiColorEditFlags_NoAlpha) - ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X", cr, cg, cb); - else - ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X%02X", cr, cg, cb, ca); + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb); if (Selectable(buf)) SetClipboardText(buf); + if (!(flags & ImGuiColorEditFlags_NoAlpha)) + { + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca); + if (Selectable(buf)) + SetClipboardText(buf); + } EndPopup(); } From 52334ad8df3325d01a7597c4306d8b4cc8016a4f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 13 Jan 2020 15:04:28 +0100 Subject: [PATCH 07/11] Internals: Minor ordering/comments of ImGuiWindowTempData. --- imgui.cpp | 2 +- imgui_internal.h | 37 +++++++++++++++++++++++-------------- imgui_widgets.cpp | 6 +++--- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c9ca32a3..8e6527a2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5859,7 +5859,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.TreeMayJumpToParentOnPopMask = 0x00; + window->DC.TreeJumpToParentOnPopMask = 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 96ff585f..4e5b35bc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1310,6 +1310,7 @@ 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 { + // Layout ImVec2 CursorPos; // Current emitting position, in absolute coordinates. ImVec2 CursorPosPrevLine; ImVec2 CursorStartPos; // Initial position after Begin(), generally ~ window position + WindowPadding. @@ -1318,27 +1319,38 @@ struct IMGUI_API ImGuiWindowTempData ImVec2 PrevLineSize; 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; // Current tree depth. - ImU32 TreeMayJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. + ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) + ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. + ImVec1 GroupOffset; + + // Last item status 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) + + // Keyboard/Gamepad navigation 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) int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame) bool NavHideHighlightOneFrame; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) + + // Miscellaneous 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. + int TreeDepth; // Current tree depth. + ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. ImVector ChildWindows; ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) + ImGuiColumns* CurrentColumns; // Current columns set 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) int FocusCounterTab; // (same, but only count widgets which you can Tab through) + // Local parameters stacks // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default] float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window @@ -1349,29 +1361,31 @@ struct IMGUI_API ImGuiWindowTempData ImVectorGroupStack; short StackSizesBackup[6]; // Store size of various stacks for asserting - ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) - ImVec1 GroupOffset; - ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - ImGuiColumns* CurrentColumns; // Current columns set - ImGuiWindowTempData() { CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f); CurrLineSize = PrevLineSize = ImVec2(0.0f, 0.0f); CurrLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; - TreeDepth = 0; - TreeMayJumpToParentOnPopMask = 0x00; + Indent = ImVec1(0.0f); + ColumnsOffset = ImVec1(0.0f); + GroupOffset = ImVec1(0.0f); + LastItemId = 0; LastItemStatusFlags = 0; LastItemRect = LastItemDisplayRect = ImRect(); + NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; NavLayerCurrent = ImGuiNavLayer_Main; NavLayerCurrentMask = (1 << ImGuiNavLayer_Main); NavHideHighlightOneFrame = false; NavHasScroll = false; + MenuBarAppending = false; MenuBarOffset = ImVec2(0.0f, 0.0f); + TreeDepth = 0; + TreeJumpToParentOnPopMask = 0x00; StateStorage = NULL; + CurrentColumns = NULL; LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical; FocusCounterAll = FocusCounterTab = -1; @@ -1379,11 +1393,6 @@ struct IMGUI_API ImGuiWindowTempData ItemWidth = 0.0f; TextWrapPos = -1.0f; memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); - - Indent = ImVec1(0.0f); - GroupOffset = ImVec1(0.0f); - ColumnsOffset = ImVec1(0.0f); - CurrentColumns = NULL; } }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4f3c6fa7..3c0a5d8e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5269,7 +5269,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.TreeMayJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); + window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); bool item_add = ItemAdd(interact_bb, id); window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; @@ -5442,12 +5442,12 @@ void ImGui::TreePop() // 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.TreeMayJumpToParentOnPopMask & tree_depth_mask)) + if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask)) { SetNavID(window->IDStack.back(), g.NavLayer); NavMoveRequestCancel(); } - window->DC.TreeMayJumpToParentOnPopMask &= tree_depth_mask - 1; + window->DC.TreeJumpToParentOnPopMask &= 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 02c2d18aa3be3be2a7762a90c3c6d275e7ea51c3 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 13 Jan 2020 15:21:37 +0100 Subject: [PATCH 08/11] Internals: Renaming and marking of legacy focus/tabbing system --- imgui.cpp | 40 ++++++++++++++++++++-------------------- imgui_internal.h | 20 ++++++++++---------- imgui_widgets.cpp | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8e6527a2..8146459e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3080,24 +3080,24 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // Increment counters const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; - window->DC.FocusCounterAll++; + window->DC.FocusCounterRegular++; if (is_tab_stop) - window->DC.FocusCounterTab++; + window->DC.FocusCounterTabStop++; // 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 && !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. + g.FocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (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. } // Handle focus requests if (g.FocusRequestCurrWindow == window) { - if (window->DC.FocusCounterAll == g.FocusRequestCurrCounterAll) + if (window->DC.FocusCounterRegular == g.FocusRequestCurrCounterRegular) return true; - if (is_tab_stop && window->DC.FocusCounterTab == g.FocusRequestCurrCounterTab) + if (is_tab_stop && window->DC.FocusCounterTabStop == g.FocusRequestCurrCounterTabStop) { g.NavJustTabbedId = id; return true; @@ -3113,8 +3113,8 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id) void ImGui::FocusableItemUnregister(ImGuiWindow* window) { - window->DC.FocusCounterAll--; - window->DC.FocusCounterTab--; + window->DC.FocusCounterRegular--; + window->DC.FocusCounterTabStop--; } float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) @@ -3767,26 +3767,26 @@ void ImGui::NewFrame() // Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also // manipulate the Next fields even, even though they will be turned into Curr fields by the code below. g.FocusRequestNextWindow = g.NavWindow; - g.FocusRequestNextCounterAll = INT_MAX; + g.FocusRequestNextCounterRegular = INT_MAX; if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) - g.FocusRequestNextCounterTab = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); + g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); else - g.FocusRequestNextCounterTab = g.IO.KeyShift ? -1 : 0; + g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0; } // Turn queued focus request into current one g.FocusRequestCurrWindow = NULL; - g.FocusRequestCurrCounterAll = g.FocusRequestCurrCounterTab = INT_MAX; + g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX; if (g.FocusRequestNextWindow != NULL) { ImGuiWindow* window = g.FocusRequestNextWindow; g.FocusRequestCurrWindow = window; - if (g.FocusRequestNextCounterAll != INT_MAX && window->DC.FocusCounterAll != -1) - g.FocusRequestCurrCounterAll = ImModPositive(g.FocusRequestNextCounterAll, window->DC.FocusCounterAll + 1); - if (g.FocusRequestNextCounterTab != INT_MAX && window->DC.FocusCounterTab != -1) - g.FocusRequestCurrCounterTab = ImModPositive(g.FocusRequestNextCounterTab, window->DC.FocusCounterTab + 1); + if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1) + g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1); + if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1) + g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1); g.FocusRequestNextWindow = NULL; - g.FocusRequestNextCounterAll = g.FocusRequestNextCounterTab = INT_MAX; + g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX; } g.NavIdTabCounter = INT_MAX; @@ -5850,7 +5850,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.ChildWindows.resize(0); window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; - window->DC.FocusCounterAll = window->DC.FocusCounterTab = -1; + window->DC.FocusCounterRegular = window->DC.FocusCounterTabStop = -1; window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled @@ -6904,8 +6904,8 @@ void ImGui::SetKeyboardFocusHere(int offset) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; g.FocusRequestNextWindow = window; - g.FocusRequestNextCounterAll = window->DC.FocusCounterAll + 1 + offset; - g.FocusRequestNextCounterTab = INT_MAX; + g.FocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset; + g.FocusRequestNextCounterTabStop = INT_MAX; } void ImGui::SetItemDefaultFocus() @@ -8059,7 +8059,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. g.NavLayer = window->DC.NavLayerCurrent; g.NavIdIsAlive = true; - g.NavIdTabCounter = window->DC.FocusCounterTab; + g.NavIdTabCounter = window->DC.FocusCounterTabStop; window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) } } diff --git a/imgui_internal.h b/imgui_internal.h index 4e5b35bc..50565382 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1076,13 +1076,13 @@ struct ImGuiContext 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) - // Legacy Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) + // Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) ImGuiWindow* FocusRequestCurrWindow; // ImGuiWindow* FocusRequestNextWindow; // - int FocusRequestCurrCounterAll; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch) - int FocusRequestCurrCounterTab; // Tab item being requested for focus, stored as an index - int FocusRequestNextCounterAll; // Stored for next frame - int FocusRequestNextCounterTab; // " + int FocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch) + int FocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index + int FocusRequestNextCounterRegular; // Stored for next frame + int FocusRequestNextCounterTabStop; // " bool FocusTabPressed; // // Range-Select/Multi-Select @@ -1243,8 +1243,8 @@ struct ImGuiContext NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; FocusRequestCurrWindow = FocusRequestNextWindow = NULL; - FocusRequestCurrCounterAll = FocusRequestCurrCounterTab = INT_MAX; - FocusRequestNextCounterAll = FocusRequestNextCounterTab = INT_MAX; + FocusRequestCurrCounterRegular = FocusRequestCurrCounterTabStop = INT_MAX; + FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX; FocusTabPressed = false; MultiSelectScopeId = 0; @@ -1347,8 +1347,8 @@ struct IMGUI_API ImGuiWindowTempData ImGuiColumns* CurrentColumns; // Current columns set 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) - int FocusCounterTab; // (same, but only count widgets which you can Tab through) + int FocusCounterRegular; // (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign) + int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through. // Local parameters stacks // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. @@ -1387,7 +1387,7 @@ struct IMGUI_API ImGuiWindowTempData StateStorage = NULL; CurrentColumns = NULL; LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical; - FocusCounterAll = FocusCounterTab = -1; + FocusCounterRegular = FocusCounterTabStop = -1; ItemFlags = ImGuiItemFlags_Default_; ItemWidth = 0.0f; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3c0a5d8e..5453d84c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3458,7 +3458,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ state = &g.InputTextState; const bool focus_requested = FocusableItemRegister(window, id); - const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterAll == window->DC.FocusCounterAll); + const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterRegular == window->DC.FocusCounterRegular); const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; const bool user_clicked = hovered && io.MouseClicked[0]; From e2eb0b4bc48b7644e09fb2ce9d569255a3553e93 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 13 Jan 2020 15:36:24 +0100 Subject: [PATCH 09/11] Internals: Begin tries to setup WindowTemp/DC members in same order as their declaration. Readme: remove Coverity banner (PVS is better) --- docs/README.md | 1 - imgui.cpp | 23 ++++++++++++++--------- imgui_internal.h | 2 +- imgui_widgets.cpp | 10 +++++----- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/README.md b/docs/README.md index ce4e5bc5..97b7812c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,6 @@ dear 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.) diff --git a/imgui.cpp b/imgui.cpp index 8146459e..7fcaea29 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5533,8 +5533,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->WindowPadding = style.WindowPadding; if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); - window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); - window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; // Collapse window by double-clicking on title bar // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing @@ -5842,27 +5840,34 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; - window->DC.NavHideHighlightOneFrame = false; - window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); + + window->DC.NavLayerCurrent = ImGuiNavLayer_Main; + window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main); window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; window->DC.NavLayerActiveMaskNext = 0x00; + window->DC.NavHideHighlightOneFrame = false; + window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); + window->DC.MenuBarAppending = false; + window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); + window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; + window->DC.MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); + window->DC.TreeDepth = 0; + window->DC.TreeJumpToParentOnPopMask = 0x00; window->DC.ChildWindows.resize(0); + window->DC.StateStorage = &window->StateStorage; + window->DC.CurrentColumns = NULL; window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; window->DC.FocusCounterRegular = window->DC.FocusCounterTabStop = -1; + window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); - window->DC.CurrentColumns = NULL; - window->DC.TreeDepth = 0; - window->DC.TreeJumpToParentOnPopMask = 0x00; - window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); - window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags)) { diff --git a/imgui_internal.h b/imgui_internal.h index 50565382..d3cfabe7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1340,6 +1340,7 @@ struct IMGUI_API ImGuiWindowTempData // Miscellaneous 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. + ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement int TreeDepth; // Current tree depth. ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. ImVector ChildWindows; @@ -1460,7 +1461,6 @@ struct IMGUI_API ImGuiWindow 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) float ItemWidthDefault; - ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; ImVector ColumnsStorage; float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale() diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5453d84c..a6d1dfd2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6172,11 +6172,11 @@ bool ImGui::BeginMenu(const char* label, bool enabled) { // Menu inside a menu popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); - float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame + float w = window->DC.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); - RenderArrow(window->DrawList, pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); + RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); } const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); @@ -6320,17 +6320,17 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo else { ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); - float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame + float w = window->DC.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) { PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); + RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected) - RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + RenderCheckMark(pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); From 4f7bf7e96a83030000e76fdcd281fa1e2619115d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Jan 2020 14:58:32 +0100 Subject: [PATCH 10/11] Backends: Win32: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. (#2716) --- docs/CHANGELOG.txt | 4 ++++ examples/imgui_impl_win32.cpp | 21 +++++++++++++++------ examples/imgui_impl_win32.h | 8 ++++++-- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 782f5be2..ae128853 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -82,6 +82,10 @@ Other Changes: - Backends: GLFW: Added support for the missing mouse cursors newly added in GLFW 3.4+. [@rokups] - Backends: SDL: Wayland: use SDL_GetMouseState (because there is no global mouse state available on Wayland). (#2800, #2802) [@NeroBurner] +- Backends: Win32: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD to disable all + XInput using code, and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT to disable linking with XInput, + the later may be problematic if compiling with recent Windows SDK and you want your app to run + on Windows 7. You can instead try linking with Xinput9_1_0.lib instead. (#2716) - CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups] - Examples: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index ffe1e8bf..140e1e4b 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -13,11 +13,22 @@ #define WIN32_LEAN_AND_MEAN #endif #include -#include #include +// Using XInput library for gamepad (with recent Windows SDK this may leads to executables which won't run on Windows 7) +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD +#include +#else +#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT +#endif +#if defined(_MSC_VER) && !defined(IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT) +#pragma comment(lib, "xinput") +//#pragma comment(lib, "Xinput9_1_0") +#endif + // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). // 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. @@ -40,7 +51,7 @@ // 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. // Win32 Data -static HWND g_hWnd = 0; +static HWND g_hWnd = NULL; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; @@ -149,13 +160,10 @@ static void ImGui_ImplWin32_UpdateMousePos() io.MousePos = ImVec2((float)pos.x, (float)pos.y); } -#ifdef _MSC_VER -#pragma comment(lib, "xinput") -#endif - // Gamepad navigation mapping static void ImGui_ImplWin32_UpdateGamepads() { +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD ImGuiIO& io = ImGui::GetIO(); memset(io.NavInputs, 0, sizeof(io.NavInputs)); if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) @@ -198,6 +206,7 @@ static void ImGui_ImplWin32_UpdateGamepads() #undef MAP_BUTTON #undef MAP_ANALOG } +#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD } void ImGui_ImplWin32_NewFrame() diff --git a/examples/imgui_impl_win32.h b/examples/imgui_impl_win32.h index 76161860..93dc75a0 100644 --- a/examples/imgui_impl_win32.h +++ b/examples/imgui_impl_win32.h @@ -13,9 +13,13 @@ IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); +// Configuration: Disable gamepad support or linking with xinput.lib +//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD +//#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT + // Handler for Win32 messages, update mouse/keyboard data. // You may or not need this for your implementation, but it can serve as reference for handling inputs. // Intentionally commented out to avoid dragging dependencies on types. You can COPY this line into your .cpp code instead. -/* +#if 0 IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -*/ +#endif From 2ebe08be40da88eada47a8c2a5ba6f6c93e91acb Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Jan 2020 19:23:50 +0100 Subject: [PATCH 11/11] Focus, Nav: Merged bits from RangeSelect features to enable early manipulation of focus scope for styling purpose. FocusScopeId is tracked by nav scoring/request and stored in result. It's all rather WIP and we should reorganize the SetNavIDXXX functions fiasco at some point (soon?). Didn't separate FocusScope from SelectionScope for now, will re-investigate this later, this is the minimum commit to be able to do some styling. --- imgui.cpp | 51 ++++++++++++++++++++++++++++------------------- imgui_internal.h | 45 ++++++++++++++++++++--------------------- imgui_widgets.cpp | 8 ++++---- 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7fcaea29..c7e7a3c6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2752,19 +2752,21 @@ void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0; } -void ImGui::SetNavID(ImGuiID id, int nav_layer) +// FIXME-NAV: Refactor those functions into a single, more explicit one. +void ImGui::SetNavID(ImGuiID id, int nav_layer, int focus_scope_id) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow); IM_ASSERT(nav_layer == 0 || nav_layer == 1); g.NavId = id; + g.NavFocusScopeId = focus_scope_id; g.NavWindow->NavLastIds[nav_layer] = id; } -void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel) +void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; - SetNavID(id, nav_layer); + SetNavID(id, nav_layer, focus_scope_id); g.NavWindow->NavRectRel[nav_layer] = rect_rel; g.NavMousePosDirty = true; g.NavDisableHighlight = false; @@ -2809,13 +2811,15 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) ImGuiContext& g = *GImGui; IM_ASSERT(id != 0); - // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. + // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. + // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; if (g.NavWindow != window) g.NavInitRequest = false; - g.NavId = id; g.NavWindow = window; + g.NavId = id; g.NavLayer = nav_layer; + g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; window->NavLastIds[nav_layer] = id; if (window->DC.LastItemId == id) window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); @@ -5845,6 +5849,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main); window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; window->DC.NavLayerActiveMaskNext = 0x00; + window->DC.NavFocusScopeIdCurrent = 0; window->DC.NavHideHighlightOneFrame = false; window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); @@ -6047,6 +6052,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavMousePosDirty = true; g.NavInitRequest = false; g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId + g.NavFocusScopeId = 0; g.NavIdIsAlive = false; g.NavLayer = ImGuiNavLayer_Main; //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL); @@ -8039,21 +8045,22 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con #endif if (new_best) { - result->ID = id; - result->SelectScopeId = g.MultiSelectScopeId; result->Window = window; + result->ID = id; + result->FocusScopeId = window->DC.NavFocusScopeIdCurrent; result->RectRel = nav_bb_rel; } + // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. const float VISIBLE_RATIO = 0.70f; if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) if (NavScoreItem(&g.NavMoveResultLocalVisibleSet, nav_bb)) { result = &g.NavMoveResultLocalVisibleSet; - result->ID = id; - result->SelectScopeId = g.MultiSelectScopeId; result->Window = window; + result->ID = id; + result->FocusScopeId = window->DC.NavFocusScopeIdCurrent; result->RectRel = nav_bb_rel; } } @@ -8063,6 +8070,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con { g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. g.NavLayer = window->DC.NavLayerCurrent; + g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; g.NavIdIsAlive = true; g.NavIdTabCounter = window->DC.FocusCounterTabStop; window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) @@ -8153,10 +8161,11 @@ static void NavRestoreLayer(ImGuiNavLayer layer) g.NavLayer = layer; if (layer == 0) g.NavWindow = ImGui::NavRestoreLastChildNavWindow(g.NavWindow); - if (layer == 0 && g.NavWindow->NavLastIds[0] != 0) - ImGui::SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); + ImGuiWindow* window = g.NavWindow; + if (layer == 0 && window->NavLastIds[0] != 0) + ImGui::SetNavIDWithRectRel(window->NavLastIds[0], layer, 0, window->NavRectRel[0]); else - ImGui::NavInitWindow(g.NavWindow, true); + ImGui::NavInitWindow(window, true); } static inline void ImGui::NavUpdateAnyRequestFlag() @@ -8179,7 +8188,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) //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); + SetNavID(0, g.NavLayer, 0); g.NavInitRequest = true; g.NavInitRequestFromMove = false; g.NavInitResultId = 0; @@ -8189,6 +8198,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) else { g.NavId = window->NavLastIds[0]; + g.NavFocusScopeId = 0; } } @@ -8295,9 +8305,9 @@ static void ImGui::NavUpdate() // 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); + SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel); else - SetNavID(g.NavInitResultId, g.NavLayer); + SetNavID(g.NavInitResultId, g.NavLayer, 0); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; } g.NavInitRequest = false; @@ -8364,7 +8374,7 @@ static void ImGui::NavUpdate() ImGuiWindow* parent_window = g.NavWindow->ParentWindow; IM_ASSERT(child_window->ChildId != 0); FocusWindow(parent_window); - SetNavID(child_window->ChildId, 0); + SetNavID(child_window->ChildId, 0, 0); // Reassigning with same value, we're being explicit here. g.NavIdIsAlive = false; // -V1048 if (g.NavDisableMouseHover) @@ -8386,7 +8396,7 @@ static void ImGui::NavUpdate() // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) g.NavWindow->NavLastIds[0] = 0; - g.NavId = 0; + g.NavId = g.NavFocusScopeId = 0; } } @@ -8506,7 +8516,7 @@ static void ImGui::NavUpdate() float pad = window->CalcFontSize() * 0.5f; window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel); - g.NavId = 0; + g.NavId = g.NavFocusScopeId = 0; } g.NavMoveFromClampedRefRect = false; } @@ -8586,9 +8596,10 @@ static void ImGui::NavUpdateMoveResult() { // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId) g.NavJustMovedToId = result->ID; - g.NavJustMovedToMultiSelectScopeId = result->SelectScopeId; + g.NavJustMovedToFocusScopeId = result->FocusScopeId; + } - SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel); + SetNavIDWithRectRel(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel); g.NavMoveFromClampedRefRect = false; } diff --git a/imgui_internal.h b/imgui_internal.h index d3cfabe7..894519b2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -877,16 +877,16 @@ struct ImDrawDataBuilder struct ImGuiNavMoveResult { - ImGuiID ID; // Best candidate - ImGuiID SelectScopeId;// Best candidate window current selectable group ID - ImGuiWindow* Window; // Best candidate window - float DistBox; // Best candidate box distance to current NavId - float DistCenter; // Best candidate center distance to current NavId - float DistAxial; - ImRect RectRel; // Best candidate bounding box in window relative space + ImGuiWindow* Window; // Best candidate window + ImGuiID ID; // Best candidate ID + ImGuiID FocusScopeId; // Best candidate focus scope ID + float DistBox; // Best candidate box distance to current NavId + float DistCenter; // Best candidate center distance to current NavId + float DistAxial; + ImRect RectRel; // Best candidate bounding box in window relative space ImGuiNavMoveResult() { Clear(); } - void Clear() { ID = SelectScopeId = 0; Window = NULL; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); } + void Clear() { Window = NULL; ID = FocusScopeId = 0; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); } }; enum ImGuiNextWindowDataFlags_ @@ -920,7 +920,7 @@ struct ImGuiNextWindowData 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; } // Also cleared by ItemAdd() + inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } }; enum ImGuiNextItemDataFlags_ @@ -933,12 +933,13 @@ enum ImGuiNextItemDataFlags_ struct ImGuiNextItemData { ImGuiNextItemDataFlags Flags; - float Width; // Set by SetNextItemWidth(). - bool OpenVal; // Set by SetNextItemOpen() function. + float Width; // Set by SetNextItemWidth() + ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging) ImGuiCond OpenCond; + bool OpenVal; // Set by SetNextItemOpen() ImGuiNextItemData() { memset(this, 0, sizeof(*this)); } - inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } + inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()! }; //----------------------------------------------------------------------------- @@ -1038,13 +1039,15 @@ struct ImGuiContext // Gamepad/keyboard Navigation ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiID NavId; // Focused item for navigation + ImGuiID NavFocusScopeId; ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0 ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). - ImGuiID NavJustMovedToMultiSelectScopeId; // Just navigated to this select scope id (result of a successfully MoveRequest). + ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). + ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. 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. @@ -1085,10 +1088,6 @@ struct ImGuiContext int FocusRequestNextCounterTabStop; // " bool FocusTabPressed; // - // Range-Select/Multi-Select - // [This is unused in this branch, but left here to facilitate merging/syncing multiple branches] - ImGuiID MultiSelectScopeId; - // Render ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user ImDrawDataBuilder DrawDataBuilder; @@ -1218,8 +1217,8 @@ struct ImGuiContext LastActiveIdTimer = 0.0f; NavWindow = NULL; - NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; - NavJustTabbedId = NavJustMovedToId = NavJustMovedToMultiSelectScopeId = NavNextActivateId = 0; + NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; + NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavInputSource = ImGuiInputSource_None; NavScoringRectScreen = ImRect(); NavScoringCount = 0; @@ -1247,8 +1246,6 @@ struct ImGuiContext FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX; FocusTabPressed = false; - MultiSelectScopeId = 0; - DimBgRatio = 0.0f; BackgroundDrawList._OwnerName = "##Background"; // Give it a name for debugging ForegroundDrawList._OwnerName = "##Foreground"; // Give it a name for debugging @@ -1334,6 +1331,7 @@ struct IMGUI_API ImGuiWindowTempData int NavLayerCurrentMask; // = (1 << NavLayerCurrent) used by ItemAdd prior to clipping. int NavLayerActiveMask; // Which layer have been written to (result from previous frame) int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame) + ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending bool NavHideHighlightOneFrame; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) @@ -1378,6 +1376,7 @@ struct IMGUI_API ImGuiWindowTempData NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; NavLayerCurrent = ImGuiNavLayer_Main; NavLayerCurrentMask = (1 << ImGuiNavLayer_Main); + NavFocusScopeIdCurrent = 0; NavHideHighlightOneFrame = false; NavHasScroll = false; @@ -1701,8 +1700,8 @@ namespace ImGui IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); 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); + IMGUI_API void SetNavID(ImGuiID id, int nav_layer, int focus_scope_id); + IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel); // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a6d1dfd2..95483e2f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5312,9 +5312,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bool hovered, held; bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); + bool toggled = false; if (!is_leaf) { - bool toggled = false; if (pressed) { if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id)) @@ -5444,7 +5444,7 @@ void ImGui::TreePop() if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask)) { - SetNavID(window->IDStack.back(), g.NavLayer); + SetNavID(window->IDStack.back(), g.NavLayer, 0); NavMoveRequestCancel(); } window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1; @@ -5600,7 +5600,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { g.NavDisableHighlight = true; - SetNavID(id, window->DC.NavLayerCurrent); + SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent); } } if (pressed) @@ -6077,7 +6077,7 @@ void ImGui::EndMenuBar() const ImGuiNavLayer layer = ImGuiNavLayer_Menu; IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check FocusWindow(window); - SetNavIDWithRectRel(window->NavLastIds[layer], layer, window->NavRectRel[layer]); + SetNavIDWithRectRel(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); g.NavLayer = layer; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;