From c5027d4fa1efea339710ef316c321146a9977830 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 25 Oct 2017 20:55:15 +0200 Subject: [PATCH 1/4] Examples: Extra clarification for the 100th person who insist on using the OpenGL2 code in spite of existing documentation leaning against it. (#1394) --- examples/README.txt | 30 +++++++++++-------- examples/opengl2_example/imgui_impl_glfw.cpp | 10 ++++--- .../sdl_opengl2_example/imgui_impl_sdl.cpp | 8 +++-- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/examples/README.txt b/examples/README.txt index 2769c1bf..35490b5b 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -8,15 +8,16 @@ Third party languages and frameworks bindings: https://github.com/ocornut/imgui/ TL;DR; - Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase. - - To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one. - The other examples requires more boilerplate and are harder to read. - However, USE 'opengl3_example' in your application if you are using any modern OpenGL3+ calls. - Mixing old fixed pipeline OpenGL2 and programmable pipeline OpenGL3+ isn't well supported by some drivers. - If you are not sure, in doubt, use 'opengl3_example'. - If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files to your project and use them unmodified. - - If you have your own engine, you probably want to start from one of the OpenGL example and adapt it to - your engine, but you can read the other examples as well. + - To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one to read. + However, do NOT USE the 'opengl2_example' if your code is using any modern GL3+ calls. + Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated. + Read comments below for details. If you are not sure, in doubt, use 'opengl3_example'. + - If you have your own engine, you probably want to read a few of the examples first then adapt it to + your engine. Please note that if your engine is based on OpenGL/DirectX you can perfectly use the + existing rendering backends, don't feel forced to rewrite them with your own engine API, or you can + do that later when you already got things to work. ImGui is highly portable and only requires a few things to run: - Providing mouse/keyboard inputs @@ -45,12 +46,12 @@ Also note that some setup or GPU drivers may be causing extra lag (possibly by e leaving you with no option but sadness/anger (Intel GPU drivers were reported as such). opengl2_example/ + *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* GLFW + OpenGL example (old, fixed graphic pipeline). - This is only provided as a reference to learn how ImGui integration works, because it is easier to read. - However, if your code is using GL3+ context, using this may confuse your driver. Please use the GL3 example below. - (You might be able to use this code in a GL3/GL4 context but make sure you disable the programmable - pipeline by calling "glUseProgram(0)" before ImGui::Render. It appears that many librairies and drivers - are having issues mixing GL2 calls and newer GL3/GL4 calls. So it isn't recommended that you use that.) + This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. + If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything + more complicated, will require your code to reset every single OpenGL attributes to their initial state, + and might confuse your GPU driver. Prefer using opengl3_example. opengl3_example/ GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W). @@ -74,7 +75,12 @@ apple_example/ Synergy keyboard integration is rather hacky. sdl_opengl2_example/ + *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* SDL2 + OpenGL example (old fixed pipeline). + This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. + If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything + more complicated, will require your code to reset every single OpenGL attributes to their initial state, + and might confuse your GPU driver. Prefer using sdl_opengl3_example. sdl_opengl3_example/ SDL2 + OpenGL3 example. diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index 4aed20a6..643606db 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -1,10 +1,12 @@ // ImGui GLFW binding with OpenGL // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// If your context or own usage of OpenGL involve anything GL3/GL4, prefer using the code in opengl3_example. -// If you are not sure what that means, prefer using the code in opengl3_example. -// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render(). -// We cannot do that from GL2 code because the function doesn't exist. Mixing GL2 calls and GL3/GL4 calls is giving trouble to many librairies/drivers. +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. +// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything +// more complicated, will require your code to reset every single OpenGL attributes to their initial state, +// and might confuse your GPU driver. Prefer using opengl3_example. +// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 78ce4035..8f870eb6 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -1,8 +1,12 @@ // ImGui SDL2 binding with OpenGL // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// If your context or own usage of OpenGL involve anything GL3/GL4, prefer using the code in sdl_opengl3_example. -// If you are not sure what that means, prefer using the code in sdl_opengl3_example. +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. +// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything +// more complicated, will require your code to reset every single OpenGL attributes to their initial state, +// and might confuse your GPU driver. Prefer using sdl_opengl3_example. +// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). From a6ff14d66e66c167fbcbc01c4aea1a8361e3dc4e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 26 Oct 2017 16:12:53 +0200 Subject: [PATCH 2/4] Exposed IM_ARRAYSIZE() in imgui.h --- imgui.h | 6 ++++-- imgui_internal.h | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui.h b/imgui.h index c865d357..2f58e066 100644 --- a/imgui.h +++ b/imgui.h @@ -29,14 +29,16 @@ #define IM_ASSERT(_EXPR) assert(_EXPR) #endif +// Helpers // Some compilers support applying printf-style warnings to user functions. #if defined(__clang__) || defined(__GNUC__) -#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) -#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) +#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) +#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else #define IM_FMTARGS(FMT) #define IM_FMTLIST(FMT) #endif +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) #if defined(__clang__) #pragma clang diagnostic push diff --git a/imgui_internal.h b/imgui_internal.h index 24e48412..76a83beb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -79,9 +79,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointe // Helpers //----------------------------------------------------------------------------- -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_PI 3.14159265358979323846f -#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) +#define IM_PI 3.14159265358979323846f +#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) // Helpers: UTF-8 <> wchar IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count From c432fcf2bbaded0d126360e332361173358c0a79 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Oct 2017 12:01:52 +0200 Subject: [PATCH 3/4] Minor renaming. --- imgui.cpp | 34 +++++++++++++++++----------------- imgui_internal.h | 8 ++++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2d27a79e..65373204 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2328,29 +2328,29 @@ void ImGui::NewFrame() g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. - if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) + if (g.MovingWindowMoveId && g.MovingWindowMoveId == g.ActiveId) { - KeepAliveID(g.MovedWindowMoveId); - IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow); - IM_ASSERT(g.MovedWindow->MoveId == g.MovedWindowMoveId); + KeepAliveID(g.MovingWindowMoveId); + IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); + IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { - g.MovedWindow->RootWindow->PosFloat += g.IO.MouseDelta; + g.MovingWindow->RootWindow->PosFloat += g.IO.MouseDelta; if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) - MarkIniSettingsDirty(g.MovedWindow->RootWindow); - FocusWindow(g.MovedWindow); + MarkIniSettingsDirty(g.MovingWindow->RootWindow); + FocusWindow(g.MovingWindow); } else { ClearActiveID(); - g.MovedWindow = NULL; - g.MovedWindowMoveId = 0; + g.MovingWindow = NULL; + g.MovingWindowMoveId = 0; } } else { - g.MovedWindow = NULL; - g.MovedWindowMoveId = 0; + g.MovingWindow = NULL; + g.MovingWindowMoveId = 0; } // Delay saving settings so we don't spam disk too much @@ -2362,11 +2362,11 @@ void ImGui::NewFrame() } // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow - g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false); + g.HoveredWindow = g.MovingWindow ? g.MovingWindow : FindHoveredWindow(g.IO.MousePos, false); if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow)) g.HoveredRootWindow = g.HoveredWindow->RootWindow; else - g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true); + g.HoveredRootWindow = g.MovingWindow ? g.MovingWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true); if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) { @@ -2504,7 +2504,7 @@ void ImGui::Shutdown() g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; g.ActiveIdWindow = NULL; - g.MovedWindow = NULL; + g.MovingWindow = NULL; for (int i = 0; i < g.Settings.Size; i++) ImGui::MemFree(g.Settings[i].Name); g.Settings.clear(); @@ -2799,9 +2799,9 @@ void ImGui::EndFrame() FocusWindow(g.HoveredWindow); if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) { - g.MovedWindow = g.HoveredWindow; - g.MovedWindowMoveId = g.HoveredWindow->MoveId; - SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); + g.MovingWindow = g.HoveredWindow; + g.MovingWindowMoveId = g.MovingWindow->MoveId; + SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); } } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) diff --git a/imgui_internal.h b/imgui_internal.h index 76a83beb..f240b608 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -435,8 +435,8 @@ struct ImGuiContext bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; - ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. - ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId + ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window. + ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector Settings; // .ini Settings float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() @@ -527,8 +527,8 @@ struct ImGuiContext ActiveIdAllowOverlap = false; ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; - MovedWindow = NULL; - MovedWindowMoveId = 0; + MovingWindow = NULL; + MovingWindowMoveId = 0; SettingsDirtyTimer = 0.0f; SetNextWindowPosVal = ImVec2(0.0f, 0.0f); From d42f6bb6ccdbfb77f6fe9bf0d195542c2ea1664a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Oct 2017 15:52:45 +0200 Subject: [PATCH 4/4] Merged a bit of code from Navigation branch to ease further merging (InnerRect is currently not required in the Master branch) --- imgui.cpp | 18 ++++++++++++------ imgui_internal.h | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 65373204..4699576e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4613,17 +4613,23 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) */ } - // Inner clipping rectangle + // Inner rectangle and inner clipping rectangle // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); const float border_size = window->BorderSize; - // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + window->InnerRect.Min.x = title_bar_rect.Min.x; + window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight(); + window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x; + window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y; + //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); + + // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. ImRect clip_rect; - clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size); - clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size); + clip_rect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + border_size); + clip_rect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - border_size); PushClipRect(clip_rect.Min, clip_rect.Max, true); // Clear 'accessed' flag last thing diff --git a/imgui_internal.h b/imgui_internal.h index f240b608..39fc77f5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -714,6 +714,7 @@ struct IMGUI_API ImGuiWindow ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. + ImRect InnerRect; int LastFrameActive; float ItemWidthDefault; ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items